Маршалинг JSON и использование тегов структур
Мы подошли к моменту, когда приложение должно общаться с внешним миром. В React вы привыкли к JSON как к «родному» формату: JSON.parse() превращает строку в объект, а JSON.stringify() — обратно.
В Go процесс устроен иначе из-за строгой типизации. Мы не просто преобразуем данные, а сопоставляем их с конкретными структурами, используя метаданные.
JSON в Go: Marshaling и Unmarshaling
Работа с JSON строится вокруг двух процессов:
- Marshaling — преобразование структуры Go в формат JSON (срез байт
[]byte). - Unmarshaling — извлечение данных из JSON в структуру Go.
Главное отличие от TypeScript: Go использует механизм рефлексии, чтобы читать структуру в рантайме. Чтобы это работало, поля структуры должны быть экспортируемыми — начинаться с заглавной буквы. Поля со строчной буквы пакет encoding/json игнорирует.
Как показано в Сравнении 1, описание модели данных в Go требует явного маппинга полей.
Теги структур (Struct tags)
В Go принято именовать публичные поля в PascalCase, а во фронтенде стандарт — camelCase. Чтобы связать их, используют Struct tags — аннотации в обратных кавычках после типа поля.
type UserProfile struct {
ID int `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
// Скрывает поле в JSON, если оно пустое
Email string `json:"email,omitempty"`
// Полностью исключает поле из обмена данными
Password string `json:"-"`
}
Практика: преобразование байт в данные
Данные от React-приложения приходят на сервер в виде среза байт ([]byte).
package main
import (
"encoding/json"
"fmt"
)
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
func main() {
// Имитируем JSON из тела HTTP-запроса
jsonData := []byte(`{"username": "admin", "password": "123"}`)
var req LoginRequest
// Передаем указатель (&req), чтобы функция записала данные в переменную
err := json.Unmarshal(jsonData, &req)
if err != nil {
fmt.Println("Ошибка парсинга:", err)
return
}
fmt.Printf("Пользователь %s вошел в систему\n", req.Username)
}
Гибкость с json.RawMessage
Иногда структура части JSON заранее неизвестна или её нужно обработать позже. В TypeScript для этого есть any, а в Go — json.RawMessage. Это тип, который сохраняет часть JSON как «сырой» массив байт.
Это полезно в микросервисах, когда сервис-посредник передает данные дальше, не вникая в их содержимое 🧩
type Event struct {
Type string `json:"type"`
Payload json.RawMessage `json:"payload"` // Любой валидный JSON
}
Упражнение: проектирование контракта
Спроектируйте структуру для Todo-сервиса, которая будет обмениваться данными с вашим React-фронтендом.
Создайте структуру TodoItem со следующими правилами:
- Поле
ID(int), в JSON —id. - Поле
Title(string), в JSON —title. - Поле
IsDone(bool), в JSON —completed. - Поле
Tags([]string), в JSON —tags, скрывать при отсутствии данных (omitempty). - Поле
InternalCode(string), которое не должно попадать в JSON.
Напишите код в IDE и проверьте, как работает маршалинг при пустых полях.
Мы разобрались с «нервной системой» API — передачей данных. Чтобы эти данные начали перемещаться между сервером и клиентом, нужен транспорт.
В следующей теме мы создадим веб-сервер на стандартной библиотеке Go 1.22+ и научимся обрабатывать реальные HTTP-запросы.
Понравился урок?
Сохраните прогресс и получите персональный курс по любой теме — без форм и паролей
Продолжить в Telegram