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.user := User{ID: 1, Name: "Oleg"} b, _ := json.Marshal(user) fmt.Println(string(b)) // {"id":1,"name":"Oleg","age":"0"}
var u User json.Unmarshal([]byte('{"id":2,"name":"Iwan"}'), &u)
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! }
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.