LoginSignup
35
24

More than 3 years have passed since last update.

Goのjsonのomitemptyや-(ハイフン)の挙動

Posted at

Goのomitemptyオプションや-タグの挙動がいまいちわからなかったので確認してみました。

    type Hoge struct {
        Foo string `json:"foo,omitempty"`
        Bar string `json:"-"`
    }

結論

結論としては次のような挙動になるようでした。ドキュメントにも書かれてますが。。。

  • omitemptyオプションは、フィールドの値が空の値(false, 0, nil、 空配列、空マップ、空文字など)の場合、エンコーディング時にフィールドを省略する
  • "-"タグは、エンコーディング、デコーディング時に常にフィールドを省略する

検証結果

ドキュメント確認

まずは、公式ドキュメントを読むとそれぞれ次のように記載されています。

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.

"omitempty"オプションはフィールドが空の値のときにエンコーディング時に省略される。

As a special case, if the field tag is "-", the field is always omitted. Note that a field with name "-" can still be generated using the tag "-,".

フィールドタグの"-"は常に省略される。もし-をフィールド名に使いたい場合は"-,"と指定する

動作確認

ここまででなんとなくわかるのですが一応動作確認してみます。(go 1.14)
デコード時の挙動はいまいちわかりませんので。。。

まずjson.Marshalでエンコーディング時にどうなるか確認してみます。
結果として、"omitempty", "-"があるフィールドは省略されてることがわかります。

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    type Hoge struct {
        Field1 string `json:"field1"`

        // "omitempty" オプションは、フィールドの値が空の値の場合
        // エンコーディングするときに省略される
        Field2 string `json:"field2,omitempty"`

        // "-" は常にフィールドは省略される
        Field3 string `json:"-"`
    }

    hoge := Hoge{
        Field1: "",
        Field2: "",
        Field3: "something",
    }

    b, err := json.Marshal(hoge)
    if err != nil {
        fmt.Printf("error: %+v\n", err)
        return
    }

    // "omitempty", "-" を指定したフィールドが省略されていることがわかります
    fmt.Printf("%s\n", string(b))
    //=> {"field1":""} 
}

次にjson.Unmarshalでデコード時にどのようになるか確認してみます。
デコード時にはomitemptyは問題なくデコードされ、"-"タグは省略される(フィールドの値は初期値)ようです。

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    type Hoge struct {
        Field1 string `json:"field1"`

        // "omitempty" オプションは、フィールドの値が空の値の場合
        // エンコーディングするときに省略される
        Field2 string `json:"field2,omitempty"`

        // "-" は、常にフィールドは省略される
        Field3 string `json:"-"`
    }

    jsonBlob := []byte(`[
    {"field1": "someting1", "field2": "something2", "field3": "something3"},
    {"field1": null,        "field2": null,         "field3": null}
]`)

    var hoges []Hoge
    err := json.Unmarshal(jsonBlob, &hoges)
    if err != nil {
        fmt.Println("error:", err)
        return
    }

    // デコード時には`omitempty`は問題なくデコードされ、
    // `"-"`タグは省略される(フィールドの値は初期値)ようです。
    fmt.Printf("%+v\n", hoges)
    //=> [{Field1:someting1 Field2:something2 Field3:} {Field1: Field2: Field3:}]
}

結論(再掲)

  • omitemptyオプションは、フィールドの値が空の値(false, 0, nil、 空配列、空マップ、空文字など)の場合、エンコーディング時にフィールドを省略する
  • "-"タグは、エンコーディング、デコーディング時に常にフィールドを省略する
35
24
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
35
24