Salt la conținutul principal
Modulul 8 · Lecția 5 din 540/50 în curs~14 min
Lecții din modul (5/5)

`encoding/json`

encoding/json este pachetul canonic pentru serializarea structurilor Go în JSON și înapoi. Cunoașterea convențiilor și capcanele sale vă economisește ore întregi de depanare a API-urilor și a fișierelor de configurare.

Mareșal și Unmarshal

Cele două funcții principale:

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

Pentru ieșire indentată (lizibilă de om) utilizați json.MarshalIndent(v, "", " ").

Numai câmpuri exportate

json.Marshal serializează numai câmpurile exportate (Majuscule). Câmpurile private sunt ignorate în tăcere:

Go
type U struct {
    Name string // exported → serialized
    age  int    // private → ignored
}

Etichete Struct: controlează numele și opțiunile

Etichetele json:"..." controlează numele, omisiunile și tipurile în rezultat:

Go
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
}

Cele mai utilizate optiuni:

  • ,omitempty — omite câmpul dacă este valoarea zero (0, "", zero, felie/hartă goală).
  • ,- — nu serializat/dezerializat niciodată.
  • ,string — împachetează numere/bool ca șiruri de caractere (util pentru ID-urile JS).

Decodor/Codor pentru fluxuri

Când lucrați cu io.Reader/io.Writer (corp HTTP, fișiere uriașe) utilizați Decoder și Encoder în loc să încărcați totul în memorie:

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 acceptă, de asemenea, dec.Token() pentru analizarea în flux bucată cu bucată și dec.DisallowUnknownFields() pentru a respinge JSON cu chei neașteptate (utilă pentru validarea intrării).

Hărți generice și any

Dacă nu cunoașteți schema, deserializați în map[string]any:

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

Valorile vor avea tipuri dinamice (string, float64 pentru numere, []any, map[string]any, bool, _IN_LINE_21___).

Erori comune

  • Uitând &: json.Unmarshal(data, v) nu populează nimic; aveți nevoie de &v.
  • Decodificarea structurilor cu câmpuri zero: pentru a evita panica, verificați err ÎNAINTE de a citi câmpurile.
  • Tipuri incompatibile: deserializarea unui număr într-un șir sau invers returnează *json.UnmarshalTypeError.

Exerciții

Exercițiu#go.m8.l5.e1
Încercări: 0Se încarcă…

Serializați structura u în JSON cu json.Marshal și imprimați rezultatul ca șir.

Se încarcă editorul...

Soluție disponibilă după 3 încercări

Exercițiu#go.m8.l5.e2
Încercări: 0Se încarcă…

Deserializați `{"Name":"Ada"}` în structura U cu json.Unmarshal și imprimați-o.

Se încarcă editorul...

Soluție disponibilă după 3 încercări

Quiz#go.m8.l5.e3
Gata

Este câmpul „șir de nume” (minuscule) al unei structuri inclus de json.Marshal?

Go
type U struct {
  name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))
Opțiuni de răspuns