Работа с JSON в Go: парсинг и сериализация для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в работу с JSON в Go

JSON (JavaScript Object Notation) — это один из самых популярных форматов обмена данными в современных веб-приложениях и микросервисах. Благодаря своей простоте и читаемости, JSON стал стандартом для REST API, конфигурационных файлов и хранения структурированных данных.

Язык Go (Golang) предлагает встроенную мощную поддержку JSON через пакет encoding/json. Этот пакет позволяет легко преобразовывать Go-структуры в JSON (сериализация) и обратно (десериализация или парсинг).

В этой статье мы разберем основы работы с JSON в Go: от простых примеров до обработки сложных вложенных структур и ошибок. Материал ориентирован на начинающих разработчиков, которые уже знакомы с основами синтаксиса Go.

Сериализация: преобразование Go-структур в JSON

Сериализация (кодирование) — это процесс преобразования данных из внутреннего представления Go (структуры, срезы, карты) в строку JSON. В Go для этого используется функция json.Marshal().

Базовый пример сериализации

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string
    Age  int
    City string
}

func main() {
    person := Person{
        Name: "Иван Петров",
        Age:  30,
        City: "Москва",
    }

    jsonBytes, err := json.Marshal(person)
    if err != nil {
        fmt.Println("Ошибка сериализации:", err)
        return
    }

    fmt.Println(string(jsonBytes))
    // Вывод: {"Name":"Иван Петров","Age":30,"City":"Москва"}
}

Обратите внимание: json.Marshal() возвращает срез байтов ([]byte), поэтому мы преобразуем его в строку с помощью string().

Форматированный вывод с json.MarshalIndent

Для отладки или вывода в читаемом виде используйте json.MarshalIndent():

jsonBytes, err := json.MarshalIndent(person, "", "  ")
if err != nil {
    fmt.Println("Ошибка:", err)
    return
}
fmt.Println(string(jsonBytes))
// Вывод:
// {
//   "Name": "Иван Петров",
//   "Age": 30,
//   "City": "Москва"
// }

Сериализация срезов и карт

Go позволяет сериализовать не только структуры, но и другие типы данных:

// Срез структур
people := []Person{
    {Name: "Анна", Age: 25, City: "СПб"},
    {Name: "Петр", Age: 35, City: "Казань"},
}
jsonBytes, _ := json.Marshal(people)
fmt.Println(string(jsonBytes))
// Вывод: [{"Name":"Анна","Age":25,"City":"СПб"},{"Name":"Петр","Age":35,"City":"Казань"}]

// Карта
scores := map[string]int{"Алгебра": 5, "Физика": 4, "Информатика": 5}
jsonBytes, _ = json.Marshal(scores)
fmt.Println(string(jsonBytes))
// Вывод: {"Алгебра":5,"Информатика":5,"Физика":4}

Парсинг JSON: преобразование JSON в Go-структуры

Парсинг (десериализация) — это обратный процесс: из строки JSON мы получаем структуру Go. Для этого используется функция json.Unmarshal().

Парсинг в структуру

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string
    Age  int
    City string
}

func main() {
    jsonString := `{"Name":"Иван Петров","Age":30,"City":"Москва"}`

    var person Person
    err := json.Unmarshal([]byte(jsonString), &person)
    if err != nil {
        fmt.Println("Ошибка парсинга:", err)
        return
    }

    fmt.Printf("Имя: %s, Возраст: %d, Город: %s\n", person.Name, person.Age, person.City)
    // Вывод: Имя: Иван Петров, Возраст: 30, Город: Москва
}

Важно: передавайте указатель на структуру (&person), иначе Unmarshal не сможет изменить её поля.

Парсинг в map[string]interface{}

Если структура данных заранее неизвестна, можно использовать универсальный тип:

jsonString := `{"name":"Анна","age":25,"hobbies":["чтение","плавание"]}`

var data map[string]interface{}
err := json.Unmarshal([]byte(jsonString), &data)
if err != nil {
    fmt.Println("Ошибка:", err)
    return
}

for key, value := range data {
    fmt.Printf("Ключ: %s, Значение: %v (тип: %T)\n", key, value, value)
}
// Вывод:
// Ключ: name, Значение: Анна (тип: string)
// Ключ: age, Значение: 25 (тип: float64)
// Ключ: hobbies, Значение: [чтение плавание] (тип: []interface{})

Обратите внимание: числа в JSON по умолчанию парсятся как float64, а не как int. Для точного контроля используйте структуры с явными типами.

Теги структур: управление именами полей в JSON

По умолчанию имена полей в JSON совпадают с именами полей структуры. Однако часто требуется использовать другие имена (например, в стиле camelCase или snake_case). Для этого в Go используются теги структур.

Пример с тегами

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
    City string `json:"city,omitempty"` // omitempty — пропустить пустое значение
}

func main() {
    person := Person{Name: "Иван", Age: 30}
    jsonBytes, _ := json.Marshal(person)
    fmt.Println(string(jsonBytes))
    // Вывод: {"name":"Иван","age":30}
    // Поле City пропущено, так как оно пустое
}

Популярные опции тегов

  • json:"field_name" — задаёт имя поля в JSON
  • json:"-" — полностью исключает поле из JSON
  • json:"field_name,omitempty" — пропускает поле, если оно имеет нулевое значение
  • json:"field_name,string" — принудительно преобразует числовое поле в строку

Пример с разными опциями


                
                

Блоги

Рекомендаций по книгам