programowanieBackend Go Developer

Jak zaimplementowano pracę z JSON (encoding/json) w Go: szczegóły serializacji, szczegóły tagów struct, częste problemy przy marshalingu/unmarshalingu i obejścia?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

W Go marshaling JSON jest standardowo realizowany przez pakiet encoding/json. Można serializować tylko eksportowane (z dużą literą) pola struktur. Do zarządzania nazwami i ich obsługą używane są tagi struct:

type User struct { ID int `json:"id"` Name string `json:"name,omitempty"` Age int `json:"age,string"` }
  • omitempty wyklucza pole przy zerowej wartości;
  • string serializuje wartość jako ciąg znaków, nawet jeśli jest to liczba.

Przykład serializacji:

user := User{ID: 1, Name: "Oleg"} b, _ := json.Marshal(user) fmt.Println(string(b)) // {"id":1,"name":"Oleg","age":"0"}

Przykład rozbioru JSON

var u User json.Unmarshal([]byte('{"id":2,"name":"Iwan"}'), &u)

Pytanie z podstępem.

Jak są serializowane nieeksportowane (z małą literą) pola struktury przy marshalingu do JSON?

Poprawna odpowiedź: Są ignorowane, w serializacji biorą udział tylko eksportowane (z dużą literą) pola. Często nagle łamie to API:

type Foo struct { bar int // nie będzie serializowane! }

Przykłady rzeczywistych błędów z powodu braku znajomości szczegółów tematu.


Historia

Backend zwracał niepełne obiekty JSON, ponieważ część potrzebnych pól pozostała nieeksportowana (z małą literą). Kilka dni zajęło ustalenie, dlaczego klienci nie widzą tych pól.


Historia

W odpowiedzi API pole miało konstrukcję omitempty, ale czasami przychodziła pusta wartość, ponieważ zerowa wartość dla slice'a — to nil, a nie pusty slice. Klienci otrzymywali null zamiast pustej tablicy [] i padali przy parsowaniu.


Historia

W projekcie dodawano dynamiczne pola do struktur przez map[string]interface, ale zapominali o zaimplementowaniu niestandardowego UnmarshalJSON, przez co część danych "znikała" bez błędów. Dane klienta znikały i były ręcznie odzyskiwane z kopii zapasowych.