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

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

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

Начать курс

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

JSON (JavaScript Object Notation) — это один из самых популярных форматов обмена данными в современных веб-приложениях, микросервисах и API. Язык Go (Golang) предлагает встроенную мощную поддержку для работы с JSON через пакет encoding/json. Этот пакет позволяет легко преобразовывать данные между Go-структурами и JSON-строками, а также наоборот.

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

Основы сериализации (Marshal) в Go

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

Сериализация — это процесс преобразования Go-объекта (например, структуры или слайса) в JSON-строку. Для этого используется функция json.Marshal(). Рассмотрим простейший пример:

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    Name  string
    Age   int
    Email string
}

func main() {
    user := User{
        Name:  "Иван Петров",
        Age:   30,
        Email: "ivan@example.com",
    }

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

    fmt.Println(string(jsonData))
}

Вывод программы:

{"Name":"Иван Петров","Age":30,"Email":"ivan@example.com"}

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

Использование тегов для настройки JSON

Теги структур позволяют задать, как именно поле будет сериализоваться. Добавим теги к нашему примеру:

type User struct {
    Name  string `json:"name"`
    Age   int    `json:"age"`
    Email string `json:"email,omitempty"`
}

Теперь вывод будет таким:

{"name":"Иван Петров","age":30,"email":"ivan@example.com"}

Ключевые опции тегов:

  • json:"field_name" — задаёт имя поля в JSON.
  • omitempty — исключает поле из JSON, если оно имеет нулевое значение (пустая строка, 0, false, nil).
  • - — полностью игнорирует поле при сериализации/десериализации.

Сериализация слайсов и мап

Пакет encoding/json отлично работает не только со структурами, но и со слайсами, мапами и простыми типами:

// Слайс структур
users := []User{
    {Name: "Анна", Age: 25},
    {Name: "Борис", Age: 35},
}
jsonUsers, _ := json.Marshal(users)
fmt.Println(string(jsonUsers))
// Вывод: [{"name":"Анна","age":25},{"name":"Борис","age":35}]

// Мапа
data := map[string]interface{}{
    "status": "ok",
    "count":  42,
}
jsonMap, _ := json.Marshal(data)
fmt.Println(string(jsonMap))
// Вывод: {"count":42,"status":"ok"}

Парсинг JSON (Unmarshal) в Go

Базовый парсинг в структуру

Десериализация (парсинг) — это обратный процесс: преобразование JSON-строки в Go-объект. Используется функция json.Unmarshal(). Важно: целевая структура должна быть экспортирована (поля с большой буквы) или иметь соответствующие теги.

jsonString := `{"name":"Мария","age":28,"email":"maria@example.com"}`

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

fmt.Printf("Имя: %s, Возраст: %d\n", user.Name, user.Age)
// Вывод: Имя: Мария, Возраст: 28

Парсинг вложенных структур

JSON часто содержит вложенные объекты. Go позволяет моделировать их с помощью вложенных структур:

type Address struct {
    City    string `json:"city"`
    Street  string `json:"street"`
}

type Person struct {
    Name    string  `json:"name"`
    Age     int     `json:"age"`
    Address Address `json:"address"`
}

func main() {
    jsonData := `{
        "name": "Алексей",
        "age": 40,
        "address": {
            "city": "Москва",
            "street": "Тверская"
        }
    }`

    var person Person
    json.Unmarshal([]byte(jsonData), &person)
    fmt.Printf("%s живёт в городе %s\n", person.Name, person.Address.City)
    // Вывод: Алексей живёт в городе Москва
}

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

Если структура заранее неизвестна, можно использовать map[string]interface{}. Это гибкий, но менее безопасный подход, так как требует приведения типов:

jsonString := `{"name":"Ольга","age":32,"skills":["Go","Python","SQL"]}`

var result map[string]interface{}
json.Unmarshal([]byte(jsonString), &result)

name := result["name"].(string)
age := result["age"].(float64) // числа в JSON всегда float64
skills := result["skills"].([]interface{})

fmt.Printf("Имя: %s, Возраст: %.0f\n", name, age)
fmt.Println("Навыки:")
for _, skill := range skills {
    fmt.Println("-", skill)
}

Продвинутые приёмы работы с JSON

Форматированный вывод (Pretty Print)

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

user := User{Name: "Дмитрий", Age: 45}
jsonPretty, _ := json.MarshalIndent(user, "", "    ")
fmt.Println(string(jsonPretty))

Вывод:

{
    "name": "Дмитрий",
    "age": 45
}

Обработка ошибок и валидация

Всегда проверяйте ошибки после Marshal и Unmarshal. Типичные

Блоги

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