JSON to Go Struct
Generování Go struktur z JSON
Vstup JSON
Výstup Go
Co je převod JSON na Go Struct?
Převod JSON na Go struct je proces generování definic Go typů z dat JSON pro použití s balíčkem encoding/json ze standardní knihovny Go. Protože Go je staticky typované, každé pole JSON potřebuje odpovídající pole struktury se správným typem a struct tagem, který serializátoru říká, na který klíč JSON se mapuje. Ruční psaní těchto definic pro velké nebo hluboce vnořené API odpovědi je pomalé a náchylné k chybám.
Balíček encoding/json, definovaný ve specifikaci Go od verze 1.0, používá reflexi pro porovnávání klíčů JSON s exportovanými poli struktury. Porovnávání je ve výchozím nastavení nerozlišující velikost písmen, ale explicitní json struct tagy jsou standardní praxí, protože odstraňují nejednoznačnost a umožňují používat konvenci PascalCase jazyka Go, zatímco JSON zůstává v camelCase nebo snake_case. Převodník tuto práci automatizuje: přečte váš JSON, odvodí Go typy z hodnot a vypíše definice struktur se správnými tagy.
Typový systém Go se čistě mapuje na JSON. Řetězce se stávají string, booleovské hodnoty bool, celá čísla int a čísla s plovoucí desetinnou čárkou float64. Vnořené JSON objekty se stávají samostatnými pojmenovanými strukturami a pole se stávají slicy. Jediná mezera je null: Go nemá univerzální typ pro nullable hodnoty, proto se hodnoty null obvykle stávají typy ukazatelů (*string, *int) nebo interface{}. Generátor se s tím vším vypořádá v milisekundách.
Proč použít generátor JSON na Go?
Ruční definování Go struktur z JSON znamená počítání složených závorek, odhadování typů a přepisování tagů pokaždé, když se API změní. Generátor toto tření odstraňuje.
Případy použití JSON na Go Struct
Mapování typů JSON na Go
Balíček encoding/json dodržuje specifická pravidla při mapování hodnot JSON na Go typy. Tabulka níže zobrazuje výchozí mapování a běžné alternativy. Sloupec "Výchozí" je to, co většina generátorů produkuje. Sloupec "Alternativa" zobrazuje typy, které můžete zvolit podle vašich požadavků, například int64 pro velká ID nebo typy ukazatelů pro nullable pole.
| Typ JSON | Příklad | Výchozí | Alternativa |
|---|---|---|---|
| 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{} |
Přehled Go JSON Struct tagů
Struct tagy ovládají, jak encoding/json serializuje a deserializuje pole. Tag json je zdaleka nejběžnější, ale můžete ho kombinovat s dalšími tagy (db, yaml, xml) na stejném poli. Syntaxe tagu je řetězec ohraničený zpětnými uvozovkami za typem pole. Níže jsou uvedeny možnosti json tagu, které encoding/json podporuje.
| Tag | Chování | Případ použití |
|---|---|---|
| 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 poskytuje dva způsoby dekódování JSON: json.Unmarshal pro byte slicy a json.NewDecoder pro proudy io.Reader. Oba používají stejná pravidla struct tagů, ale liší se tím, kdy je použít.
Příklady kódu
Tyto příklady ukazují, jak používat Go struktury vygenerované z JSON v reálných programech, a také jak je generovat z jiných jazyků. Příklady Go používají encoding/json ze standardní knihovny.
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
}