diff options
| author | Jes Cok <xigua67damn@gmail.com> | 2024-10-01 03:15:08 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-10-02 14:22:27 +0000 |
| commit | e86982c515ba4a494fb1f8e1367f4238a2b59c2e (patch) | |
| tree | f6e5d0f5832ae30c309e5815d209f364a1ee5d38 /src/encoding/json/encode_test.go | |
| parent | 41d189a3f68bbda96fcaf83b7db5d69d51c58bcf (diff) | |
| download | go-e86982c515ba4a494fb1f8e1367f4238a2b59c2e.tar.xz | |
encoding/json: add omitzero option
Fixes #45669
Change-Id: Ic13523c0b3acdfc5b3e29a717bc62fde302ed8fd
GitHub-Last-Rev: 57030f26b0062fa8eda21b3a73b7665deab88c76
GitHub-Pull-Request: golang/go#69622
Reviewed-on: https://go-review.googlesource.com/c/go/+/615676
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/encoding/json/encode_test.go')
| -rw-r--r-- | src/encoding/json/encode_test.go | 188 |
1 files changed, 185 insertions, 3 deletions
diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go index 23a14d0b17..79c481754e 100644 --- a/src/encoding/json/encode_test.go +++ b/src/encoding/json/encode_test.go @@ -15,9 +15,10 @@ import ( "runtime/debug" "strconv" "testing" + "time" ) -type Optionals struct { +type OptionalsEmpty struct { Sr string `json:"sr"` So string `json:"so,omitempty"` Sw string `json:"-"` @@ -45,7 +46,7 @@ type Optionals struct { } func TestOmitEmpty(t *testing.T) { - var want = `{ + const want = `{ "sr": "", "omitempty": 0, "slr": null, @@ -56,7 +57,7 @@ func TestOmitEmpty(t *testing.T) { "str": {}, "sto": {} }` - var o Optionals + var o OptionalsEmpty o.Sw = "something" o.Mr = map[string]any{} o.Mo = map[string]any{} @@ -70,6 +71,187 @@ func TestOmitEmpty(t *testing.T) { } } +type NonZeroStruct struct{} + +func (nzs NonZeroStruct) IsZero() bool { + return false +} + +type NoPanicStruct struct { + Int int `json:"int,omitzero"` +} + +func (nps *NoPanicStruct) IsZero() bool { + return nps.Int != 0 +} + +type OptionalsZero struct { + Sr string `json:"sr"` + So string `json:"so,omitzero"` + Sw string `json:"-"` + + Ir int `json:"omitzero"` // actually named omitzero, not an option + Io int `json:"io,omitzero"` + + Slr []string `json:"slr,random"` + Slo []string `json:"slo,omitzero"` + SloNonNil []string `json:"slononnil,omitzero"` + + Mr map[string]any `json:"mr"` + Mo map[string]any `json:",omitzero"` + Moo map[string]any `json:"moo,omitzero"` + + Fr float64 `json:"fr"` + Fo float64 `json:"fo,omitzero"` + Foo float64 `json:"foo,omitzero"` + Foo2 [2]float64 `json:"foo2,omitzero"` + + Br bool `json:"br"` + Bo bool `json:"bo,omitzero"` + + Ur uint `json:"ur"` + Uo uint `json:"uo,omitzero"` + + Str struct{} `json:"str"` + Sto struct{} `json:"sto,omitzero"` + + Time time.Time `json:"time,omitzero"` + TimeLocal time.Time `json:"timelocal,omitzero"` + Nzs NonZeroStruct `json:"nzs,omitzero"` + + NilIsZeroer isZeroer `json:"niliszeroer,omitzero"` // nil interface + NonNilIsZeroer isZeroer `json:"nonniliszeroer,omitzero"` // non-nil interface + NoPanicStruct0 isZeroer `json:"nps0,omitzero"` // non-nil interface with nil pointer + NoPanicStruct1 isZeroer `json:"nps1,omitzero"` // non-nil interface with non-nil pointer + NoPanicStruct2 *NoPanicStruct `json:"nps2,omitzero"` // nil pointer + NoPanicStruct3 *NoPanicStruct `json:"nps3,omitzero"` // non-nil pointer + NoPanicStruct4 NoPanicStruct `json:"nps4,omitzero"` // concrete type +} + +func TestOmitZero(t *testing.T) { + const want = `{ + "sr": "", + "omitzero": 0, + "slr": null, + "slononnil": [], + "mr": {}, + "Mo": {}, + "fr": 0, + "br": false, + "ur": 0, + "str": {}, + "nzs": {}, + "nps1": {}, + "nps3": {}, + "nps4": {} +}` + var o OptionalsZero + o.Sw = "something" + o.SloNonNil = make([]string, 0) + o.Mr = map[string]any{} + o.Mo = map[string]any{} + + o.Foo = -0 + o.Foo2 = [2]float64{+0, -0} + + o.TimeLocal = time.Time{}.Local() + + o.NonNilIsZeroer = time.Time{} + o.NoPanicStruct0 = (*NoPanicStruct)(nil) + o.NoPanicStruct1 = &NoPanicStruct{} + o.NoPanicStruct3 = &NoPanicStruct{} + + got, err := MarshalIndent(&o, "", " ") + if err != nil { + t.Fatalf("MarshalIndent error: %v", err) + } + if got := string(got); got != want { + t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want)) + } +} + +func TestOmitZeroMap(t *testing.T) { + const want = `{ + "foo": { + "sr": "", + "omitzero": 0, + "slr": null, + "mr": null, + "fr": 0, + "br": false, + "ur": 0, + "str": {}, + "nzs": {}, + "nps4": {} + } +}` + m := map[string]OptionalsZero{"foo": {}} + got, err := MarshalIndent(m, "", " ") + if err != nil { + t.Fatalf("MarshalIndent error: %v", err) + } + if got := string(got); got != want { + fmt.Println(got) + t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want)) + } +} + +type OptionalsEmptyZero struct { + Sr string `json:"sr"` + So string `json:"so,omitempty,omitzero"` + Sw string `json:"-"` + + Io int `json:"io,omitempty,omitzero"` + + Slr []string `json:"slr,random"` + Slo []string `json:"slo,omitempty,omitzero"` + SloNonNil []string `json:"slononnil,omitempty,omitzero"` + + Mr map[string]any `json:"mr"` + Mo map[string]any `json:",omitempty,omitzero"` + + Fr float64 `json:"fr"` + Fo float64 `json:"fo,omitempty,omitzero"` + + Br bool `json:"br"` + Bo bool `json:"bo,omitempty,omitzero"` + + Ur uint `json:"ur"` + Uo uint `json:"uo,omitempty,omitzero"` + + Str struct{} `json:"str"` + Sto struct{} `json:"sto,omitempty,omitzero"` + + Time time.Time `json:"time,omitempty,omitzero"` + Nzs NonZeroStruct `json:"nzs,omitempty,omitzero"` +} + +func TestOmitEmptyZero(t *testing.T) { + const want = `{ + "sr": "", + "slr": null, + "mr": {}, + "fr": 0, + "br": false, + "ur": 0, + "str": {}, + "nzs": {} +}` + var o OptionalsEmptyZero + o.Sw = "something" + o.SloNonNil = make([]string, 0) + o.Mr = map[string]any{} + o.Mo = map[string]any{} + + got, err := MarshalIndent(&o, "", " ") + if err != nil { + t.Fatalf("MarshalIndent error: %v", err) + } + if got := string(got); got != want { + t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want)) + } +} + type StringTag struct { BoolStr bool `json:",string"` IntStr int64 `json:",string"` |
