はじめに

構造体を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
广告
将在 10 秒后关闭
bannerAds