Modulelessen (5/5)
`codering/json`
encoding/json is het canonieke pakket voor het serialiseren van Go-structuren naar JSON en terug. Als u de conventies en valkuilen kent, bespaart u urenlang debuggen van API's en configuratiebestanden.
Maarschalk en Unmaarschalk
De twee belangrijkste functies:
data, err := json.Marshal(v) // Go → []byte JSON
err = json.Unmarshal(data, &v) // JSON → Go (pass a pointer!)type User struct {
Name string
Email string
}
u := User{Name: "Ada", Email: "ada@example.com"}
b, _ := json.Marshal(u)
fmt.Println(string(b))
// {"Name":"Ada","Email":"ada@example.com"}
var back User
_ = json.Unmarshal(b, &back)Voor ingesprongen uitvoer (voor mensen leesbaar) gebruikt u json.MarshalIndent(v, "", " ").
Alleen geëxporteerde velden
json.Marshal serialiseert alleen geëxporteerde velden (hoofdletters). Privévelden worden stil genegeerd:
type U struct {
Name string // exported → serialized
age int // private → ignored
}Structure-tags: controle over naam en opties
De json:"..." tags bepalen de naam, weglatingen en typen in de uitvoer:
type User struct {
Name string `json:"name"` // rename
Email string `json:"email,omitempty"` // omit if zero value
Private string `json:"-"` // never serialized
ID int `json:"id,string"` // number as string
}Meest gebruikte opties:
,omitempty— laat het veld weg als het de nulwaarde is (0, "", nul, leeg segment/kaart).,-— nooit geserialiseerd/gedeserialiseerd.,string— verpakt getallen/bools als tekenreeksen (handig voor JS-ID's).
Decoder/Encoder voor streams
Wanneer u werkt met io.Reader/io.Writer (HTTP-body, grote bestanden), gebruikt u Decoder en Encoder in plaats van alles in het geheugen te laden:
dec := json.NewDecoder(resp.Body)
var users []User
if err := dec.Decode(&users); err != nil {
return err
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
_ = enc.Encode(users)Decoder ondersteunt ook dec.Token() voor het stuk voor stuk parseren van streaming en dec.DisallowUnknownFields() om JSON met onverwachte sleutels te weigeren (handig voor invoervalidatie).
Algemene kaarten en any
Als u het schema niet kent, deserialiseer dan naar map[string]any:
var v map[string]any
_ = json.Unmarshal(data, &v)
fmt.Println(v["name"])Waarden hebben dynamische typen (string, float64 voor getallen, []any, map[string]any, bool, nil).
Veelvoorkomende fouten
- Vergeten
&:json.Unmarshal(data, v)vult niets in; je hebt&vnodig. - Decodering van structuren met nul velden: om paniek te voorkomen, controleer
errVOORDAT u velden leest. - Incompatibele typen: het deserialiseren van een getal in een tekenreeks of omgekeerd retourneert
*json.UnmarshalTypeError.
Oefeningen
Serialiseer de struct u naar JSON met json.Marshal en druk het resultaat af als een tekenreeks.
Oplossing beschikbaar na 3 pogingen
Deserialiseer `{"Name":Ada"}` in de struct U met json.Unmarshal en druk het af.
Oplossing beschikbaar na 3 pogingen
Is het veld `name string` (kleine letters) van een struct opgenomen door json.Marshal?
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))