Source file
src/encoding/json/v2_encode_test.go
1
2
3
4
5
6
7 package json
8
9 import (
10 "bytes"
11 "encoding"
12 "fmt"
13 "log"
14 "math"
15 "reflect"
16 "regexp"
17 "runtime/debug"
18 "strconv"
19 "sync"
20 "testing"
21 "testing/synctest"
22 "time"
23 )
24
25 type OptionalsEmpty struct {
26 Sr string `json:"sr"`
27 So string `json:"so,omitempty"`
28 Sw string `json:"-"`
29
30 Ir int `json:"omitempty"`
31 Io int `json:"io,omitempty"`
32
33 Slr []string `json:"slr,random"`
34 Slo []string `json:"slo,omitempty"`
35
36 Mr map[string]any `json:"mr"`
37 Mo map[string]any `json:",omitempty"`
38
39 Fr float64 `json:"fr"`
40 Fo float64 `json:"fo,omitempty"`
41
42 Br bool `json:"br"`
43 Bo bool `json:"bo,omitempty"`
44
45 Ur uint `json:"ur"`
46 Uo uint `json:"uo,omitempty"`
47
48 Str struct{} `json:"str"`
49 Sto struct{} `json:"sto,omitempty"`
50 }
51
52 func TestOmitEmpty(t *testing.T) {
53 const want = `{
54 "sr": "",
55 "omitempty": 0,
56 "slr": null,
57 "mr": {},
58 "fr": 0,
59 "br": false,
60 "ur": 0,
61 "str": {},
62 "sto": {}
63 }`
64 var o OptionalsEmpty
65 o.Sw = "something"
66 o.Mr = map[string]any{}
67 o.Mo = map[string]any{}
68
69 got, err := MarshalIndent(&o, "", " ")
70 if err != nil {
71 t.Fatalf("MarshalIndent error: %v", err)
72 }
73 if got := string(got); got != want {
74 t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))
75 }
76 }
77
78 type NonZeroStruct struct{}
79
80 func (nzs NonZeroStruct) IsZero() bool {
81 return false
82 }
83
84 type NoPanicStruct struct {
85 Int int `json:"int,omitzero"`
86 }
87
88 func (nps *NoPanicStruct) IsZero() bool {
89 return nps.Int != 0
90 }
91
92 type isZeroer interface {
93 IsZero() bool
94 }
95
96 type OptionalsZero struct {
97 Sr string `json:"sr"`
98 So string `json:"so,omitzero"`
99 Sw string `json:"-"`
100
101 Ir int `json:"omitzero"`
102 Io int `json:"io,omitzero"`
103
104 Slr []string `json:"slr,random"`
105 Slo []string `json:"slo,omitzero"`
106 SloNonNil []string `json:"slononnil,omitzero"`
107
108 Mr map[string]any `json:"mr"`
109 Mo map[string]any `json:",omitzero"`
110 Moo map[string]any `json:"moo,omitzero"`
111
112 Fr float64 `json:"fr"`
113 Fo float64 `json:"fo,omitzero"`
114 Foo float64 `json:"foo,omitzero"`
115 Foo2 [2]float64 `json:"foo2,omitzero"`
116
117 Br bool `json:"br"`
118 Bo bool `json:"bo,omitzero"`
119
120 Ur uint `json:"ur"`
121 Uo uint `json:"uo,omitzero"`
122
123 Str struct{} `json:"str"`
124 Sto struct{} `json:"sto,omitzero"`
125
126 Time time.Time `json:"time,omitzero"`
127 TimeLocal time.Time `json:"timelocal,omitzero"`
128 Nzs NonZeroStruct `json:"nzs,omitzero"`
129
130 NilIsZeroer isZeroer `json:"niliszeroer,omitzero"`
131 NonNilIsZeroer isZeroer `json:"nonniliszeroer,omitzero"`
132 NoPanicStruct0 isZeroer `json:"nps0,omitzero"`
133 NoPanicStruct1 isZeroer `json:"nps1,omitzero"`
134 NoPanicStruct2 *NoPanicStruct `json:"nps2,omitzero"`
135 NoPanicStruct3 *NoPanicStruct `json:"nps3,omitzero"`
136 NoPanicStruct4 NoPanicStruct `json:"nps4,omitzero"`
137 }
138
139 func TestOmitZero(t *testing.T) {
140 const want = `{
141 "sr": "",
142 "omitzero": 0,
143 "slr": null,
144 "slononnil": [],
145 "mr": {},
146 "Mo": {},
147 "fr": 0,
148 "br": false,
149 "ur": 0,
150 "str": {},
151 "nzs": {},
152 "nps1": {},
153 "nps3": {},
154 "nps4": {}
155 }`
156 var o OptionalsZero
157 o.Sw = "something"
158 o.SloNonNil = make([]string, 0)
159 o.Mr = map[string]any{}
160 o.Mo = map[string]any{}
161
162 o.Foo = -0
163 o.Foo2 = [2]float64{+0, -0}
164
165 o.TimeLocal = time.Time{}.Local()
166
167 o.NonNilIsZeroer = time.Time{}
168 o.NoPanicStruct0 = (*NoPanicStruct)(nil)
169 o.NoPanicStruct1 = &NoPanicStruct{}
170 o.NoPanicStruct3 = &NoPanicStruct{}
171
172 got, err := MarshalIndent(&o, "", " ")
173 if err != nil {
174 t.Fatalf("MarshalIndent error: %v", err)
175 }
176 if got := string(got); got != want {
177 t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))
178 }
179 }
180
181 func TestOmitZeroMap(t *testing.T) {
182 const want = `{
183 "foo": {
184 "sr": "",
185 "omitzero": 0,
186 "slr": null,
187 "mr": null,
188 "fr": 0,
189 "br": false,
190 "ur": 0,
191 "str": {},
192 "nzs": {},
193 "nps4": {}
194 }
195 }`
196 m := map[string]OptionalsZero{"foo": {}}
197 got, err := MarshalIndent(m, "", " ")
198 if err != nil {
199 t.Fatalf("MarshalIndent error: %v", err)
200 }
201 if got := string(got); got != want {
202 fmt.Println(got)
203 t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))
204 }
205 }
206
207 type OptionalsEmptyZero struct {
208 Sr string `json:"sr"`
209 So string `json:"so,omitempty,omitzero"`
210 Sw string `json:"-"`
211
212 Io int `json:"io,omitempty,omitzero"`
213
214 Slr []string `json:"slr,random"`
215 Slo []string `json:"slo,omitempty,omitzero"`
216 SloNonNil []string `json:"slononnil,omitempty,omitzero"`
217
218 Mr map[string]any `json:"mr"`
219 Mo map[string]any `json:",omitempty,omitzero"`
220
221 Fr float64 `json:"fr"`
222 Fo float64 `json:"fo,omitempty,omitzero"`
223
224 Br bool `json:"br"`
225 Bo bool `json:"bo,omitempty,omitzero"`
226
227 Ur uint `json:"ur"`
228 Uo uint `json:"uo,omitempty,omitzero"`
229
230 Str struct{} `json:"str"`
231 Sto struct{} `json:"sto,omitempty,omitzero"`
232
233 Time time.Time `json:"time,omitempty,omitzero"`
234 Nzs NonZeroStruct `json:"nzs,omitempty,omitzero"`
235 }
236
237 func TestOmitEmptyZero(t *testing.T) {
238 const want = `{
239 "sr": "",
240 "slr": null,
241 "mr": {},
242 "fr": 0,
243 "br": false,
244 "ur": 0,
245 "str": {},
246 "nzs": {}
247 }`
248 var o OptionalsEmptyZero
249 o.Sw = "something"
250 o.SloNonNil = make([]string, 0)
251 o.Mr = map[string]any{}
252 o.Mo = map[string]any{}
253
254 got, err := MarshalIndent(&o, "", " ")
255 if err != nil {
256 t.Fatalf("MarshalIndent error: %v", err)
257 }
258 if got := string(got); got != want {
259 t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))
260 }
261 }
262
263 type StringTag struct {
264 BoolStr bool `json:",string"`
265 IntStr int64 `json:",string"`
266 UintptrStr uintptr `json:",string"`
267 StrStr string `json:",string"`
268 NumberStr Number `json:",string"`
269 }
270
271 func TestRoundtripStringTag(t *testing.T) {
272 tests := []struct {
273 CaseName
274 in StringTag
275 want string
276 }{{
277 CaseName: Name("AllTypes"),
278 in: StringTag{
279 BoolStr: true,
280 IntStr: 42,
281 UintptrStr: 44,
282 StrStr: "xzbit",
283 NumberStr: "46",
284 },
285 want: `{
286 "BoolStr": "true",
287 "IntStr": "42",
288 "UintptrStr": "44",
289 "StrStr": "\"xzbit\"",
290 "NumberStr": "46"
291 }`,
292 }, {
293
294 CaseName: Name("StringDoubleEscapes"),
295 in: StringTag{
296 StrStr: "\b\f\n\r\t\"\\",
297 NumberStr: "0",
298 },
299 want: `{
300 "BoolStr": "false",
301 "IntStr": "0",
302 "UintptrStr": "0",
303 "StrStr": "\"\\b\\f\\n\\r\\t\\\"\\\\\"",
304 "NumberStr": "0"
305 }`,
306 }}
307 for _, tt := range tests {
308 t.Run(tt.Name, func(t *testing.T) {
309 got, err := MarshalIndent(&tt.in, "", "\t")
310 if err != nil {
311 t.Fatalf("%s: MarshalIndent error: %v", tt.Where, err)
312 }
313 if got := string(got); got != tt.want {
314 t.Fatalf("%s: MarshalIndent:\n\tgot: %s\n\twant: %s", tt.Where, stripWhitespace(got), stripWhitespace(tt.want))
315 }
316
317
318 var s2 StringTag
319 if err := Unmarshal(got, &s2); err != nil {
320 t.Fatalf("%s: Decode error: %v", tt.Where, err)
321 }
322 if !reflect.DeepEqual(s2, tt.in) {
323 t.Fatalf("%s: Decode:\n\tinput: %s\n\tgot: %#v\n\twant: %#v", tt.Where, indentNewlines(string(got)), s2, tt.in)
324 }
325 })
326 }
327 }
328
329
330 type renamedByte byte
331 type renamedByteSlice []byte
332 type renamedRenamedByteSlice []renamedByte
333
334 func TestEncodeRenamedByteSlice(t *testing.T) {
335 s := renamedByteSlice("abc")
336 got, err := Marshal(s)
337 if err != nil {
338 t.Fatalf("Marshal error: %v", err)
339 }
340 want := `"YWJj"`
341 if string(got) != want {
342 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
343 }
344 r := renamedRenamedByteSlice("abc")
345 got, err = Marshal(r)
346 if err != nil {
347 t.Fatalf("Marshal error: %v", err)
348 }
349 if string(got) != want {
350 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
351 }
352 }
353
354 type SamePointerNoCycle struct {
355 Ptr1, Ptr2 *SamePointerNoCycle
356 }
357
358 var samePointerNoCycle = &SamePointerNoCycle{}
359
360 type PointerCycle struct {
361 Ptr *PointerCycle
362 }
363
364 var pointerCycle = &PointerCycle{}
365
366 type PointerCycleIndirect struct {
367 Ptrs []any
368 }
369
370 type RecursiveSlice []RecursiveSlice
371
372 var (
373 pointerCycleIndirect = &PointerCycleIndirect{}
374 mapCycle = make(map[string]any)
375 sliceCycle = []any{nil}
376 sliceNoCycle = []any{nil, nil}
377 recursiveSliceCycle = []RecursiveSlice{nil}
378 )
379
380 func init() {
381 ptr := &SamePointerNoCycle{}
382 samePointerNoCycle.Ptr1 = ptr
383 samePointerNoCycle.Ptr2 = ptr
384
385 pointerCycle.Ptr = pointerCycle
386 pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect}
387
388 mapCycle["x"] = mapCycle
389 sliceCycle[0] = sliceCycle
390 sliceNoCycle[1] = sliceNoCycle[:1]
391 const startDetectingCyclesAfter = 1e3
392 for i := startDetectingCyclesAfter; i > 0; i-- {
393 sliceNoCycle = []any{sliceNoCycle}
394 }
395 recursiveSliceCycle[0] = recursiveSliceCycle
396 }
397
398 func TestSamePointerNoCycle(t *testing.T) {
399 if _, err := Marshal(samePointerNoCycle); err != nil {
400 t.Fatalf("Marshal error: %v", err)
401 }
402 }
403
404 func TestSliceNoCycle(t *testing.T) {
405 if _, err := Marshal(sliceNoCycle); err != nil {
406 t.Fatalf("Marshal error: %v", err)
407 }
408 }
409
410 func TestUnsupportedValues(t *testing.T) {
411 tests := []struct {
412 CaseName
413 in any
414 }{
415 {Name(""), math.NaN()},
416 {Name(""), math.Inf(-1)},
417 {Name(""), math.Inf(1)},
418 {Name(""), pointerCycle},
419 {Name(""), pointerCycleIndirect},
420 {Name(""), mapCycle},
421 {Name(""), sliceCycle},
422 {Name(""), recursiveSliceCycle},
423 }
424 for _, tt := range tests {
425 t.Run(tt.Name, func(t *testing.T) {
426 if _, err := Marshal(tt.in); err != nil {
427 if _, ok := err.(*UnsupportedValueError); !ok {
428 t.Errorf("%s: Marshal error:\n\tgot: %T\n\twant: %T", tt.Where, err, new(UnsupportedValueError))
429 }
430 } else {
431 t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)
432 }
433 })
434 }
435 }
436
437
438 func TestMarshalTextFloatMap(t *testing.T) {
439 m := map[textfloat]string{
440 textfloat(math.NaN()): "1",
441 textfloat(math.NaN()): "1",
442 }
443 got, err := Marshal(m)
444 if err != nil {
445 t.Errorf("Marshal error: %v", err)
446 }
447 want := `{"TF:NaN":"1","TF:NaN":"1"}`
448 if string(got) != want {
449 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
450 }
451 }
452
453
454 type Ref int
455
456 func (*Ref) MarshalJSON() ([]byte, error) {
457 return []byte(`"ref"`), nil
458 }
459
460 func (r *Ref) UnmarshalJSON([]byte) error {
461 *r = 12
462 return nil
463 }
464
465
466 type Val int
467
468 func (Val) MarshalJSON() ([]byte, error) {
469 return []byte(`"val"`), nil
470 }
471
472
473 type RefText int
474
475 func (*RefText) MarshalText() ([]byte, error) {
476 return []byte(`"ref"`), nil
477 }
478
479 func (r *RefText) UnmarshalText([]byte) error {
480 *r = 13
481 return nil
482 }
483
484
485 type ValText int
486
487 func (ValText) MarshalText() ([]byte, error) {
488 return []byte(`"val"`), nil
489 }
490
491 func TestRefValMarshal(t *testing.T) {
492 var s = struct {
493 R0 Ref
494 R1 *Ref
495 R2 RefText
496 R3 *RefText
497 V0 Val
498 V1 *Val
499 V2 ValText
500 V3 *ValText
501 }{
502 R0: 12,
503 R1: new(Ref),
504 R2: 14,
505 R3: new(RefText),
506 V0: 13,
507 V1: new(Val),
508 V2: 15,
509 V3: new(ValText),
510 }
511 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
512 b, err := Marshal(&s)
513 if err != nil {
514 t.Fatalf("Marshal error: %v", err)
515 }
516 if got := string(b); got != want {
517 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
518 }
519 }
520
521
522 type C int
523
524 func (C) MarshalJSON() ([]byte, error) {
525 return []byte(`"<&>"`), nil
526 }
527
528
529 type CText int
530
531 func (CText) MarshalText() ([]byte, error) {
532 return []byte(`"<&>"`), nil
533 }
534
535 func TestMarshalerEscaping(t *testing.T) {
536 var c C
537 want := `"\u003c\u0026\u003e"`
538 b, err := Marshal(c)
539 if err != nil {
540 t.Fatalf("Marshal error: %v", err)
541 }
542 if got := string(b); got != want {
543 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
544 }
545
546 var ct CText
547 want = `"\"\u003c\u0026\u003e\""`
548 b, err = Marshal(ct)
549 if err != nil {
550 t.Fatalf("Marshal error: %v", err)
551 }
552 if got := string(b); got != want {
553 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
554 }
555 }
556
557 func TestAnonymousFields(t *testing.T) {
558 tests := []struct {
559 CaseName
560 makeInput func() any
561 want string
562 }{{
563
564
565
566 CaseName: Name("AmbiguousField"),
567 makeInput: func() any {
568 type (
569 S1 struct{ x, X int }
570 S2 struct{ x, X int }
571 S struct {
572 S1
573 S2
574 }
575 )
576 return S{S1{1, 2}, S2{3, 4}}
577 },
578 want: `{}`,
579 }, {
580 CaseName: Name("DominantField"),
581
582
583 makeInput: func() any {
584 type (
585 S1 struct{ x, X int }
586 S2 struct{ x, X int }
587 S struct {
588 S1
589 S2
590 x, X int
591 }
592 )
593 return S{S1{1, 2}, S2{3, 4}, 5, 6}
594 },
595 want: `{"X":6}`,
596 }, {
597
598 CaseName: Name("UnexportedEmbeddedInt"),
599 makeInput: func() any {
600 type (
601 myInt int
602 S struct{ myInt }
603 )
604 return S{5}
605 },
606 want: `{}`,
607 }, {
608
609 CaseName: Name("ExportedEmbeddedInt"),
610 makeInput: func() any {
611 type (
612 MyInt int
613 S struct{ MyInt }
614 )
615 return S{5}
616 },
617 want: `{"MyInt":5}`,
618 }, {
619
620
621 CaseName: Name("UnexportedEmbeddedIntPointer"),
622 makeInput: func() any {
623 type (
624 myInt int
625 S struct{ *myInt }
626 )
627 s := S{new(myInt)}
628 *s.myInt = 5
629 return s
630 },
631 want: `{}`,
632 }, {
633
634
635 CaseName: Name("ExportedEmbeddedIntPointer"),
636 makeInput: func() any {
637 type (
638 MyInt int
639 S struct{ *MyInt }
640 )
641 s := S{new(MyInt)}
642 *s.MyInt = 5
643 return s
644 },
645 want: `{"MyInt":5}`,
646 }, {
647
648
649
650 CaseName: Name("EmbeddedStruct"),
651 makeInput: func() any {
652 type (
653 s1 struct{ x, X int }
654 S2 struct{ y, Y int }
655 S struct {
656 s1
657 S2
658 }
659 )
660 return S{s1{1, 2}, S2{3, 4}}
661 },
662 want: `{"X":2,"Y":4}`,
663 }, {
664
665
666
667 CaseName: Name("EmbeddedStructPointer"),
668 makeInput: func() any {
669 type (
670 s1 struct{ x, X int }
671 S2 struct{ y, Y int }
672 S struct {
673 *s1
674 *S2
675 }
676 )
677 return S{&s1{1, 2}, &S2{3, 4}}
678 },
679 want: `{"X":2,"Y":4}`,
680 }, {
681
682
683 CaseName: Name("NestedStructAndInts"),
684 makeInput: func() any {
685 type (
686 MyInt1 int
687 MyInt2 int
688 myInt int
689 s2 struct {
690 MyInt2
691 myInt
692 }
693 s1 struct {
694 MyInt1
695 myInt
696 s2
697 }
698 S struct {
699 s1
700 myInt
701 }
702 )
703 return S{s1{1, 2, s2{3, 4}}, 6}
704 },
705 want: `{"MyInt1":1,"MyInt2":3}`,
706 }, {
707
708
709
710 CaseName: Name("EmbeddedFieldBehindNilPointer"),
711 makeInput: func() any {
712 type (
713 S2 struct{ Field string }
714 S struct{ *S2 }
715 )
716 return S{}
717 },
718 want: `{}`,
719 }}
720
721 for _, tt := range tests {
722 t.Run(tt.Name, func(t *testing.T) {
723 b, err := Marshal(tt.makeInput())
724 if err != nil {
725 t.Fatalf("%s: Marshal error: %v", tt.Where, err)
726 }
727 if string(b) != tt.want {
728 t.Fatalf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, b, tt.want)
729 }
730 })
731 }
732 }
733
734 type BugA struct {
735 S string
736 }
737
738 type BugB struct {
739 BugA
740 S string
741 }
742
743 type BugC struct {
744 S string
745 }
746
747
748 type BugX struct {
749 A int
750 BugA
751 BugB
752 }
753
754
755
756
757 type nilJSONMarshaler string
758
759 func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {
760 if nm == nil {
761 return Marshal("0zenil0")
762 }
763 return Marshal("zenil:" + string(*nm))
764 }
765
766
767
768
769 type nilTextMarshaler string
770
771 func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {
772 if nm == nil {
773 return []byte("0zenil0"), nil
774 }
775 return []byte("zenil:" + string(*nm)), nil
776 }
777
778
779 func TestNilMarshal(t *testing.T) {
780 tests := []struct {
781 CaseName
782 in any
783 want string
784 }{
785 {Name(""), nil, `null`},
786 {Name(""), new(float64), `0`},
787 {Name(""), []any(nil), `null`},
788 {Name(""), []string(nil), `null`},
789 {Name(""), map[string]string(nil), `null`},
790 {Name(""), []byte(nil), `null`},
791 {Name(""), struct{ M string }{"gopher"}, `{"M":"gopher"}`},
792 {Name(""), struct{ M Marshaler }{}, `{"M":null}`},
793 {Name(""), struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, `{"M":"0zenil0"}`},
794 {Name(""), struct{ M any }{(*nilJSONMarshaler)(nil)}, `{"M":null}`},
795 {Name(""), struct{ M encoding.TextMarshaler }{}, `{"M":null}`},
796 {Name(""), struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, `{"M":"0zenil0"}`},
797 {Name(""), struct{ M any }{(*nilTextMarshaler)(nil)}, `{"M":null}`},
798 }
799 for _, tt := range tests {
800 t.Run(tt.Name, func(t *testing.T) {
801 switch got, err := Marshal(tt.in); {
802 case err != nil:
803 t.Fatalf("%s: Marshal error: %v", tt.Where, err)
804 case string(got) != tt.want:
805 t.Fatalf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want)
806 }
807 })
808 }
809 }
810
811
812 func TestEmbeddedBug(t *testing.T) {
813 v := BugB{
814 BugA{"A"},
815 "B",
816 }
817 b, err := Marshal(v)
818 if err != nil {
819 t.Fatal("Marshal error:", err)
820 }
821 want := `{"S":"B"}`
822 got := string(b)
823 if got != want {
824 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
825 }
826
827 x := BugX{
828 A: 23,
829 }
830 b, err = Marshal(x)
831 if err != nil {
832 t.Fatal("Marshal error:", err)
833 }
834 want = `{"A":23}`
835 got = string(b)
836 if got != want {
837 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
838 }
839 }
840
841 type BugD struct {
842 XXX string `json:"S"`
843 }
844
845
846 type BugY struct {
847 BugA
848 BugD
849 }
850
851
852 func TestTaggedFieldDominates(t *testing.T) {
853 v := BugY{
854 BugA{"BugA"},
855 BugD{"BugD"},
856 }
857 b, err := Marshal(v)
858 if err != nil {
859 t.Fatal("Marshal error:", err)
860 }
861 want := `{"S":"BugD"}`
862 got := string(b)
863 if got != want {
864 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
865 }
866 }
867
868
869 type BugZ struct {
870 BugA
871 BugC
872 BugY
873 }
874
875 func TestDuplicatedFieldDisappears(t *testing.T) {
876 v := BugZ{
877 BugA{"BugA"},
878 BugC{"BugC"},
879 BugY{
880 BugA{"nested BugA"},
881 BugD{"nested BugD"},
882 },
883 }
884 b, err := Marshal(v)
885 if err != nil {
886 t.Fatal("Marshal error:", err)
887 }
888 want := `{}`
889 got := string(b)
890 if got != want {
891 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
892 }
893 }
894
895 func TestIssue10281(t *testing.T) {
896 type Foo struct {
897 N Number
898 }
899 x := Foo{Number(`invalid`)}
900
901 if _, err := Marshal(&x); err == nil {
902 t.Fatalf("Marshal error: got nil, want non-nil")
903 }
904 }
905
906 func TestMarshalErrorAndReuseEncodeState(t *testing.T) {
907
908 percent := debug.SetGCPercent(-1)
909 defer debug.SetGCPercent(percent)
910
911
912 type Dummy struct {
913 Name string
914 Next *Dummy
915 }
916 dummy := Dummy{Name: "Dummy"}
917 dummy.Next = &dummy
918 if _, err := Marshal(dummy); err == nil {
919 t.Errorf("Marshal error: got nil, want non-nil")
920 }
921
922 type Data struct {
923 A string
924 I int
925 }
926 want := Data{A: "a", I: 1}
927 b, err := Marshal(want)
928 if err != nil {
929 t.Errorf("Marshal error: %v", err)
930 }
931
932 var got Data
933 if err := Unmarshal(b, &got); err != nil {
934 t.Errorf("Unmarshal error: %v", err)
935 }
936 if got != want {
937 t.Errorf("Unmarshal:\n\tgot: %v\n\twant: %v", got, want)
938 }
939 }
940
941 func TestHTMLEscape(t *testing.T) {
942 var b, want bytes.Buffer
943 m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
944 want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
945 HTMLEscape(&b, []byte(m))
946 if !bytes.Equal(b.Bytes(), want.Bytes()) {
947 t.Errorf("HTMLEscape:\n\tgot: %s\n\twant: %s", b.Bytes(), want.Bytes())
948 }
949 }
950
951
952 func TestEncodePointerString(t *testing.T) {
953 type stringPointer struct {
954 N *int64 `json:"n,string"`
955 }
956 var n int64 = 42
957 b, err := Marshal(stringPointer{N: &n})
958 if err != nil {
959 t.Fatalf("Marshal error: %v", err)
960 }
961 if got, want := string(b), `{"n":"42"}`; got != want {
962 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
963 }
964 var back stringPointer
965 switch err = Unmarshal(b, &back); {
966 case err != nil:
967 t.Fatalf("Unmarshal error: %v", err)
968 case back.N == nil:
969 t.Fatalf("Unmarshal: back.N = nil, want non-nil")
970 case *back.N != 42:
971 t.Fatalf("Unmarshal: *back.N = %d, want 42", *back.N)
972 }
973 }
974
975 var encodeStringTests = []struct {
976 in string
977 out string
978 }{
979 {"\x00", `"\u0000"`},
980 {"\x01", `"\u0001"`},
981 {"\x02", `"\u0002"`},
982 {"\x03", `"\u0003"`},
983 {"\x04", `"\u0004"`},
984 {"\x05", `"\u0005"`},
985 {"\x06", `"\u0006"`},
986 {"\x07", `"\u0007"`},
987 {"\x08", `"\b"`},
988 {"\x09", `"\t"`},
989 {"\x0a", `"\n"`},
990 {"\x0b", `"\u000b"`},
991 {"\x0c", `"\f"`},
992 {"\x0d", `"\r"`},
993 {"\x0e", `"\u000e"`},
994 {"\x0f", `"\u000f"`},
995 {"\x10", `"\u0010"`},
996 {"\x11", `"\u0011"`},
997 {"\x12", `"\u0012"`},
998 {"\x13", `"\u0013"`},
999 {"\x14", `"\u0014"`},
1000 {"\x15", `"\u0015"`},
1001 {"\x16", `"\u0016"`},
1002 {"\x17", `"\u0017"`},
1003 {"\x18", `"\u0018"`},
1004 {"\x19", `"\u0019"`},
1005 {"\x1a", `"\u001a"`},
1006 {"\x1b", `"\u001b"`},
1007 {"\x1c", `"\u001c"`},
1008 {"\x1d", `"\u001d"`},
1009 {"\x1e", `"\u001e"`},
1010 {"\x1f", `"\u001f"`},
1011 }
1012
1013 func TestEncodeString(t *testing.T) {
1014 for _, tt := range encodeStringTests {
1015 b, err := Marshal(tt.in)
1016 if err != nil {
1017 t.Errorf("Marshal(%q) error: %v", tt.in, err)
1018 continue
1019 }
1020 out := string(b)
1021 if out != tt.out {
1022 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
1023 }
1024 }
1025 }
1026
1027 type jsonbyte byte
1028
1029 func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }
1030
1031 type textbyte byte
1032
1033 func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }
1034
1035 type jsonint int
1036
1037 func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }
1038
1039 type textint int
1040
1041 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }
1042
1043 func tenc(format string, a ...any) ([]byte, error) {
1044 var buf bytes.Buffer
1045 fmt.Fprintf(&buf, format, a...)
1046 return buf.Bytes(), nil
1047 }
1048
1049 type textfloat float64
1050
1051 func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
1052
1053
1054 func TestEncodeBytekind(t *testing.T) {
1055 tests := []struct {
1056 CaseName
1057 in any
1058 want string
1059 }{
1060 {Name(""), byte(7), "7"},
1061 {Name(""), jsonbyte(7), `{"JB":7}`},
1062 {Name(""), textbyte(4), `"TB:4"`},
1063 {Name(""), jsonint(5), `{"JI":5}`},
1064 {Name(""), textint(1), `"TI:1"`},
1065 {Name(""), []byte{0, 1}, `"AAE="`},
1066 {Name(""), []jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},
1067 {Name(""), [][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},
1068 {Name(""), []textbyte{2, 3}, `["TB:2","TB:3"]`},
1069 {Name(""), []jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
1070 {Name(""), []textint{9, 3}, `["TI:9","TI:3"]`},
1071 {Name(""), []int{9, 3}, `[9,3]`},
1072 {Name(""), []textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
1073 }
1074 for _, tt := range tests {
1075 t.Run(tt.Name, func(t *testing.T) {
1076 b, err := Marshal(tt.in)
1077 if err != nil {
1078 t.Errorf("%s: Marshal error: %v", tt.Where, err)
1079 }
1080 got, want := string(b), tt.want
1081 if got != want {
1082 t.Errorf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, got, want)
1083 }
1084 })
1085 }
1086 }
1087
1088 func TestTextMarshalerMapKeysAreSorted(t *testing.T) {
1089 got, err := Marshal(map[unmarshalerText]int{
1090 {"x", "y"}: 1,
1091 {"y", "x"}: 2,
1092 {"a", "z"}: 3,
1093 {"z", "a"}: 4,
1094 })
1095 if err != nil {
1096 t.Fatalf("Marshal error: %v", err)
1097 }
1098 const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}`
1099 if string(got) != want {
1100 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1101 }
1102 }
1103
1104
1105 func TestNilMarshalerTextMapKey(t *testing.T) {
1106 got, err := Marshal(map[*unmarshalerText]int{
1107 (*unmarshalerText)(nil): 1,
1108 {"A", "B"}: 2,
1109 })
1110 if err != nil {
1111 t.Fatalf("Marshal error: %v", err)
1112 }
1113 const want = `{"":1,"A:B":2}`
1114 if string(got) != want {
1115 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1116 }
1117 }
1118
1119 var re = regexp.MustCompile
1120
1121
1122 var badFloatREs = []*regexp.Regexp{
1123 re(`p`),
1124 re(`^\+`),
1125 re(`^-?0[^.]`),
1126 re(`^-?\.`),
1127 re(`\.(e|$)`),
1128 re(`\.[0-9]+0(e|$)`),
1129 re(`^-?(0|[0-9]{2,})\..*e`),
1130 re(`e[0-9]`),
1131 re(`e[+-]0`),
1132 re(`e-[1-6]$`),
1133 re(`e+(.|1.|20)$`),
1134 re(`^-?0\.0000000`),
1135 re(`^-?[0-9]{22}`),
1136 re(`[1-9][0-9]{16}[1-9]`),
1137 re(`[1-9][0-9.]{17}[1-9]`),
1138
1139 re(`[1-9][0-9]{8}[1-9]`),
1140 re(`[1-9][0-9.]{9}[1-9]`),
1141 }
1142
1143 func TestMarshalFloat(t *testing.T) {
1144 t.Parallel()
1145 nfail := 0
1146 test := func(f float64, bits int) {
1147 vf := any(f)
1148 if bits == 32 {
1149 f = float64(float32(f))
1150 vf = float32(f)
1151 }
1152 bout, err := Marshal(vf)
1153 if err != nil {
1154 t.Errorf("Marshal(%T(%g)) error: %v", vf, vf, err)
1155 nfail++
1156 return
1157 }
1158 out := string(bout)
1159
1160
1161 g, err := strconv.ParseFloat(out, bits)
1162 if err != nil {
1163 t.Errorf("ParseFloat(%q) error: %v", out, err)
1164 nfail++
1165 return
1166 }
1167 if f != g || fmt.Sprint(f) != fmt.Sprint(g) {
1168 t.Errorf("ParseFloat(%q):\n\tgot: %g\n\twant: %g", out, float32(g), vf)
1169 nfail++
1170 return
1171 }
1172
1173 bad := badFloatREs
1174 if bits == 64 {
1175 bad = bad[:len(bad)-2]
1176 }
1177 for _, re := range bad {
1178 if re.MatchString(out) {
1179 t.Errorf("Marshal(%T(%g)) = %q; must not match /%s/", vf, vf, out, re)
1180 nfail++
1181 return
1182 }
1183 }
1184 }
1185
1186 var (
1187 bigger = math.Inf(+1)
1188 smaller = math.Inf(-1)
1189 )
1190
1191 var digits = "1.2345678901234567890123"
1192 for i := len(digits); i >= 2; i-- {
1193 if testing.Short() && i < len(digits)-4 {
1194 break
1195 }
1196 for exp := -30; exp <= 30; exp++ {
1197 for _, sign := range "+-" {
1198 for bits := 32; bits <= 64; bits += 32 {
1199 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
1200 f, err := strconv.ParseFloat(s, bits)
1201 if err != nil {
1202 log.Fatal(err)
1203 }
1204 next := math.Nextafter
1205 if bits == 32 {
1206 next = func(g, h float64) float64 {
1207 return float64(math.Nextafter32(float32(g), float32(h)))
1208 }
1209 }
1210 test(f, bits)
1211 test(next(f, bigger), bits)
1212 test(next(f, smaller), bits)
1213 if nfail > 50 {
1214 t.Fatalf("stopping test early")
1215 }
1216 }
1217 }
1218 }
1219 }
1220 test(0, 64)
1221 test(math.Copysign(0, -1), 64)
1222 test(0, 32)
1223 test(math.Copysign(0, -1), 32)
1224 }
1225
1226 func TestMarshalRawMessageValue(t *testing.T) {
1227 type (
1228 T1 struct {
1229 M RawMessage `json:",omitempty"`
1230 }
1231 T2 struct {
1232 M *RawMessage `json:",omitempty"`
1233 }
1234 )
1235
1236 var (
1237 rawNil = RawMessage(nil)
1238 rawEmpty = RawMessage([]byte{})
1239 rawText = RawMessage([]byte(`"foo"`))
1240 )
1241
1242 tests := []struct {
1243 CaseName
1244 in any
1245 want string
1246 ok bool
1247 }{
1248
1249 {Name(""), rawNil, "null", true},
1250 {Name(""), &rawNil, "null", true},
1251 {Name(""), []any{rawNil}, "[null]", true},
1252 {Name(""), &[]any{rawNil}, "[null]", true},
1253 {Name(""), []any{&rawNil}, "[null]", true},
1254 {Name(""), &[]any{&rawNil}, "[null]", true},
1255 {Name(""), struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1256 {Name(""), &struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1257 {Name(""), struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1258 {Name(""), &struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1259 {Name(""), map[string]any{"M": rawNil}, `{"M":null}`, true},
1260 {Name(""), &map[string]any{"M": rawNil}, `{"M":null}`, true},
1261 {Name(""), map[string]any{"M": &rawNil}, `{"M":null}`, true},
1262 {Name(""), &map[string]any{"M": &rawNil}, `{"M":null}`, true},
1263 {Name(""), T1{rawNil}, "{}", true},
1264 {Name(""), T2{&rawNil}, `{"M":null}`, true},
1265 {Name(""), &T1{rawNil}, "{}", true},
1266 {Name(""), &T2{&rawNil}, `{"M":null}`, true},
1267
1268
1269 {Name(""), rawEmpty, "", false},
1270 {Name(""), &rawEmpty, "", false},
1271 {Name(""), []any{rawEmpty}, "", false},
1272 {Name(""), &[]any{rawEmpty}, "", false},
1273 {Name(""), []any{&rawEmpty}, "", false},
1274 {Name(""), &[]any{&rawEmpty}, "", false},
1275 {Name(""), struct{ X RawMessage }{rawEmpty}, "", false},
1276 {Name(""), &struct{ X RawMessage }{rawEmpty}, "", false},
1277 {Name(""), struct{ X *RawMessage }{&rawEmpty}, "", false},
1278 {Name(""), &struct{ X *RawMessage }{&rawEmpty}, "", false},
1279 {Name(""), map[string]any{"nil": rawEmpty}, "", false},
1280 {Name(""), &map[string]any{"nil": rawEmpty}, "", false},
1281 {Name(""), map[string]any{"nil": &rawEmpty}, "", false},
1282 {Name(""), &map[string]any{"nil": &rawEmpty}, "", false},
1283 {Name(""), T1{rawEmpty}, "{}", true},
1284 {Name(""), T2{&rawEmpty}, "", false},
1285 {Name(""), &T1{rawEmpty}, "{}", true},
1286 {Name(""), &T2{&rawEmpty}, "", false},
1287
1288
1289
1290
1291
1292
1293 {Name(""), rawText, `"foo"`, true},
1294 {Name(""), &rawText, `"foo"`, true},
1295 {Name(""), []any{rawText}, `["foo"]`, true},
1296 {Name(""), &[]any{rawText}, `["foo"]`, true},
1297 {Name(""), []any{&rawText}, `["foo"]`, true},
1298 {Name(""), &[]any{&rawText}, `["foo"]`, true},
1299 {Name(""), struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1300 {Name(""), &struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1301 {Name(""), struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1302 {Name(""), &struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1303 {Name(""), map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1304 {Name(""), &map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1305 {Name(""), map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1306 {Name(""), &map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1307 {Name(""), T1{rawText}, `{"M":"foo"}`, true},
1308 {Name(""), T2{&rawText}, `{"M":"foo"}`, true},
1309 {Name(""), &T1{rawText}, `{"M":"foo"}`, true},
1310 {Name(""), &T2{&rawText}, `{"M":"foo"}`, true},
1311 }
1312
1313 for _, tt := range tests {
1314 t.Run(tt.Name, func(t *testing.T) {
1315 b, err := Marshal(tt.in)
1316 if ok := (err == nil); ok != tt.ok {
1317 if err != nil {
1318 t.Errorf("%s: Marshal error: %v", tt.Where, err)
1319 } else {
1320 t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)
1321 }
1322 }
1323 if got := string(b); got != tt.want {
1324 t.Errorf("%s: Marshal:\n\tinput: %#v\n\tgot: %s\n\twant: %s", tt.Where, tt.in, got, tt.want)
1325 }
1326 })
1327 }
1328 }
1329
1330 type marshalPanic struct{}
1331
1332 func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) }
1333
1334 func TestMarshalPanic(t *testing.T) {
1335 defer func() {
1336 if got := recover(); !reflect.DeepEqual(got, 0xdead) {
1337 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
1338 }
1339 }()
1340 Marshal(&marshalPanic{})
1341 t.Error("Marshal should have panicked")
1342 }
1343
1344 func TestMarshalUncommonFieldNames(t *testing.T) {
1345 v := struct {
1346 A0, À, Aβ int
1347 }{}
1348 b, err := Marshal(v)
1349 if err != nil {
1350 t.Fatal("Marshal error:", err)
1351 }
1352 want := `{"A0":0,"À":0,"Aβ":0}`
1353 got := string(b)
1354 if got != want {
1355 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1356 }
1357 }
1358
1359 func TestMarshalerError(t *testing.T) {
1360 s := "test variable"
1361 st := reflect.TypeOf(s)
1362 const errText = "json: test error"
1363
1364 tests := []struct {
1365 CaseName
1366 err *MarshalerError
1367 want string
1368 }{{
1369 Name(""),
1370 &MarshalerError{st, fmt.Errorf(errText), ""},
1371 "json: error calling MarshalJSON for type " + st.String() + ": " + errText,
1372 }, {
1373 Name(""),
1374 &MarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"},
1375 "json: error calling TestMarshalerError for type " + st.String() + ": " + errText,
1376 }}
1377
1378 for _, tt := range tests {
1379 t.Run(tt.Name, func(t *testing.T) {
1380 got := tt.err.Error()
1381 if got != tt.want {
1382 t.Errorf("%s: Error:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want)
1383 }
1384 })
1385 }
1386 }
1387
1388 type marshaledValue string
1389
1390 func (v marshaledValue) MarshalJSON() ([]byte, error) {
1391 return []byte(v), nil
1392 }
1393
1394 func TestIssue63379(t *testing.T) {
1395 for _, v := range []string{
1396 "[]<",
1397 "[]>",
1398 "[]&",
1399 "[]\u2028",
1400 "[]\u2029",
1401 "{}<",
1402 "{}>",
1403 "{}&",
1404 "{}\u2028",
1405 "{}\u2029",
1406 } {
1407 _, err := Marshal(marshaledValue(v))
1408 if err == nil {
1409 t.Errorf("expected error for %q", v)
1410 }
1411 }
1412 }
1413
1414
1415
1416
1417 func TestSynctestMarshal(t *testing.T) {
1418 var wg sync.WaitGroup
1419 for range 5 {
1420 wg.Go(func() {
1421 synctest.Test(t, func(t *testing.T) {
1422 _, err := Marshal([]string{})
1423 if err != nil {
1424 t.Errorf("Marshal: %v", err)
1425 }
1426 })
1427 })
1428 }
1429 wg.Wait()
1430 }
1431
View as plain text