Goでは、JSONマシュアルは標準でencoding/jsonパッケージを通じて実装されています。シリアライズできるのはエクスポートされた(大文字の)構造体のフィールドのみです。名前と処理の管理には構造体のタグを使用します:
type User struct { ID int `json:"id"` Name string `json:"name,omitempty"` Age int `json:"age,string"` }
omitemptyはフィールドがゼロ値の場合に除外されます;stringは値を文字列としてシリアライズし、たとえそれが数値でもです。user := User{ID: 1, Name: "オレグ"} b, _ := json.Marshal(user) fmt.Println(string(b)) // {"id":1,"name":"オレグ","age":"0"}
var u User json.Unmarshal([]byte('{"id":2,"name":"イワン"}'), &u)
JSONでマシュアル時、非エクスポートされた(小文字の)構造体フィールドはどのようにシリアライズされますか?
正しい答え: それらは無視され、シリアライズにはエクスポートされた(大文字の)フィールドのみが参加します。これはAPIを妨げることがよくあります:
type Foo struct { bar int // シリアル化されません! }
物語
バックエンドは不完全なJSONオブジェクトを返しました。必要なフィールドの一部が非エクスポート(小文字)であったためです。クライアントがこれらのフィールドを見ない理由を特定するのに数日かかりました。
物語
APIの応答にフィールドがomitemptyの構造を含んでいましたが、ゼロ値のスライスはnilであり、空のスライスではないため、時々空の値が返されました。クライアントは空の配列[]の代わりにnullを受け取り、解析時にクラッシュしました。
物語
プロジェクトでは、構造体に動的フィールドをmap[string]interface{}を通じて混ぜましたが、カスタムのUnmarshalJSONを実装することを忘れたため、データの一部がエラーなしに「失われる」ことがありました。クライアントのデータは失われ、手動でバックアップから復元されました。