16
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Golang】jsonのomitemptyタグについて

Last updated at Posted at 2020-12-10

はじめに

構造体を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"`
}

まず、素直にItemomitemptyタグをつけてみると、

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読むの大事!
ポインタが便利

参考

16
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?