JSON do struktury Go
Generuj struktury Go z JSON
Wejście JSON
Wyjście Go
Czym jest konwersja JSON do struktury Go?
Konwersja JSON do struktury Go przekształca surowe dane JSON w definicje typów Go działające z pakietem encoding/json ze standardowej biblioteki Go. Go jest językiem statycznie typowanym, więc każde pole JSON wymaga odpowiedniego pola struktury z poprawnym typem oraz tagiem struktury informującym serializator, który klucz JSON należy odwzorować. Ręczne pisanie tych definicji dla dużych lub głęboko zagnieżdżonych odpowiedzi API jest powolne i łatwe do pomylenia.
Pakiet encoding/json, obecny w specyfikacji Go od wersji 1.0, używa refleksji do dopasowania kluczy JSON do eksportowanych pól struktury. Domyślnie dopasowanie jest bez rozróżnienia wielkości liter, ale jawne tagi json są standardową praktyką, ponieważ eliminują niejednoznaczność i pozwalają używać konwencji PascalCase Go, podczas gdy JSON pozostaje w camelCase lub snake_case. Konwerter automatyzuje ten proces: odczytuje JSON, wnioskuje typy Go z wartości i generuje definicje struktur z poprawnymi tagami.
System typów Go mapuje się czytelnie na JSON. Ciągi znaków stają się string, wartości logiczne — bool, liczby całkowite — int, a liczby zmiennoprzecinkowe — float64. Zagnieżdżone obiekty JSON stają się oddzielnymi nazwanymi strukturami, a tablice — wycinkami (slice). Jedyna luka to null: Go nie ma uniwersalnego typu dopuszczającego null, więc wartości null zazwyczaj stają się typami wskaźnikowymi (*string, *int) lub interface{}. Generator obsługuje to wszystko w milisekundy.
Dlaczego warto używać konwertera JSON do Go?
Ręczne definiowanie struktur Go z JSON oznacza liczenie nawiasów klamrowych, zgadywanie typów i przepisywanie tagów za każdym razem, gdy API się zmienia. Konwerter usuwa te niedogodności.
Przypadki użycia JSON do struktury Go
Mapowanie typów JSON do Go
Pakiet encoding/json stosuje określone reguły mapowania wartości JSON na typy Go. Poniższa tabela przedstawia domyślne mapowanie i popularne alternatywy. Kolumna "Domyślny" pokazuje to, co większość generatorów produkuje. Kolumna "Alternatywny" pokazuje typy, które możesz wybrać na podstawie swoich wymagań, np. int64 dla dużych identyfikatorów lub typy wskaźnikowe dla pól dopuszczających null.
| Typ JSON | Przykład | Domyślny | Alternatywny |
|---|---|---|---|
| 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{} |
Informacje o tagach json struktury Go
Tagi struktury kontrolują sposób serializacji i deserializacji pól przez encoding/json. Tag json jest zdecydowanie najpowszechniejszy, ale możesz łączyć go z innymi tagami (db, yaml, xml) w tym samym polu. Składnia tagu to ciąg znaków ujęty w znaki backtick po typie pola. Oto opcje tagu json obsługiwane przez encoding/json.
| Tag | Zachowanie | Przypadek użycia |
|---|---|---|
| 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 a json.NewDecoder
Go oferuje dwa sposoby dekodowania JSON: json.Unmarshal dla wycinków bajtów i json.NewDecoder dla strumieni io.Reader. Oba używają tych samych reguł tagów struktury, ale różnią się sytuacjami, w których należy ich używać.
Przykłady kodu
Te przykłady pokazują, jak używać struktur Go wygenerowanych z JSON w prawdziwych programach, a także jak generować je z innych języków. Przykłady Go używają encoding/json ze standardowej biblioteki.
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
}