Введение в работу с 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"— задаёт имя поля в JSONjson:"-"— полностью исключает поле из JSONjson:"field_name,omitempty"— пропускает поле, если оно имеет нулевое значениеjson:"field_name,string"— принудительно преобразует числовое поле в строку
Пример с разными опциями
Блоги
Рекомендаций по книгам
Читайте также