[インデックス 18148] ファイルの概要
このコミットは、Go言語の標準ライブラリ encoding/json パッケージにおける omitempty タグのテストカバレッジを向上させることを目的としています。具体的には、float64、bool、uint、および空の構造体 (struct{}) 型に対して omitempty タグがどのように機能するかを確認するための新しいテストケースが追加されています。
コミット
commit a39f3b29ec47fb9ed73fc922a44b5e6ff931073d
Author: Shawn Smith <shawn.p.smith@gmail.com>
Date: Wed Jan 1 17:54:06 2014 +1100
encoding/json: improve omitempty test coverage
R=golang-codereviews, dave, bradfitz
CC=golang-codereviews
https://golang.org/cl/46250043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a39f3b29ec47fb9ed73fc922a44b5e6ff931073d
元コミット内容
encoding/json: improve omitempty test coverage
変更の背景
Go言語の encoding/json パッケージは、Goの構造体とJSONデータの間で変換を行うための標準的な方法を提供します。構造体のフィールドに json:"fieldName,omitempty" のように omitempty タグが指定されている場合、そのフィールドの値が型の「ゼロ値」であるとき、JSON出力からそのフィールドが省略されます。
このコミットの背景には、omitempty タグの挙動が様々なデータ型で正しく機能することを保証するためのテストカバレッジの不足があったと考えられます。特に、float64 (0.0)、bool (false)、uint (0)、そして空の構造体 (struct{}) のような、直感的にゼロ値と認識されにくい、あるいはその挙動が曖昧になりがちな型に対する omitempty の振る舞いを明確にし、テストで検証する必要がありました。これにより、開発者が omitempty タグを安心して利用できるよう、ライブラリの堅牢性を高めることが目的です。
前提知識の解説
Go言語の encoding/json パッケージ
encoding/json パッケージは、Goのデータ構造をJSON形式にエンコード(Marshal)したり、JSONデータをGoのデータ構造にデコード(Unmarshal)したりするための機能を提供します。
JSONタグ
Goの構造体のフィールドには、json:"fieldName" のような「タグ」を付与することができます。これにより、JSONエンコード/デコード時のフィールド名や挙動をカスタマイズできます。
omitempty タグ
omitempty はJSONタグのオプションの一つです。構造体のフィールドに json:"fieldName,omitempty" と指定すると、そのフィールドの値がGoの型の「ゼロ値」である場合に、JSON出力からそのフィールドが完全に省略されます。
各型のゼロ値は以下の通りです。
- 数値型 (int, float64, uintなど):
0 - bool型:
false - string型:
""(空文字列) - ポインタ、スライス、マップ、チャネル、関数、インターフェース:
nil - 構造体: その構造体のすべてのフィールドがそれぞれのゼロ値である場合
このコミットでは、特に float64 (0.0)、bool (false)、uint (0)、そして struct{} (空の構造体) のゼロ値に対する omitempty の挙動がテストされています。struct{} は、メモリを消費しない特殊な構造体で、セットのような用途で使われることがあります。そのゼロ値は、struct{} 型のインスタンスそのものです。
技術的詳細
このコミットは、encoding/json パッケージのテストファイル encode_test.go に新しいフィールドと期待されるJSON出力の変更を追加することで、omitempty タグのテストカバレッジを向上させています。
具体的には、Optionals というテスト用の構造体に以下のフィールドが追加されました。
Fr float64json:"fr":float64` 型の必須フィールド。Fo float64json:"fo,omitempty":float64型でomitempty` が適用されるフィールド。Br booljson:"br":bool` 型の必須フィールド。Bo booljson:"bo,omitempty":bool型でomitempty` が適用されるフィールド。Ur uintjson:"ur":uint` 型の必須フィールド。Uo uintjson:"uo,omitempty":uint型でomitempty` が適用されるフィールド。Str struct{}json:"str": 空の構造体struct{}型の必須フィールド。Sto struct{}json:"sto,omitempty": 空の構造体struct{}型でomitemptyが適用されるフィールド。
これらのフィールドは、Optionals 構造体のインスタンスが初期化された際に、それぞれの型のゼロ値(0.0、false、0、{})を持つことになります。
そして、optionalsExpected という期待されるJSON文字列が更新され、これらの新しいフィールドが omitempty タグなしで定義されている場合はJSON出力に含まれ、omitempty タグ付きで定義されている場合はゼロ値のときに省略されることを検証しています。特に struct{} の場合、omitempty が付いていても、その値がゼロ値(つまり struct{} そのもの)であれば省略されるべきですが、このテストでは Sto フィールドが optionalsExpected に含まれています。これは、struct{} のゼロ値は struct{} そのものであり、omitempty が付いていても、そのフィールドが構造体として存在する場合は出力されるという挙動をテストしている可能性があります。しかし、一般的な omitempty の挙動からすると、struct{} のゼロ値は省略されるべきです。このコミットの変更点を見ると、"sto": {} が optionalsExpected に追加されているため、struct{} のゼロ値は omitempty が付いていても出力されるという挙動をテストしているように見えます。これは、struct{} が他の型とは異なる omitempty の振る舞いをする可能性を示唆しています。
コアとなるコードの変更箇所
変更は src/pkg/encoding/json/encode_test.go ファイルに集中しています。
--- a/src/pkg/encoding/json/encode_test.go
+++ b/src/pkg/encoding/json/encode_test.go
@@ -25,13 +25,30 @@ type Optionals struct {
Mr map[string]interface{} `json:"mr"`
Mo map[string]interface{} `json:",omitempty"`
+
+ Fr float64 `json:"fr"`
+ Fo float64 `json:"fo,omitempty"`
+
+ Br bool `json:"br"`
+ Bo bool `json:"bo,omitempty"`
+
+ Ur uint `json:"ur"`
+ Uo uint `json:"uo,omitempty"`
+
+ Str struct{} `json:"str"`
+ Sto struct{} `json:"sto,omitempty"`
}
var optionalsExpected = `{
"sr": "",
"omitempty": 0,
"slr": null,
- "mr": {}
+ "mr": {},
+ "fr": 0,
+ "br": false,
+ "ur": 0,
+ "str": {},
+ "sto": {}
}`
func TestOmitEmpty(t *testing.T) {
コアとなるコードの解説
Optionals 構造体へのフィールド追加
Optionals 構造体は、encoding/json パッケージの omitempty タグの挙動をテストするために使用されます。このコミットでは、以下のフィールドが追加されました。
Fr float64json:"fr":float64型のフィールドFrは、JSON出力ではfrというキーになります。omitempty` タグがないため、値がゼロ値 (0.0) であってもJSON出力に含まれます。Fo float64json:"fo,omitempty":float64型のフィールドFoは、JSON出力ではfoというキーになります。omitempty` タグがあるため、値がゼロ値 (0.0) の場合はJSON出力から省略されます。Br booljson:"br":bool型のフィールドBrは、JSON出力ではbrというキーになります。omitempty` タグがないため、値がゼロ値 (false) であってもJSON出力に含まれます。Bo booljson:"bo,omitempty":bool型のフィールドBoは、JSON出力ではboというキーになります。omitempty` タグがあるため、値がゼロ値 (false) の場合はJSON出力から省略されます。Ur uintjson:"ur":uint型のフィールドUrは、JSON出力ではurというキーになります。omitempty` タグがないため、値がゼロ値 (0) であってもJSON出力に含まれます。Uo uintjson:"uo,omitempty":uint型のフィールドUoは、JSON出力ではuoというキーになります。omitempty` タグがあるため、値がゼロ値 (0) の場合はJSON出力から省略されます。Str struct{}json:"str": 空の構造体struct{}型のフィールドStrは、JSON出力ではstrというキーになります。omitemptyタグがないため、値がゼロ値 ({}) であってもJSON出力に含まれます。Sto struct{}json:"sto,omitempty": 空の構造体struct{}型のフィールドStoは、JSON出力ではstoというキーになります。omitemptyタグがあるため、値がゼロ値 ({}) の場合はJSON出力から省略されるはずですが、optionalsExpectedの変更を見ると、"sto": {}が含まれています。これは、struct{}のゼロ値に対するomitemptyの挙動が他の型とは異なり、常に{}として出力されることをテストしている可能性があります。
optionalsExpected 変数の更新
optionalsExpected は、Optionals 構造体をJSONエンコードした際に期待されるJSON文字列を定義しています。このコミットでは、上記で追加されたフィールドに対応するために、この文字列が更新されました。
"fr": 0,:Frフィールドはomitemptyがないため、ゼロ値 (0.0) であってもJSONに含まれます。"br": false,:Brフィールドはomitemptyがないため、ゼロ値 (false) であってもJSONに含まれます。"ur": 0,:Urフィールドはomitemptyがないため、ゼロ値 (0) であってもJSONに含まれます。"str": {},:Strフィールドはomitemptyがないため、ゼロ値 ({}) であってもJSONに含まれます。"sto": {}:Stoフィールドはomitemptyがありますが、struct{}のゼロ値は{}として出力されることをテストしています。これは、struct{}のゼロ値が他の型のゼロ値とは異なる扱いを受けることを示唆しています。
これらの変更により、TestOmitEmpty 関数は、Optionals 構造体のインスタンスをJSONエンコードし、その結果が optionalsExpected と一致するかどうかを検証します。これにより、float64、bool、uint、struct{} 型に対する omitempty の挙動が正しく実装されていることを確認できます。
関連リンク
- Go言語
encoding/jsonパッケージのドキュメント: https://pkg.go.dev/encoding/json - Go言語の
omitemptyタグに関する公式ブログ記事 (もしあれば、検索して追加)
参考にした情報源リンク
- https://github.com/golang/go/commit/a39f3b29ec47fb9ed73fc922a44b5e6ff931073d
- Go言語の
encoding/jsonパッケージに関する一般的な情報 (Web検索結果に基づく) - Go言語のゼロ値に関する情報 (Web検索結果に基づく)
- Go言語の
struct{}型に関する情報 (Web検索結果に基づく)