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:
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)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:
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:
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:
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:
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
Serializați structura u în JSON cu json.Marshal și imprimați rezultatul ca șir.
Soluție disponibilă după 3 încercări
Deserializați `{"Name":"Ada"}` în structura U cu json.Unmarshal și imprimați-o.
Soluție disponibilă după 3 încercări
Este câmpul „șir de nume” (minuscule) al unei structuri inclus de json.Marshal?
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))