JSON to Go Struct
Генерация Go struct из JSON
Ввод JSON
Вывод Go
Что такое конвертация JSON в Go struct?
Конвертация JSON в Go struct превращает сырые JSON-данные в определения типов Go, совместимые с пакетом encoding/json из стандартной библиотеки. Go является статически типизированным языком, поэтому каждому полю JSON должно соответствовать поле struct с правильным типом и тегом struct, указывающим сериализатору, какой JSON-ключ с ним сопоставить. Писать такие определения вручную для больших или глубоко вложенных ответов API — медленно и легко ошибиться.
Пакет encoding/json, определённый в спецификации Go начиная с версии 1.0, использует рефлексию для сопоставления JSON-ключей с экспортируемыми полями struct. По умолчанию сопоставление выполняется без учёта регистра, однако явные теги struct json являются стандартной практикой: они устраняют неоднозначность и позволяют использовать соглашение PascalCase в Go, пока JSON остаётся в camelCase или snake_case. Конвертер автоматизирует этот процесс: читает JSON, определяет типы Go из значений и выводит определения struct с правильными тегами.
Система типов Go чисто отображается на JSON. Строки становятся string, булевы значения — bool, целые числа — int, а числа с плавающей точкой — float64. Вложенные JSON-объекты становятся отдельными именованными struct, а массивы — слайсами. Единственный пробел — null: в Go нет универсального nullable-типа, поэтому null-значения обычно становятся типами-указателями (*string, *int) или interface{}. Генератор справляется со всем этим за миллисекунды.
Зачем использовать конвертер JSON в Go?
Определять Go struct из JSON вручную — значит считать фигурные скобки, угадывать типы и переписывать теги каждый раз при изменении API. Конвертер снимает это трение.
Сценарии использования JSON to Go Struct
Справочник по сопоставлению типов JSON и Go
Пакет encoding/json следует определённым правилам при сопоставлении JSON-значений с типами Go. В таблице ниже показано сопоставление по умолчанию и распространённые альтернативы. Столбец «По умолчанию» — это то, что производит большинство генераторов. Столбец «Альтернатива» содержит типы, которые вы можете выбрать исходя из своих требований, например int64 для больших ID или типы-указатели для nullable-полей.
| Тип JSON | Пример | По умолчанию | Альтернатива |
|---|---|---|---|
| string | "hello" | string | string |
| number (integer) | 42 | int | int64 |
| number (float) | 3.14 | float64 | float64 |
| boolean | true | bool | bool |
| null | null | interface{} | *string / *int |
| object | {"k": "v"} | struct | struct |
| array of strings | ["a", "b"] | []string | []string |
| array of objects | [{"id": 1}] | []Item | []Item |
| mixed array | [1, "a"] | []interface{} | []interface{} |
Справочник тегов struct для JSON в Go
Теги struct управляют тем, как encoding/json сериализует и десериализует поля. Тег json является наиболее распространённым, но его можно комбинировать с другими тегами (db, yaml, xml) на одном поле. Синтаксис тега — строка в обратных кавычках после типа поля. Ниже приведены параметры тега json, поддерживаемые encoding/json.
| Тег | Поведение | Сценарий использования |
|---|---|---|
| json:"name" | Maps struct field to JSON key "name" | Always generated |
| json:"name,omitempty" | Omits field from output if zero value | Optional fields |
| json:"-" | Field is never serialized or deserialized | Internal fields |
| json:"name,string" | Encodes int/bool as JSON string | String-encoded numbers |
json.Unmarshal vs json.NewDecoder
Go предоставляет два способа декодирования JSON: json.Unmarshal для байтовых срезов и json.NewDecoder для потоков io.Reader. Оба используют одни и те же правила тегов struct, но различаются по области применения.
Примеры кода
Эти примеры показывают, как использовать Go struct, сгенерированные из JSON, в реальных программах, а также как генерировать их из других языков. Примеры на Go используют encoding/json из стандартной библиотеки.
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
IsActive bool `json:"is_active"`
Tags []string `json:"tags"`
}
func main() {
data := []byte(`{"id":1,"name":"Alice","email":"alice@example.com","is_active":true,"tags":["admin","editor"]}`)
var user User
if err := json.Unmarshal(data, &user); err != nil {
panic(err)
}
fmt.Println(user.Name) // → Alice
fmt.Println(user.Tags) // → [admin editor]
}// JSON response from API — this is the shape you'd convert to Go:
const res = await fetch("https://api.example.com/users/1");
const user = await res.json();
// user → { "id": 1, "name": "Alice", "email": "alice@example.com" }
// Equivalent Go struct:
// type User struct {
// ID int `json:"id"`
// Name string `json:"name"`
// Email string `json:"email"`
// }import json
def json_to_go(data: dict, name: str = "Root") -> str:
lines = [f"type {name} struct {{"]
type_map = {str: "string", int: "int", float: "float64", bool: "bool"}
for key, value in data.items():
go_type = type_map.get(type(value), "interface{}")
field = key.title().replace("_", "") # snake_case → PascalCase
lines.append(f'\t{field} {go_type} `json:"{key}"`')
lines.append("}")
return "\n".join(lines)
data = json.loads('{"user_name": "Alice", "age": 30, "verified": true}')
print(json_to_go(data))
# type Root struct {
# UserName string `json:"user_name"`
# Age int `json:"age"`
# Verified bool `json:"verified"`
# }package main
import (
"encoding/json"
"fmt"
"strings"
)
type Event struct {
Type string `json:"type"`
Payload string `json:"payload"`
}
func main() {
stream := strings.NewReader(`{"type":"click","payload":"btn-1"}
{"type":"scroll","payload":"page-2"}`)
dec := json.NewDecoder(stream)
for dec.More() {
var ev Event
if err := dec.Decode(&ev); err != nil {
break
}
fmt.Printf("%s: %s\n", ev.Type, ev.Payload)
}
// → click: btn-1
// → scroll: page-2
}