Перейти к основному содержимому
Модуль 8 · Урок 5 из 540/50 в курсе~14 min
Уроки модуля (5/5)

`кодировка/json`

encoding/json — это канонический пакет для сериализации структур Go в JSON и обратно. Знание его соглашений и ошибок сэкономит вам часы отладки API и файлов конфигурации.

Маршал и унмаршал

Две основные функции:

Go
data, err := json.Marshal(v)      // Go → []byte JSON
err = json.Unmarshal(data, &v)    // JSON → Go (pass a pointer!)
Go
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 сериализует только экспортированные поля (в верхнем регистре). Приватные поля игнорируются тихо:

Go
type U struct {
    Name string // exported → serialized
    age  int    // private → ignored
}

Структурные теги: управление именем и параметрами

Теги json:"..." управляют именем, пропусками и типами выходных данных:

Go
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 вместо загрузки всего в память:

Go
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:

Go
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.

Упражнения

Упражнение#go.m8.l5.e1
Попыток: 0Загрузка…

Сериализуйте структуру u в JSON с помощью json.Marshal и распечатайте результат в виде строки.

Загрузка редактора…

Решение доступно после 3 попыток

Упражнение#go.m8.l5.e2
Попыток: 0Загрузка…

Десериализуйте `{"Name":"Ada"}` в структуру U с помощью json.Unmarshal и распечатайте ее.

Загрузка редактора…

Решение доступно после 3 попыток

Quiz#go.m8.l5.e3
Готово

Является ли поле `name string` (строчными буквами) структуры, включенной в json.Marshal?

Go
type U struct {
  name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))
Варианты ответа