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、 空配列、空マップ、空文字など)の場合、エンコーディング時にフィールドを省略する -
"-"
タグは、エンコーディング、デコーディング時に常にフィールドを省略する