はじめに
構造体をJSONに変換したときに、不要なフィールドを除外したい
valueにnullを入れるのではなく、そもそもkeyもvalueも除外したい
そのような時に使うomitemptyタグなるものがあるが、いくつかハマりポイントがあったので備忘録として残す
基本的な使い方
以下のような構造体がある
type Player struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
Weight int `json:"weight"`
}
これを以下のような形でJSONに変換する
player1 := Player{
Name: "Alice",
}
hogehoge, err := json.Marshal(player1)
// このようにして生成されるJSONは以下の通り
// {
// "name": "Alice",
// "weight": 0
// }
omitemptyタグをつけていないweightフィールドには初期値(?)の0が勝手に入っている
タグをつけたageフィールドは無視されている
しかし、公式Docによると、このようにomitemptyタグをつけることで無視できるフィールドの型は決まっている
The “omitempty” option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.
→bool型のfalse、int型などの0、nilポインタ、nilインターフェース、空のarray・slice・map、空文字あたりがomitemptyタグを使えるらしい
構造体を無視したい
では、以下のようなPlayerのフィールドにあるItem構造体を無視したい場合はどうすれば良いか?
type Player struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
Weight int `json:"weight"`
Item Item `json:"item,omitempty"`
}
type Item struct {
Name string `json:"name"`
Price int `json:"price"`
}
まず、素直にItemにomitemptyタグをつけてみると、
player1 := Player{
Name: "Alice",
}
hogehoge, err := json.Marshal(player1)
// このようにして生成されるJSONは以下の通り
// {
// "name": "Alice",
// "weight": 0,
// "item": null,
// }
上記のように、itemは無視されず、nullが入ってしまう
これを回避するには、ポインタを使えば良い
type Player struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
Weight int `json:"weight"`
Item *Item `json:"item,omitempty"`
}
omitemptyタグでnilポインタは無視することができるので、
player1 := Player{
Name: "Alice",
}
hogehoge, err := json.Marshal(player1)
// このようにして生成されるJSONは以下の通り
// {
// "name": "Alice",
// "weight": 0
// }
nullは無視したいけど0は許可したい
例えば、int型のフィールドで、nullの場合はJSONに含めたくないけど、0の場合は含めたいことがある
このような場合にもポインタ型が役立つ
type Player struct {
Name string `json:"name"`
Age *int `json:"age,omitempty"`
Weight int `json:"weight,omitempty"`
}
zero := 0
player1 := Player{
Name: "Alice",
Age: &zero,
Weight: 0,
}
hogehoge, err := json.Marshal(player1)
// このようにして生成されるJSONは以下の通り
// {
// "name": "Alice",
// "age": 0
// }
omitemptyタグのつけかたに注意!!
これは、もしかしたら超基本的なことなのかもしれないが、以下のように記述するとomitemptyが上手く働かない
type Player struct {
Name string `json:"name"`
Age int `json:"age, omitempty"`
Weight int `json:"weight"`
}
`json:”age, omitempty”`
この部分の,とomitemptyの間に半角スペースがあることが悪さをしているらしい
なので、正しくは以下の通り
type Player struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
Weight int `json:"weight"`
}
さいごに
omitemptyに限らず、しっかりと公式Doc読むの大事!
ポインタが便利
参考
-
- json – The Go Programming Language
-
- Structをomitemptyする方法 – Qiita
- Go’s “omitempty” explained