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