はじめに
構造体を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読むの大事!
ポインタが便利