aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json/encode_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/json/encode_test.go')
-rw-r--r--src/encoding/json/encode_test.go188
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"`