Уроки модуля (5/5)
`кодировка/json`
encoding/json — это канонический пакет для сериализации структур Go в JSON и обратно. Знание его соглашений и ошибок сэкономит вам часы отладки API и файлов конфигурации.
Маршал и унмаршал
Две основные функции:
data, err := json.Marshal(v) // Go → []byte JSON
err = json.Unmarshal(data, &v) // JSON → Go (pass a pointer!)type User struct {
Name string
Email string
}
u := User{Name: "Ada", Email: "ada@example.com"}
b, _ := json.Marshal(u)
fmt.Println(string(b))
// {"Name":"Ada","Email":"ada@example.com"}
var back User
_ = json.Unmarshal(b, &back)Для вывода с отступом (удобочитаемым человеком) используйте json.MarshalIndent(v, "", " ").
Только экспортированные поля
json.Marshal сериализует только экспортированные поля (в верхнем регистре). Приватные поля игнорируются тихо:
type U struct {
Name string // exported → serialized
age int // private → ignored
}Структурные теги: управление именем и параметрами
Теги json:"..." управляют именем, пропусками и типами выходных данных:
type User struct {
Name string `json:"name"` // rename
Email string `json:"email,omitempty"` // omit if zero value
Private string `json:"-"` // never serialized
ID int `json:"id,string"` // number as string
}Наиболее используемые варианты:
,omitempty— опускает поле, если оно имеет нулевое значение (0, "", ноль, пустой срез/карта).,-— никогда не сериализуется/десериализуется.,string— переносит числа и логические значения в строки (полезно для идентификаторов JS).
Декодер/кодировщик потоков
При работе с io.Reader/io.Writer (тело HTTP, огромные файлы) используйте Decoder и Encoder вместо загрузки всего в память:
dec := json.NewDecoder(resp.Body)
var users []User
if err := dec.Decode(&users); err != nil {
return err
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
_ = enc.Encode(users)Decoder также поддерживает dec.Token() для потоковой передачи по частям и dec.DisallowUnknownFields() для отклонения JSON с неожиданными ключами (полезно для проверки ввода).
Общие карты и any
Если вы не знаете схему, десериализуйте в map[string]any:
var v map[string]any
_ = json.Unmarshal(data, &v)
fmt.Println(v["name"])Значения будут иметь динамические типы (string, float64 для чисел, []any, map[string]any, bool, nil).
Распространенные ошибки
- Забываем
&:json.Unmarshal(data, v)ничего не заполняет; вам нужен&v. - Декодирование структур с нулевыми полями: во избежание паники проверяйте
errПЕРЕД чтением полей. - Несовместимые типы: десериализация числа в строку или наоборот возвращает
*json.UnmarshalTypeError.
Упражнения
Сериализуйте структуру u в JSON с помощью json.Marshal и распечатайте результат в виде строки.
Решение доступно после 3 попыток
Десериализуйте `{"Name":"Ada"}` в структуру U с помощью json.Unmarshal и распечатайте ее.
Решение доступно после 3 попыток
Является ли поле `name string` (строчными буквами) структуры, включенной в json.Marshal?
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))