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 TestMarshalTextFloatMap(t *testing.T) {
434 m := map[textfloat]string{
435 textfloat(math.NaN()): "1",
436 textfloat(math.NaN()): "1",
437 }
438 got, err := Marshal(m)
439 if err != nil {
440 t.Errorf("Marshal error: %v", err)
441 }
442 want := `{"TF:NaN":"1","TF:NaN":"1"}`
443 if string(got) != want {
444 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
445 }
446 }
447
448
449 type Ref int
450
451 func (*Ref) MarshalJSON() ([]byte, error) {
452 return []byte(`"ref"`), nil
453 }
454
455 func (r *Ref) UnmarshalJSON([]byte) error {
456 *r = 12
457 return nil
458 }
459
460
461 type Val int
462
463 func (Val) MarshalJSON() ([]byte, error) {
464 return []byte(`"val"`), nil
465 }
466
467
468 type RefText int
469
470 func (*RefText) MarshalText() ([]byte, error) {
471 return []byte(`"ref"`), nil
472 }
473
474 func (r *RefText) UnmarshalText([]byte) error {
475 *r = 13
476 return nil
477 }
478
479
480 type ValText int
481
482 func (ValText) MarshalText() ([]byte, error) {
483 return []byte(`"val"`), nil
484 }
485
486 func TestRefValMarshal(t *testing.T) {
487 var s = struct {
488 R0 Ref
489 R1 *Ref
490 R2 RefText
491 R3 *RefText
492 V0 Val
493 V1 *Val
494 V2 ValText
495 V3 *ValText
496 }{
497 R0: 12,
498 R1: new(Ref),
499 R2: 14,
500 R3: new(RefText),
501 V0: 13,
502 V1: new(Val),
503 V2: 15,
504 V3: new(ValText),
505 }
506 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
507 b, err := Marshal(&s)
508 if err != nil {
509 t.Fatalf("Marshal error: %v", err)
510 }
511 if got := string(b); got != want {
512 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
513 }
514 }
515
516
517 type C int
518
519 func (C) MarshalJSON() ([]byte, error) {
520 return []byte(`"<&>"`), nil
521 }
522
523
524 type CText int
525
526 func (CText) MarshalText() ([]byte, error) {
527 return []byte(`"<&>"`), nil
528 }
529
530 func TestMarshalerEscaping(t *testing.T) {
531 var c C
532 want := `"\u003c\u0026\u003e"`
533 b, err := Marshal(c)
534 if err != nil {
535 t.Fatalf("Marshal error: %v", err)
536 }
537 if got := string(b); got != want {
538 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
539 }
540
541 var ct CText
542 want = `"\"\u003c\u0026\u003e\""`
543 b, err = Marshal(ct)
544 if err != nil {
545 t.Fatalf("Marshal error: %v", err)
546 }
547 if got := string(b); got != want {
548 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
549 }
550 }
551
552 func TestAnonymousFields(t *testing.T) {
553 tests := []struct {
554 CaseName
555 makeInput func() any
556 want string
557 }{{
558
559
560
561 CaseName: Name("AmbiguousField"),
562 makeInput: func() any {
563 type (
564 S1 struct{ x, X int }
565 S2 struct{ x, X int }
566 S struct {
567 S1
568 S2
569 }
570 )
571 return S{S1{1, 2}, S2{3, 4}}
572 },
573 want: `{}`,
574 }, {
575 CaseName: Name("DominantField"),
576
577
578 makeInput: func() any {
579 type (
580 S1 struct{ x, X int }
581 S2 struct{ x, X int }
582 S struct {
583 S1
584 S2
585 x, X int
586 }
587 )
588 return S{S1{1, 2}, S2{3, 4}, 5, 6}
589 },
590 want: `{"X":6}`,
591 }, {
592
593 CaseName: Name("UnexportedEmbeddedInt"),
594 makeInput: func() any {
595 type (
596 myInt int
597 S struct{ myInt }
598 )
599 return S{5}
600 },
601 want: `{}`,
602 }, {
603
604 CaseName: Name("ExportedEmbeddedInt"),
605 makeInput: func() any {
606 type (
607 MyInt int
608 S struct{ MyInt }
609 )
610 return S{5}
611 },
612 want: `{"MyInt":5}`,
613 }, {
614
615
616 CaseName: Name("UnexportedEmbeddedIntPointer"),
617 makeInput: func() any {
618 type (
619 myInt int
620 S struct{ *myInt }
621 )
622 s := S{new(myInt)}
623 *s.myInt = 5
624 return s
625 },
626 want: `{}`,
627 }, {
628
629
630 CaseName: Name("ExportedEmbeddedIntPointer"),
631 makeInput: func() any {
632 type (
633 MyInt int
634 S struct{ *MyInt }
635 )
636 s := S{new(MyInt)}
637 *s.MyInt = 5
638 return s
639 },
640 want: `{"MyInt":5}`,
641 }, {
642
643
644
645 CaseName: Name("EmbeddedStruct"),
646 makeInput: func() any {
647 type (
648 s1 struct{ x, X int }
649 S2 struct{ y, Y int }
650 S struct {
651 s1
652 S2
653 }
654 )
655 return S{s1{1, 2}, S2{3, 4}}
656 },
657 want: `{"X":2,"Y":4}`,
658 }, {
659
660
661
662 CaseName: Name("EmbeddedStructPointer"),
663 makeInput: func() any {
664 type (
665 s1 struct{ x, X int }
666 S2 struct{ y, Y int }
667 S struct {
668 *s1
669 *S2
670 }
671 )
672 return S{&s1{1, 2}, &S2{3, 4}}
673 },
674 want: `{"X":2,"Y":4}`,
675 }, {
676
677
678 CaseName: Name("NestedStructAndInts"),
679 makeInput: func() any {
680 type (
681 MyInt1 int
682 MyInt2 int
683 myInt int
684 s2 struct {
685 MyInt2
686 myInt
687 }
688 s1 struct {
689 MyInt1
690 myInt
691 s2
692 }
693 S struct {
694 s1
695 myInt
696 }
697 )
698 return S{s1{1, 2, s2{3, 4}}, 6}
699 },
700 want: `{"MyInt1":1,"MyInt2":3}`,
701 }, {
702
703
704
705 CaseName: Name("EmbeddedFieldBehindNilPointer"),
706 makeInput: func() any {
707 type (
708 S2 struct{ Field string }
709 S struct{ *S2 }
710 )
711 return S{}
712 },
713 want: `{}`,
714 }}
715
716 for _, tt := range tests {
717 t.Run(tt.Name, func(t *testing.T) {
718 b, err := Marshal(tt.makeInput())
719 if err != nil {
720 t.Fatalf("%s: Marshal error: %v", tt.Where, err)
721 }
722 if string(b) != tt.want {
723 t.Fatalf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, b, tt.want)
724 }
725 })
726 }
727 }
728
729 type BugA struct {
730 S string
731 }
732
733 type BugB struct {
734 BugA
735 S string
736 }
737
738 type BugC struct {
739 S string
740 }
741
742
743 type BugX struct {
744 A int
745 BugA
746 BugB
747 }
748
749
750
751
752 type nilJSONMarshaler string
753
754 func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {
755 if nm == nil {
756 return Marshal("0zenil0")
757 }
758 return Marshal("zenil:" + string(*nm))
759 }
760
761
762
763
764 type nilTextMarshaler string
765
766 func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {
767 if nm == nil {
768 return []byte("0zenil0"), nil
769 }
770 return []byte("zenil:" + string(*nm)), nil
771 }
772
773
774 func TestNilMarshal(t *testing.T) {
775 tests := []struct {
776 CaseName
777 in any
778 want string
779 }{
780 {Name(""), nil, `null`},
781 {Name(""), new(float64), `0`},
782 {Name(""), []any(nil), `null`},
783 {Name(""), []string(nil), `null`},
784 {Name(""), map[string]string(nil), `null`},
785 {Name(""), []byte(nil), `null`},
786 {Name(""), struct{ M string }{"gopher"}, `{"M":"gopher"}`},
787 {Name(""), struct{ M Marshaler }{}, `{"M":null}`},
788 {Name(""), struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, `{"M":"0zenil0"}`},
789 {Name(""), struct{ M any }{(*nilJSONMarshaler)(nil)}, `{"M":null}`},
790 {Name(""), struct{ M encoding.TextMarshaler }{}, `{"M":null}`},
791 {Name(""), struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, `{"M":"0zenil0"}`},
792 {Name(""), struct{ M any }{(*nilTextMarshaler)(nil)}, `{"M":null}`},
793 }
794 for _, tt := range tests {
795 t.Run(tt.Name, func(t *testing.T) {
796 switch got, err := Marshal(tt.in); {
797 case err != nil:
798 t.Fatalf("%s: Marshal error: %v", tt.Where, err)
799 case string(got) != tt.want:
800 t.Fatalf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want)
801 }
802 })
803 }
804 }
805
806
807 func TestEmbeddedBug(t *testing.T) {
808 v := BugB{
809 BugA{"A"},
810 "B",
811 }
812 b, err := Marshal(v)
813 if err != nil {
814 t.Fatal("Marshal error:", err)
815 }
816 want := `{"S":"B"}`
817 got := string(b)
818 if got != want {
819 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
820 }
821
822 x := BugX{
823 A: 23,
824 }
825 b, err = Marshal(x)
826 if err != nil {
827 t.Fatal("Marshal error:", err)
828 }
829 want = `{"A":23}`
830 got = string(b)
831 if got != want {
832 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
833 }
834 }
835
836 type BugD struct {
837 XXX string `json:"S"`
838 }
839
840
841 type BugY struct {
842 BugA
843 BugD
844 }
845
846
847 func TestTaggedFieldDominates(t *testing.T) {
848 v := BugY{
849 BugA{"BugA"},
850 BugD{"BugD"},
851 }
852 b, err := Marshal(v)
853 if err != nil {
854 t.Fatal("Marshal error:", err)
855 }
856 want := `{"S":"BugD"}`
857 got := string(b)
858 if got != want {
859 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
860 }
861 }
862
863
864 type BugZ struct {
865 BugA
866 BugC
867 BugY
868 }
869
870 func TestDuplicatedFieldDisappears(t *testing.T) {
871 v := BugZ{
872 BugA{"BugA"},
873 BugC{"BugC"},
874 BugY{
875 BugA{"nested BugA"},
876 BugD{"nested BugD"},
877 },
878 }
879 b, err := Marshal(v)
880 if err != nil {
881 t.Fatal("Marshal error:", err)
882 }
883 want := `{}`
884 got := string(b)
885 if got != want {
886 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
887 }
888 }
889
890 func TestIssue10281(t *testing.T) {
891 type Foo struct {
892 N Number
893 }
894 x := Foo{Number(`invalid`)}
895
896 if _, err := Marshal(&x); err == nil {
897 t.Fatalf("Marshal error: got nil, want non-nil")
898 }
899 }
900
901 func TestMarshalErrorAndReuseEncodeState(t *testing.T) {
902
903 percent := debug.SetGCPercent(-1)
904 defer debug.SetGCPercent(percent)
905
906
907 type Dummy struct {
908 Name string
909 Next *Dummy
910 }
911 dummy := Dummy{Name: "Dummy"}
912 dummy.Next = &dummy
913 if _, err := Marshal(dummy); err == nil {
914 t.Errorf("Marshal error: got nil, want non-nil")
915 }
916
917 type Data struct {
918 A string
919 I int
920 }
921 want := Data{A: "a", I: 1}
922 b, err := Marshal(want)
923 if err != nil {
924 t.Errorf("Marshal error: %v", err)
925 }
926
927 var got Data
928 if err := Unmarshal(b, &got); err != nil {
929 t.Errorf("Unmarshal error: %v", err)
930 }
931 if got != want {
932 t.Errorf("Unmarshal:\n\tgot: %v\n\twant: %v", got, want)
933 }
934 }
935
936 func TestHTMLEscape(t *testing.T) {
937 var b, want bytes.Buffer
938 m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
939 want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
940 HTMLEscape(&b, []byte(m))
941 if !bytes.Equal(b.Bytes(), want.Bytes()) {
942 t.Errorf("HTMLEscape:\n\tgot: %s\n\twant: %s", b.Bytes(), want.Bytes())
943 }
944 }
945
946
947 func TestEncodePointerString(t *testing.T) {
948 type stringPointer struct {
949 N *int64 `json:"n,string"`
950 }
951 var n int64 = 42
952 b, err := Marshal(stringPointer{N: &n})
953 if err != nil {
954 t.Fatalf("Marshal error: %v", err)
955 }
956 if got, want := string(b), `{"n":"42"}`; got != want {
957 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
958 }
959 var back stringPointer
960 switch err = Unmarshal(b, &back); {
961 case err != nil:
962 t.Fatalf("Unmarshal error: %v", err)
963 case back.N == nil:
964 t.Fatalf("Unmarshal: back.N = nil, want non-nil")
965 case *back.N != 42:
966 t.Fatalf("Unmarshal: *back.N = %d, want 42", *back.N)
967 }
968 }
969
970 var encodeStringTests = []struct {
971 in string
972 out string
973 }{
974 {"\x00", `"\u0000"`},
975 {"\x01", `"\u0001"`},
976 {"\x02", `"\u0002"`},
977 {"\x03", `"\u0003"`},
978 {"\x04", `"\u0004"`},
979 {"\x05", `"\u0005"`},
980 {"\x06", `"\u0006"`},
981 {"\x07", `"\u0007"`},
982 {"\x08", `"\b"`},
983 {"\x09", `"\t"`},
984 {"\x0a", `"\n"`},
985 {"\x0b", `"\u000b"`},
986 {"\x0c", `"\f"`},
987 {"\x0d", `"\r"`},
988 {"\x0e", `"\u000e"`},
989 {"\x0f", `"\u000f"`},
990 {"\x10", `"\u0010"`},
991 {"\x11", `"\u0011"`},
992 {"\x12", `"\u0012"`},
993 {"\x13", `"\u0013"`},
994 {"\x14", `"\u0014"`},
995 {"\x15", `"\u0015"`},
996 {"\x16", `"\u0016"`},
997 {"\x17", `"\u0017"`},
998 {"\x18", `"\u0018"`},
999 {"\x19", `"\u0019"`},
1000 {"\x1a", `"\u001a"`},
1001 {"\x1b", `"\u001b"`},
1002 {"\x1c", `"\u001c"`},
1003 {"\x1d", `"\u001d"`},
1004 {"\x1e", `"\u001e"`},
1005 {"\x1f", `"\u001f"`},
1006 }
1007
1008 func TestEncodeString(t *testing.T) {
1009 for _, tt := range encodeStringTests {
1010 b, err := Marshal(tt.in)
1011 if err != nil {
1012 t.Errorf("Marshal(%q) error: %v", tt.in, err)
1013 continue
1014 }
1015 out := string(b)
1016 if out != tt.out {
1017 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
1018 }
1019 }
1020 }
1021
1022 type jsonbyte byte
1023
1024 func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }
1025
1026 type textbyte byte
1027
1028 func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }
1029
1030 type jsonint int
1031
1032 func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }
1033
1034 type textint int
1035
1036 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }
1037
1038 func tenc(format string, a ...any) ([]byte, error) {
1039 var buf bytes.Buffer
1040 fmt.Fprintf(&buf, format, a...)
1041 return buf.Bytes(), nil
1042 }
1043
1044 type textfloat float64
1045
1046 func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
1047
1048
1049 func TestEncodeBytekind(t *testing.T) {
1050 tests := []struct {
1051 CaseName
1052 in any
1053 want string
1054 }{
1055 {Name(""), byte(7), "7"},
1056 {Name(""), jsonbyte(7), `{"JB":7}`},
1057 {Name(""), textbyte(4), `"TB:4"`},
1058 {Name(""), jsonint(5), `{"JI":5}`},
1059 {Name(""), textint(1), `"TI:1"`},
1060 {Name(""), []byte{0, 1}, `"AAE="`},
1061 {Name(""), []jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},
1062 {Name(""), [][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},
1063 {Name(""), []textbyte{2, 3}, `["TB:2","TB:3"]`},
1064 {Name(""), []jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
1065 {Name(""), []textint{9, 3}, `["TI:9","TI:3"]`},
1066 {Name(""), []int{9, 3}, `[9,3]`},
1067 {Name(""), []textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
1068 }
1069 for _, tt := range tests {
1070 t.Run(tt.Name, func(t *testing.T) {
1071 b, err := Marshal(tt.in)
1072 if err != nil {
1073 t.Errorf("%s: Marshal error: %v", tt.Where, err)
1074 }
1075 got, want := string(b), tt.want
1076 if got != want {
1077 t.Errorf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, got, want)
1078 }
1079 })
1080 }
1081 }
1082
1083 func TestTextMarshalerMapKeysAreSorted(t *testing.T) {
1084 got, err := Marshal(map[unmarshalerText]int{
1085 {"x", "y"}: 1,
1086 {"y", "x"}: 2,
1087 {"a", "z"}: 3,
1088 {"z", "a"}: 4,
1089 })
1090 if err != nil {
1091 t.Fatalf("Marshal error: %v", err)
1092 }
1093 const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}`
1094 if string(got) != want {
1095 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1096 }
1097 }
1098
1099
1100 func TestNilMarshalerTextMapKey(t *testing.T) {
1101 got, err := Marshal(map[*unmarshalerText]int{
1102 (*unmarshalerText)(nil): 1,
1103 {"A", "B"}: 2,
1104 })
1105 if err != nil {
1106 t.Fatalf("Marshal error: %v", err)
1107 }
1108 const want = `{"":1,"A:B":2}`
1109 if string(got) != want {
1110 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1111 }
1112 }
1113
1114 var re = regexp.MustCompile
1115
1116
1117 var badFloatREs = []*regexp.Regexp{
1118 re(`p`),
1119 re(`^\+`),
1120 re(`^-?0[^.]`),
1121 re(`^-?\.`),
1122 re(`\.(e|$)`),
1123 re(`\.[0-9]+0(e|$)`),
1124 re(`^-?(0|[0-9]{2,})\..*e`),
1125 re(`e[0-9]`),
1126 re(`e[+-]0`),
1127 re(`e-[1-6]$`),
1128 re(`e+(.|1.|20)$`),
1129 re(`^-?0\.0000000`),
1130 re(`^-?[0-9]{22}`),
1131 re(`[1-9][0-9]{16}[1-9]`),
1132 re(`[1-9][0-9.]{17}[1-9]`),
1133
1134 re(`[1-9][0-9]{8}[1-9]`),
1135 re(`[1-9][0-9.]{9}[1-9]`),
1136 }
1137
1138 func TestMarshalFloat(t *testing.T) {
1139 t.Parallel()
1140 nfail := 0
1141 test := func(f float64, bits int) {
1142 vf := any(f)
1143 if bits == 32 {
1144 f = float64(float32(f))
1145 vf = float32(f)
1146 }
1147 bout, err := Marshal(vf)
1148 if err != nil {
1149 t.Errorf("Marshal(%T(%g)) error: %v", vf, vf, err)
1150 nfail++
1151 return
1152 }
1153 out := string(bout)
1154
1155
1156 g, err := strconv.ParseFloat(out, bits)
1157 if err != nil {
1158 t.Errorf("ParseFloat(%q) error: %v", out, err)
1159 nfail++
1160 return
1161 }
1162 if f != g || fmt.Sprint(f) != fmt.Sprint(g) {
1163 t.Errorf("ParseFloat(%q):\n\tgot: %g\n\twant: %g", out, float32(g), vf)
1164 nfail++
1165 return
1166 }
1167
1168 bad := badFloatREs
1169 if bits == 64 {
1170 bad = bad[:len(bad)-2]
1171 }
1172 for _, re := range bad {
1173 if re.MatchString(out) {
1174 t.Errorf("Marshal(%T(%g)) = %q; must not match /%s/", vf, vf, out, re)
1175 nfail++
1176 return
1177 }
1178 }
1179 }
1180
1181 var (
1182 bigger = math.Inf(+1)
1183 smaller = math.Inf(-1)
1184 )
1185
1186 var digits = "1.2345678901234567890123"
1187 for i := len(digits); i >= 2; i-- {
1188 if testing.Short() && i < len(digits)-4 {
1189 break
1190 }
1191 for exp := -30; exp <= 30; exp++ {
1192 for _, sign := range "+-" {
1193 for bits := 32; bits <= 64; bits += 32 {
1194 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
1195 f, err := strconv.ParseFloat(s, bits)
1196 if err != nil {
1197 log.Fatal(err)
1198 }
1199 next := math.Nextafter
1200 if bits == 32 {
1201 next = func(g, h float64) float64 {
1202 return float64(math.Nextafter32(float32(g), float32(h)))
1203 }
1204 }
1205 test(f, bits)
1206 test(next(f, bigger), bits)
1207 test(next(f, smaller), bits)
1208 if nfail > 50 {
1209 t.Fatalf("stopping test early")
1210 }
1211 }
1212 }
1213 }
1214 }
1215 test(0, 64)
1216 test(math.Copysign(0, -1), 64)
1217 test(0, 32)
1218 test(math.Copysign(0, -1), 32)
1219 }
1220
1221 func TestMarshalRawMessageValue(t *testing.T) {
1222 type (
1223 T1 struct {
1224 M RawMessage `json:",omitempty"`
1225 }
1226 T2 struct {
1227 M *RawMessage `json:",omitempty"`
1228 }
1229 )
1230
1231 var (
1232 rawNil = RawMessage(nil)
1233 rawEmpty = RawMessage([]byte{})
1234 rawText = RawMessage([]byte(`"foo"`))
1235 )
1236
1237 tests := []struct {
1238 CaseName
1239 in any
1240 want string
1241 ok bool
1242 }{
1243
1244 {Name(""), rawNil, "null", true},
1245 {Name(""), &rawNil, "null", true},
1246 {Name(""), []any{rawNil}, "[null]", true},
1247 {Name(""), &[]any{rawNil}, "[null]", true},
1248 {Name(""), []any{&rawNil}, "[null]", true},
1249 {Name(""), &[]any{&rawNil}, "[null]", true},
1250 {Name(""), struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1251 {Name(""), &struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1252 {Name(""), struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1253 {Name(""), &struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1254 {Name(""), map[string]any{"M": rawNil}, `{"M":null}`, true},
1255 {Name(""), &map[string]any{"M": rawNil}, `{"M":null}`, true},
1256 {Name(""), map[string]any{"M": &rawNil}, `{"M":null}`, true},
1257 {Name(""), &map[string]any{"M": &rawNil}, `{"M":null}`, true},
1258 {Name(""), T1{rawNil}, "{}", true},
1259 {Name(""), T2{&rawNil}, `{"M":null}`, true},
1260 {Name(""), &T1{rawNil}, "{}", true},
1261 {Name(""), &T2{&rawNil}, `{"M":null}`, true},
1262
1263
1264 {Name(""), rawEmpty, "", false},
1265 {Name(""), &rawEmpty, "", false},
1266 {Name(""), []any{rawEmpty}, "", false},
1267 {Name(""), &[]any{rawEmpty}, "", false},
1268 {Name(""), []any{&rawEmpty}, "", false},
1269 {Name(""), &[]any{&rawEmpty}, "", false},
1270 {Name(""), struct{ X RawMessage }{rawEmpty}, "", false},
1271 {Name(""), &struct{ X RawMessage }{rawEmpty}, "", false},
1272 {Name(""), struct{ X *RawMessage }{&rawEmpty}, "", false},
1273 {Name(""), &struct{ X *RawMessage }{&rawEmpty}, "", false},
1274 {Name(""), map[string]any{"nil": rawEmpty}, "", false},
1275 {Name(""), &map[string]any{"nil": rawEmpty}, "", false},
1276 {Name(""), map[string]any{"nil": &rawEmpty}, "", false},
1277 {Name(""), &map[string]any{"nil": &rawEmpty}, "", false},
1278 {Name(""), T1{rawEmpty}, "{}", true},
1279 {Name(""), T2{&rawEmpty}, "", false},
1280 {Name(""), &T1{rawEmpty}, "{}", true},
1281 {Name(""), &T2{&rawEmpty}, "", false},
1282
1283
1284
1285
1286
1287
1288 {Name(""), rawText, `"foo"`, true},
1289 {Name(""), &rawText, `"foo"`, true},
1290 {Name(""), []any{rawText}, `["foo"]`, true},
1291 {Name(""), &[]any{rawText}, `["foo"]`, true},
1292 {Name(""), []any{&rawText}, `["foo"]`, true},
1293 {Name(""), &[]any{&rawText}, `["foo"]`, true},
1294 {Name(""), struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1295 {Name(""), &struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1296 {Name(""), struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1297 {Name(""), &struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1298 {Name(""), map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1299 {Name(""), &map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1300 {Name(""), map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1301 {Name(""), &map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1302 {Name(""), T1{rawText}, `{"M":"foo"}`, true},
1303 {Name(""), T2{&rawText}, `{"M":"foo"}`, true},
1304 {Name(""), &T1{rawText}, `{"M":"foo"}`, true},
1305 {Name(""), &T2{&rawText}, `{"M":"foo"}`, true},
1306 }
1307
1308 for _, tt := range tests {
1309 t.Run(tt.Name, func(t *testing.T) {
1310 b, err := Marshal(tt.in)
1311 if ok := (err == nil); ok != tt.ok {
1312 if err != nil {
1313 t.Errorf("%s: Marshal error: %v", tt.Where, err)
1314 } else {
1315 t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)
1316 }
1317 }
1318 if got := string(b); got != tt.want {
1319 t.Errorf("%s: Marshal:\n\tinput: %#v\n\tgot: %s\n\twant: %s", tt.Where, tt.in, got, tt.want)
1320 }
1321 })
1322 }
1323 }
1324
1325 type marshalPanic struct{}
1326
1327 func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) }
1328
1329 func TestMarshalPanic(t *testing.T) {
1330 defer func() {
1331 if got := recover(); !reflect.DeepEqual(got, 0xdead) {
1332 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
1333 }
1334 }()
1335 Marshal(&marshalPanic{})
1336 t.Error("Marshal should have panicked")
1337 }
1338
1339 func TestMarshalUncommonFieldNames(t *testing.T) {
1340 v := struct {
1341 A0, À, Aβ int
1342 }{}
1343 b, err := Marshal(v)
1344 if err != nil {
1345 t.Fatal("Marshal error:", err)
1346 }
1347 want := `{"A0":0,"À":0,"Aβ":0}`
1348 got := string(b)
1349 if got != want {
1350 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1351 }
1352 }
1353
1354 func TestMarshalerError(t *testing.T) {
1355 s := "test variable"
1356 st := reflect.TypeOf(s)
1357 const errText = "json: test error"
1358
1359 tests := []struct {
1360 CaseName
1361 err *MarshalerError
1362 want string
1363 }{{
1364 Name(""),
1365 &MarshalerError{st, fmt.Errorf(errText), ""},
1366 "json: error calling MarshalJSON for type " + st.String() + ": " + errText,
1367 }, {
1368 Name(""),
1369 &MarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"},
1370 "json: error calling TestMarshalerError for type " + st.String() + ": " + errText,
1371 }}
1372
1373 for _, tt := range tests {
1374 t.Run(tt.Name, func(t *testing.T) {
1375 got := tt.err.Error()
1376 if got != tt.want {
1377 t.Errorf("%s: Error:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want)
1378 }
1379 })
1380 }
1381 }
1382
1383 type marshaledValue string
1384
1385 func (v marshaledValue) MarshalJSON() ([]byte, error) {
1386 return []byte(v), nil
1387 }
1388
1389 func TestIssue63379(t *testing.T) {
1390 for _, v := range []string{
1391 "[]<",
1392 "[]>",
1393 "[]&",
1394 "[]\u2028",
1395 "[]\u2029",
1396 "{}<",
1397 "{}>",
1398 "{}&",
1399 "{}\u2028",
1400 "{}\u2029",
1401 } {
1402 _, err := Marshal(marshaledValue(v))
1403 if err == nil {
1404 t.Errorf("expected error for %q", v)
1405 }
1406 }
1407 }
1408
1409
1410
1411
1412 func TestSynctestMarshal(t *testing.T) {
1413 var wg sync.WaitGroup
1414 for range 5 {
1415 wg.Go(func() {
1416 synctest.Test(t, func(t *testing.T) {
1417 _, err := Marshal([]string{})
1418 if err != nil {
1419 t.Errorf("Marshal: %v", err)
1420 }
1421 })
1422 })
1423 }
1424 wg.Wait()
1425 }
1426
View as plain text