JSON to Go Struct
Go structs genereren vanuit JSON
JSON-invoer
Go-uitvoer
Wat is JSON naar Go-conversie?
JSON naar Go-conversie zet ruwe JSON-data om in Go type-definities die werken met het encoding/json-pakket uit de standaardbibliotheek van Go. Go is statisch getypeerd, dus elk JSON-veld heeft een bijbehorend struct-veld nodig met het juiste type en een struct-tag die de serializer vertelt welke JSON-sleutel eraan gekoppeld is. Die definities met de hand schrijven voor grote of diep geneste API-responses is traag en foutgevoelig.
Het encoding/json-pakket, onderdeel van de Go-specificatie sinds Go 1.0, gebruikt reflectie om JSON-sleutels te koppelen aan geëxporteerde struct-velden. De koppeling is standaard hoofdletterongevoelig, maar expliciete json struct-tags zijn de gangbare aanpak omdat ze ambiguïteit wegnemen en je de PascalCase-conventie van Go kunt hanteren terwijl de JSON in camelCase of snake_case blijft. Een converter automatiseert dit: hij leest je JSON, leidt Go-typen af uit de waarden en geeft struct-definities terug met de juiste tags.
Het typesysteem van Go past goed op JSON. Strings worden string, booleans worden bool, integers worden int en kommagetallen worden float64. Geneste JSON-objecten worden afzonderlijke benoemde structs en arrays worden slices. De enige uitzondering is null: Go heeft geen universeel nullable type, dus null-waarden worden doorgaans pointer-typen (*string, *int) of interface{}. Een generator verwerkt dit alles in milliseconden.
Waarom een JSON naar Go-converter gebruiken?
Go structs met de hand definiëren vanuit JSON betekent accolades tellen, types raden en tags herschrijven telkens als de API verandert. Een converter neemt die moeite weg.
Toepassingen van JSON naar Go
JSON naar Go type-mapping
Het encoding/json-pakket volgt specifieke regels bij het koppelen van JSON-waarden aan Go-typen. De onderstaande tabel toont de standaard-mapping en veelgebruikte alternatieven. De kolom "Standaard" is wat de meeste generators produceren. De kolom "Alternatief" toont typen die je kunt kiezen op basis van je vereisten, zoals int64 voor grote ID's of pointer-typen voor nullable velden.
| JSON-type | Voorbeeld | Standaard | Alternatief |
|---|---|---|---|
| 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{} |
Go JSON Struct Tag-referentie
Struct-tags bepalen hoe encoding/json velden serialiseert en deserialiseert. De json-tag is verreweg de meest voorkomende, maar je kunt hem combineren met andere tags (db, yaml, xml) op hetzelfde veld. De tag-syntaxis is een backtick-afgebakende string na het veldtype. Hier zijn de json-tagopties die encoding/json ondersteunt.
| Tag | Gedrag | Toepassing |
|---|---|---|
| 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 biedt twee manieren om JSON te decoderen: json.Unmarshal voor byte-slices en json.NewDecoder voor io.Reader-streams. Beide gebruiken dezelfde struct-tagregels, maar verschillen in wanneer je ze toepast.
Codevoorbeelden
Deze voorbeelden laten zien hoe je Go structs gegenereerd vanuit JSON gebruikt in echte programma's, en hoe je ze genereert vanuit andere talen. De Go-voorbeelden gebruiken encoding/json uit de standaardbibliotheek.
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
}