Обработка JSON в Go (Golang): encoding/json и альтернативы

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

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

Начать курс

JSON обработка в Go (Golang): от основ до продвинутых техник

Go (Golang) предлагает мощный и интуитивно понятный набор инструментов для работы с JSON. Стандартная библиотека encoding/json покрывает 95% задач, а для высоконагруженных проектов существуют более производительные альтернативы. В этой статье мы разберём все аспекты JSON-обработки в Go: от базовой сериализации до кастомных парсеров и оптимизации.

1. Основы: стандартная библиотека encoding/json

В Go JSON обрабатывается через пакет encoding/json. Основные операции — маршалинг (сериализация в JSON) и анмаршалинг (десериализация из JSON).

1.1. Маршалинг (struct → JSON)

Для преобразования структуры Go в JSON используется функция json.Marshal():

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type User struct {
    Name  string `json:"name"`
    Age   int    `json:"age"`
    Email string `json:"email,omitempty"` // omitempty - пропустить, если пустое
}

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

    jsonData, err := json.Marshal(user)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonData))
    // {"name":"Иван Петров","age":30,"email":"ivan@example.com"}
}

Важно: Поля структуры должны быть экспортируемыми (с большой буквы). Теги json:"fieldname" управляют именованием полей в JSON.

1.2. Анмаршалинг (JSON → struct)

Для обратного преобразования используется json.Unmarshal():

func main() {
    jsonString := `{"name":"Анна","age":25,"email":"anna@mail.com"}`
    
    var user User
    err := json.Unmarshal([]byte(jsonString), &user)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Имя: %s, Возраст: %d\n", user.Name, user.Age)
    // Имя: Анна, Возраст: 25
}

2. Работа с вложенными структурами и массивами

JSON часто содержит вложенные объекты и массивы. В Go это отображается на вложенные структуры и срезы:

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

type Company struct {
    Name      string    `json:"name"`
    Employees []User    `json:"employees"`
    Address   Address   `json:"address"`
}

func main() {
    companyJSON := `{
        "name": "TechCorp",
        "employees": [
            {"name":"Олег","age":28,"email":"oleg@tech.com"},
            {"name":"Мария","age":32,"email":"maria@tech.com"}
        ],
        "address": {
            "city": "Москва",
            "street": "Тверская, 10",
            "zip_code": "101000"
        }
    }`

    var company Company
    json.Unmarshal([]byte(companyJSON), &company)
    fmt.Printf("Компания: %s, Город: %s, Сотрудников: %d\n",
        company.Name, company.Address.City, len(company.Employees))
}

3. Продвинутые техники

3.1. Кастомная сериализация (интерфейсы Marshaler/Unmarshaler)

Иногда нужно контролировать, как тип преобразуется в JSON. Для этого реализуют интерфейсы json.Marshaler и json.Unmarshaler:

type CustomTime struct {
    time.Time
}

const layout = "2006-01-02T15:04:05Z"

func (ct CustomTime) MarshalJSON() ([]byte, error) {
    return json.Marshal(ct.Format(layout))
}

func (ct *CustomTime) UnmarshalJSON(data []byte) error {
    var s string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    t, err := time.Parse(layout, s)
    if err != nil {
        return err
    }
    ct.Time = t
    return nil
}

type Event struct {
    Title string     `json:"title"`
    Date  CustomTime `json:"date"`
}

3.2. Работа с неструктурированным JSON (map[string]interface{})

Если структура JSON неизвестна заранее, используйте map[string]interface{}:

func main() {
    rawJSON := `{"name":"Тест","values":[1,2,3],"active":true}`
    
    var data map[string]interface{}
    json.Unmarshal([]byte(rawJSON), &data)

    // Доступ к значениям с приведением типов
    name := data["name"].(string)
    values := data["values"].([]interface{})
    
    fmt.Printf("Имя                    

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