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

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

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

Начать курс

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

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

Основы пакета encoding/json

Пакет encoding/json — это стандартная библиотека Go, которая не требует дополнительной установки. Два главных инструмента в этом пакете — функции json.Marshal (сериализация) и json.Unmarshal (десериализация).

Структуры и теги JSON

В Go данные обычно представляются в виде структур (struct). Для управления именами полей в JSON используются теги. Рассмотрим простой пример:

package main

import (
    "encoding/json"
    "fmt"
)

// Определяем структуру с тегами JSON
type Person struct {
    Name    string `json:"name"`
    Age     int    `json:"age"`
    Email   string `json:"email,omitempty"`
    IsAdmin bool   `json:"is_admin"`
}

func main() {
    // Создаём экземпляр структуры
    person := Person{
        Name:    "Иван Петров",
        Age:     30,
        Email:   "ivan@example.com",
        IsAdmin: true,
    }
    
    // Сериализуем в JSON
    jsonData, _ := json.Marshal(person)
    fmt.Println(string(jsonData))
}

Результат выполнения:

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

Важные моменты:

  • Тег json:"name" указывает, как поле будет называться в JSON
  • Опция omitempty пропускает пустые поля (нулевые значения)
  • Поля структуры должны быть экспортируемыми (начинаться с большой буквы)

Сериализация (Marshal) данных в JSON

Сериализация — это процесс преобразования Go-структуры или другого типа данных в строку JSON. Функция json.Marshal возвращает срез байтов ([]byte) и ошибку.

Примеры сериализации разных типов

package main

import (
    "encoding/json"
    "fmt"
)

type Product struct {
    ID       int      `json:"id"`
    Name     string   `json:"name"`
    Price    float64  `json:"price"`
    Tags     []string `json:"tags,omitempty"`
    InStock  bool     `json:"in_stock"`
}

func main() {
    // Сериализация структуры
    product := Product{
        ID:      101,
        Name:    "Ноутбук",
        Price:   79999.99,
        Tags:    []string{"электроника", "ноутбуки"},
        InStock: true,
    }
    
    // Красивый вывод с отступами
    jsonData, _ := json.MarshalIndent(product, "", "  ")
    fmt.Println(string(jsonData))
    
    // Сериализация среза структур
    products := []Product{
        {ID: 1, Name: "Мышь", Price: 1500.00, InStock: true},
        {ID: 2, Name: "Клавиатура", Price: 3500.00, InStock: false},
    }
    
    jsonArray, _ := json.Marshal(products)
    fmt.Println(string(jsonArray))
}

Результат:

{
  "id": 101,
  "name": "Ноутбук",
  "price": 79999.99,
  "tags": [
    "электроника",
    "ноутбуки"
  ],
  "in_stock": true
}
[{"id":1,"name":"Мышь","price":1500,"in_stock":true},{"id":2,"name":"Клавиатура","price":3500,"in_stock":false}]

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

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

Базовый пример парсинга

package main

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

type User struct {
    Username string `json:"username"`
    Age      int    `json:"age"`
    City     string `json:"city"`
}

func main() {
    // JSON-строка для парсинга
    jsonString := `{"username":"alex","age":25,"city":"Москва"}`
    
    // Создаём переменную для результата
    var user User
    
    // Парсим JSON
    err := json.Unmarshal([]byte(jsonString), &user)
    if err != nil {
        log.Fatal("Ошибка парсинга JSON:", err)
    }
    
    fmt.Printf("Имя: %s, Возраст: %d, Город: %s\n", 
        user.Username, user.Age, user.City)
}

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

package main

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

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

type Employee struct {
    Name    string  `json:"name"`
    Age     int     `json:"age"`
    Address Address `json:"address"`
    Skills  []string `json:"skills"`
}

func main() {
    complexJSON := `{
        "name": "Мария Соколова",
        "age": 28,
        "address": {
            "street": "ул. Ленина, 15",
            "city": "Санкт-Петербург",
            "zip_code": "190000"
        },
        "skills": ["Go", "Python", "JavaScript"]
    }`
    
    var employee Employee
    err := json.Unmarshal([]byte(complexJSON), &employee)
    if err != nil {
        log.Fatal("Ошибка:", err)
    }
    
    fmt.Printf("Сотрудник: %s\n", employee.Name)
    fmt.Printf("Адрес: %s, %s\n", employee.Address.City, employee.Address.Street)
    fmt.Printf("Навыки: %v\n", employee.Skills)
}

Обработка ошибок и неопределённых данных

При работе с JSON важно правильно обрабатывать ошибки. Часто встречаются случаи, когда JSON содержит неизвестные поля или данные отсутствуют.

Использование map[string]interface{}

package main

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

func main() {
    // Неизвестная структура JSON
    jsonData := `{
        "name": "Тестовый объект",
        "value": 42,
        "active": true,
        "metadata": {
            "version": 2,
            "author": "admin"                

Блоги

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