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