En Go, le marshalling JSON est standardisé via le package encoding/json. Seuls les champs exportés (avec une majuscule) des structures peuvent être sérialisés. Pour gérer les noms et le traitement, on utilise des tags struct :
type User struct { ID int `json:"id"` Name string `json:"name,omitempty"` Age int `json:"age,string"` }
omitempty exclut le champ si sa valeur est nulle ;string sérialise la valeur comme une chaîne, même si c'est un nombre.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":"Ivan"}'), &u)
Comment les champs non exportés (avec une minuscule) d'une structure sont-ils sérialisés lors du marshalling en JSON ?
Réponse correcte : Ils sont ignorés, seuls les champs exportés (avec une majuscule) participent à la sérialisation. Cela casse souvent l'API de manière surprenante :
type Foo struct { bar int // ne sera pas sérialisé ! }
Histoire
Le backend fournissait des objets JSON incomplets, car certains champs nécessaires étaient restés non exportés (avec une minuscule). Plusieurs jours ont été nécessaires pour comprendre pourquoi les clients ne voyaient pas ces champs.
Histoire
Dans la réponse de l'API, un champ contenait la construction omitempty, mais parfois une valeur vide arrivait, car la valeur nulle pour un tableau est nil, et non un tableau vide. Les clients recevaient null au lieu d'un tableau vide [] et échouaient lors du parsing.
Histoire
Dans le projet, des champs dynamiques étaient ajoutés aux structures via map[string]interface{}, mais on oubliait de mettre en œuvre un UnmarshalJSON personnalisé, ce qui entraînait la perte de certaines données sans erreur. Les données clients étaient perdues et récupérées manuellement à partir de sauvegardes.