Vai al contenuto
eLearner.app
Modulo 8 · Lezione 5 di 540/50 nel corso~14 min
Lezioni del modulo (5/5)

`encoding/json`

encoding/json è il pacchetto canonico per serializzare struct Go in JSON e viceversa. Conoscerne convenzioni e trabocchetti ti risparmia ore di debug su API e file di configurazione.

Marshal e Unmarshal

Le due funzioni principali:

Go
data, err := json.Marshal(v)      // Go → []byte JSON
err = json.Unmarshal(data, &v)    // JSON → Go (passa puntatore!)
Go
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)

Per output indentato (leggibile a umani) usa json.MarshalIndent(v, "", " ").

Solo campi esportati

json.Marshal serializza soltanto i campi esportati (Maiuscoli). I campi privati vengono ignorati silenziosamente:

Go
type U struct {
    Name string // esportato → serializzato
    age  int    // privato → ignorato
}

Struct tag: controllo del nome e delle opzioni

I tag json:"..." controllano nome, omissione e tipi nell'output:

Go
type User struct {
    Name    string `json:"name"`                    // rinomina
    Email   string `json:"email,omitempty"`         // omette se zero value
    Private string `json:"-"`                       // mai serializzato
    ID      int    `json:"id,string"`               // numero come stringa
}

Opzioni più usate:

  • ,omitempty — omette il campo se è il zero value (0, "", nil, slice/map vuoti).
  • ,- — mai serializzato/deserializzato.
  • ,string — incapsula numeri/bool come stringhe (utile per ID JS).

Decoder/Encoder per stream

Quando lavori con io.Reader/io.Writer (HTTP body, file enormi) usa Decoder ed Encoder invece di caricare tutto in memoria:

Go
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 supporta anche dec.Token() per parsing streaming pezzo-a-pezzo e dec.DisallowUnknownFields() per rifiutare JSON con chiavi non previste (utile per validare input).

Mappe generiche e any

Se non conosci lo schema, deserializza in map[string]any:

Go
var v map[string]any
_ = json.Unmarshal(data, &v)
fmt.Println(v["name"])

I valori avranno tipi dinamici (string, float64 per i numeri, []any, map[string]any, bool, nil).

Errori comuni

  • Dimenticare &: json.Unmarshal(data, v) non popola nulla; serve &v.
  • Decodare struct con campi nil: per evitare panic, controlla err PRIMA di leggere campi.
  • Tipi non compatibili: deserializzare un numero in una stringa o viceversa ritorna *json.UnmarshalTypeError.

Esercizi

Esercizio#go.m8.l5.e1
Tentativi: 0Caricamento…

Serializza la struct u in JSON con json.Marshal e stampa il risultato come stringa.

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Esercizio#go.m8.l5.e2
Tentativi: 0Caricamento…

Deserializza `{"Name":"Ada"}` nella struct U con json.Unmarshal e stampala.

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Quiz#go.m8.l5.e3
Pronto

Il campo `name string` (minuscolo) di una struct viene incluso da json.Marshal?

Go
type U struct {
  name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))
Opzioni di risposta