Свой вид значения в JSON в Go
Иногда стандартный вид поля в тексте
не подходит. Тогда на тип вешают методы
MarshalJSON и UnmarshalJSON
из пакета encoding/json, а не
склеивают строку вручную.
Метод сборки возвращает срез байт и ошибку; метод разбора принимает байты и ошибку. Внутри можно вызвать обычную сборку для строки или числа, лишь форма в тексте меняется.
Сделаем тип цвета, который в тексте остается строкой:
package main
import (
"encoding/json"
"fmt"
)
type Color string
func (c Color) MarshalJSON() ([]byte, error) {
return json.Marshal(string(c))
}
func (c *Color) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*c = Color(s)
return nil
}
type Swatch struct {
Name string `json:"name"`
Tone Color `json:"tone"`
}
func main() {
s := Swatch{Name: "sky", Tone: "blue"}
data, err := json.Marshal(s)
if err != nil {
fmt.Println("error")
return
}
fmt.Println(string(data))
}
Поле Tone записалось как строка
"blue", хотя в Go это отдельный
именованный тип. Разбор прочитает ту
же строку обратно в Color.
Проверим разбор текста с таким полем:
package main
import (
"encoding/json"
"fmt"
)
type Color string
func (c Color) MarshalJSON() ([]byte, error) {
return json.Marshal(string(c))
}
func (c *Color) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*c = Color(s)
return nil
}
type Swatch struct {
Tone Color `json:"tone"`
}
func main() {
text := []byte(`{"tone":"red"}`)
var s Swatch
err := json.Unmarshal(text, &s)
if err != nil {
fmt.Println("error")
return
}
fmt.Println(string(s.Tone))
}
Дан тип:
type Code string
func (c Code) MarshalJSON() ([]byte, error) {
return json.Marshal(string(c))
}
func (c *Code) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*c = Code(s)
return nil
}
Соберите текст для значения Code
"x1" и выведите байты как строку.
Дана строка:
text := []byte(`{"tone":"green"}`)
Используйте типы из урока, разберите
text в Swatch и выведите
тон.
Скажите, какой получатель нужен у метода разбора для поля указателя на свой тип.