Przejdź do głównej treści
eLearner.app
Moduł 8 · Lekcja 5 z 540/50 w kursie~14 min
Lekcje modułu (5/5)

`encoding/json`

encoding/json to pakiet kanoniczny do serializacji struktur Go do formatu JSON i z powrotem. Znajomość jego konwencji i pułapek pozwala zaoszczędzić wiele godzin debugowania interfejsów API i plików konfiguracyjnych.

Marszałek i Unmarszałek

Dwie główne funkcje:

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)

Aby uzyskać wcięte dane wyjściowe (czytelne dla człowieka), użyj json.MarshalIndent(v, "", " ").

Tylko wyeksportowane pola

json.Marshal serializuje tylko wyeksportowane pola (wielkie litery). Pola prywatne są ignorowane po cichu:

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

Tagi struktur: kontrolowanie nazwy i opcji

Tagi json:"..." kontrolują nazwę, pominięcie i typy na wyjściu:

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
}

Najczęściej używane opcje:

  • ,omitempty — pomija pole jeśli jest to wartość zerowa (0, "", nil, pusty plasterek/mapa).
  • ,- — nigdy nie serializowany/deserializowany.
  • ,string — zawija liczby/boole jako ciągi znaków (przydatne w przypadku identyfikatorów JS).

Dekoder/koder dla strumieni

Podczas pracy z io.Reader/io.Writer (treść HTTP, duże pliki) używaj Decoder i Encoder zamiast ładować wszystko do pamięci:

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 obsługuje także dec.Token() do analizy strumieniowej kawałek po kawałku i dec.DisallowUnknownFields() do odrzucania JSON z nieoczekiwanymi kluczami (przydatne do sprawdzania poprawności danych wejściowych).

Mapy ogólne i any

Jeśli nie znasz schematu, deserializuj do map[string]any:

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

Wartości będą miały typy dynamiczne (string, float64 dla liczb, []any, map[string]any, bool, nil).

Typowe błędy

  • Zapominanie &: json.Unmarshal(data, v) niczego nie wypełnia; potrzebujesz &v.
  • Dekodowanie struktur z polami zerowymi: aby uniknąć paniki, sprawdź err PRZED odczytaniem pól.
  • Niekompatybilne typy: deserializacja liczby na ciąg znaków lub odwrotnie zwraca *json.UnmarshalTypeError.

Ćwiczenia

Ćwiczenie#go.m8.l5.e1
Próby: 0Ładowanie...

Serializuj strukturę u do JSON za pomocą json.Marshal i wydrukuj wynik jako ciąg znaków.

Ładowanie edytora...

Rozwiązanie dostępne po 3 próbach

Ćwiczenie#go.m8.l5.e2
Próby: 0Ładowanie...

Deserializuj `{"Name":"Ada"}` do struktury U za pomocą json.Unmarshal i wydrukuj go.

Ładowanie edytora...

Rozwiązanie dostępne po 3 próbach

Quiz#go.m8.l5.e3
Gotowe

Czy pole `name string` (małe litery) struktury jest zawarte w json.Marshal?

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