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
1115 type textMarshalerString string
1116
1117 func (s textMarshalerString) MarshalText() ([]byte, error) {
1118 return []byte("X_" + string(s)), nil
1119 }
1120
1121 func (s textMarshalerString) AppendText(b []byte) ([]byte, error) {
1122 return append(b, ("X_" + string(s))...), nil
1123 }
1124
1125
1126
1127 func TestStringKindTextMarshalerMapKey(t *testing.T) {
1128 got, err := Marshal(map[textMarshalerString]textMarshalerString{"foo": "bar"})
1129 if err != nil {
1130 t.Fatalf("Marshal error: %v", err)
1131 }
1132 const want = `{"foo":"X_bar"}`
1133 if string(got) != want {
1134 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1135 }
1136 }
1137
1138 var re = regexp.MustCompile
1139
1140
1141 var badFloatREs = []*regexp.Regexp{
1142 re(`p`),
1143 re(`^\+`),
1144 re(`^-?0[^.]`),
1145 re(`^-?\.`),
1146 re(`\.(e|$)`),
1147 re(`\.[0-9]+0(e|$)`),
1148 re(`^-?(0|[0-9]{2,})\..*e`),
1149 re(`e[0-9]`),
1150 re(`e[+-]0`),
1151 re(`e-[1-6]$`),
1152 re(`e+(.|1.|20)$`),
1153 re(`^-?0\.0000000`),
1154 re(`^-?[0-9]{22}`),
1155 re(`[1-9][0-9]{16}[1-9]`),
1156 re(`[1-9][0-9.]{17}[1-9]`),
1157
1158 re(`[1-9][0-9]{8}[1-9]`),
1159 re(`[1-9][0-9.]{9}[1-9]`),
1160 }
1161
1162 func TestMarshalFloat(t *testing.T) {
1163 t.Parallel()
1164 nfail := 0
1165 test := func(f float64, bits int) {
1166 vf := any(f)
1167 if bits == 32 {
1168 f = float64(float32(f))
1169 vf = float32(f)
1170 }
1171 bout, err := Marshal(vf)
1172 if err != nil {
1173 t.Errorf("Marshal(%T(%g)) error: %v", vf, vf, err)
1174 nfail++
1175 return
1176 }
1177 out := string(bout)
1178
1179
1180 g, err := strconv.ParseFloat(out, bits)
1181 if err != nil {
1182 t.Errorf("ParseFloat(%q) error: %v", out, err)
1183 nfail++
1184 return
1185 }
1186 if f != g || fmt.Sprint(f) != fmt.Sprint(g) {
1187 t.Errorf("ParseFloat(%q):\n\tgot: %g\n\twant: %g", out, float32(g), vf)
1188 nfail++
1189 return
1190 }
1191
1192 bad := badFloatREs
1193 if bits == 64 {
1194 bad = bad[:len(bad)-2]
1195 }
1196 for _, re := range bad {
1197 if re.MatchString(out) {
1198 t.Errorf("Marshal(%T(%g)) = %q; must not match /%s/", vf, vf, out, re)
1199 nfail++
1200 return
1201 }
1202 }
1203 }
1204
1205 var (
1206 bigger = math.Inf(+1)
1207 smaller = math.Inf(-1)
1208 )
1209
1210 var digits = "1.2345678901234567890123"
1211 for i := len(digits); i >= 2; i-- {
1212 if testing.Short() && i < len(digits)-4 {
1213 break
1214 }
1215 for exp := -30; exp <= 30; exp++ {
1216 for _, sign := range "+-" {
1217 for bits := 32; bits <= 64; bits += 32 {
1218 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
1219 f, err := strconv.ParseFloat(s, bits)
1220 if err != nil {
1221 log.Fatal(err)
1222 }
1223 next := math.Nextafter
1224 if bits == 32 {
1225 next = func(g, h float64) float64 {
1226 return float64(math.Nextafter32(float32(g), float32(h)))
1227 }
1228 }
1229 test(f, bits)
1230 test(next(f, bigger), bits)
1231 test(next(f, smaller), bits)
1232 if nfail > 50 {
1233 t.Fatalf("stopping test early")
1234 }
1235 }
1236 }
1237 }
1238 }
1239 test(0, 64)
1240 test(math.Copysign(0, -1), 64)
1241 test(0, 32)
1242 test(math.Copysign(0, -1), 32)
1243 }
1244
1245 func TestMarshalRawMessageValue(t *testing.T) {
1246 type (
1247 T1 struct {
1248 M RawMessage `json:",omitempty"`
1249 }
1250 T2 struct {
1251 M *RawMessage `json:",omitempty"`
1252 }
1253 )
1254
1255 var (
1256 rawNil = RawMessage(nil)
1257 rawEmpty = RawMessage([]byte{})
1258 rawText = RawMessage([]byte(`"foo"`))
1259 )
1260
1261 tests := []struct {
1262 CaseName
1263 in any
1264 want string
1265 ok bool
1266 }{
1267
1268 {Name(""), rawNil, "null", true},
1269 {Name(""), &rawNil, "null", true},
1270 {Name(""), []any{rawNil}, "[null]", true},
1271 {Name(""), &[]any{rawNil}, "[null]", true},
1272 {Name(""), []any{&rawNil}, "[null]", true},
1273 {Name(""), &[]any{&rawNil}, "[null]", true},
1274 {Name(""), struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1275 {Name(""), &struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1276 {Name(""), struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1277 {Name(""), &struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1278 {Name(""), map[string]any{"M": rawNil}, `{"M":null}`, true},
1279 {Name(""), &map[string]any{"M": rawNil}, `{"M":null}`, true},
1280 {Name(""), map[string]any{"M": &rawNil}, `{"M":null}`, true},
1281 {Name(""), &map[string]any{"M": &rawNil}, `{"M":null}`, true},
1282 {Name(""), T1{rawNil}, "{}", true},
1283 {Name(""), T2{&rawNil}, `{"M":null}`, true},
1284 {Name(""), &T1{rawNil}, "{}", true},
1285 {Name(""), &T2{&rawNil}, `{"M":null}`, true},
1286
1287
1288 {Name(""), rawEmpty, "", false},
1289 {Name(""), &rawEmpty, "", false},
1290 {Name(""), []any{rawEmpty}, "", false},
1291 {Name(""), &[]any{rawEmpty}, "", false},
1292 {Name(""), []any{&rawEmpty}, "", false},
1293 {Name(""), &[]any{&rawEmpty}, "", false},
1294 {Name(""), struct{ X RawMessage }{rawEmpty}, "", false},
1295 {Name(""), &struct{ X RawMessage }{rawEmpty}, "", false},
1296 {Name(""), struct{ X *RawMessage }{&rawEmpty}, "", false},
1297 {Name(""), &struct{ X *RawMessage }{&rawEmpty}, "", false},
1298 {Name(""), map[string]any{"nil": rawEmpty}, "", false},
1299 {Name(""), &map[string]any{"nil": rawEmpty}, "", false},
1300 {Name(""), map[string]any{"nil": &rawEmpty}, "", false},
1301 {Name(""), &map[string]any{"nil": &rawEmpty}, "", false},
1302 {Name(""), T1{rawEmpty}, "{}", true},
1303 {Name(""), T2{&rawEmpty}, "", false},
1304 {Name(""), &T1{rawEmpty}, "{}", true},
1305 {Name(""), &T2{&rawEmpty}, "", false},
1306
1307
1308
1309
1310
1311
1312 {Name(""), rawText, `"foo"`, true},
1313 {Name(""), &rawText, `"foo"`, true},
1314 {Name(""), []any{rawText}, `["foo"]`, true},
1315 {Name(""), &[]any{rawText}, `["foo"]`, true},
1316 {Name(""), []any{&rawText}, `["foo"]`, true},
1317 {Name(""), &[]any{&rawText}, `["foo"]`, true},
1318 {Name(""), struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1319 {Name(""), &struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1320 {Name(""), struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1321 {Name(""), &struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1322 {Name(""), map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1323 {Name(""), &map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1324 {Name(""), map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1325 {Name(""), &map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1326 {Name(""), T1{rawText}, `{"M":"foo"}`, true},
1327 {Name(""), T2{&rawText}, `{"M":"foo"}`, true},
1328 {Name(""), &T1{rawText}, `{"M":"foo"}`, true},
1329 {Name(""), &T2{&rawText}, `{"M":"foo"}`, true},
1330 }
1331
1332 for _, tt := range tests {
1333 t.Run(tt.Name, func(t *testing.T) {
1334 b, err := Marshal(tt.in)
1335 if ok := (err == nil); ok != tt.ok {
1336 if err != nil {
1337 t.Errorf("%s: Marshal error: %v", tt.Where, err)
1338 } else {
1339 t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)
1340 }
1341 }
1342 if got := string(b); got != tt.want {
1343 t.Errorf("%s: Marshal:\n\tinput: %#v\n\tgot: %s\n\twant: %s", tt.Where, tt.in, got, tt.want)
1344 }
1345 })
1346 }
1347 }
1348
1349 type marshalPanic struct{}
1350
1351 func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) }
1352
1353 func TestMarshalPanic(t *testing.T) {
1354 defer func() {
1355 if got := recover(); !reflect.DeepEqual(got, 0xdead) {
1356 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
1357 }
1358 }()
1359 Marshal(&marshalPanic{})
1360 t.Error("Marshal should have panicked")
1361 }
1362
1363 func TestMarshalUncommonFieldNames(t *testing.T) {
1364 v := struct {
1365 A0, À, Aβ int
1366 }{}
1367 b, err := Marshal(v)
1368 if err != nil {
1369 t.Fatal("Marshal error:", err)
1370 }
1371 want := `{"A0":0,"À":0,"Aβ":0}`
1372 got := string(b)
1373 if got != want {
1374 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1375 }
1376 }
1377
1378 func TestMarshalerError(t *testing.T) {
1379 s := "test variable"
1380 st := reflect.TypeOf(s)
1381 const errText = "json: test error"
1382
1383 tests := []struct {
1384 CaseName
1385 err *MarshalerError
1386 want string
1387 }{{
1388 Name(""),
1389 &MarshalerError{st, fmt.Errorf(errText), ""},
1390 "json: error calling MarshalJSON for type " + st.String() + ": " + errText,
1391 }, {
1392 Name(""),
1393 &MarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"},
1394 "json: error calling TestMarshalerError for type " + st.String() + ": " + errText,
1395 }}
1396
1397 for _, tt := range tests {
1398 t.Run(tt.Name, func(t *testing.T) {
1399 got := tt.err.Error()
1400 if got != tt.want {
1401 t.Errorf("%s: Error:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want)
1402 }
1403 })
1404 }
1405 }
1406
1407 type marshaledValue string
1408
1409 func (v marshaledValue) MarshalJSON() ([]byte, error) {
1410 return []byte(v), nil
1411 }
1412
1413 func TestIssue63379(t *testing.T) {
1414 for _, v := range []string{
1415 "[]<",
1416 "[]>",
1417 "[]&",
1418 "[]\u2028",
1419 "[]\u2029",
1420 "{}<",
1421 "{}>",
1422 "{}&",
1423 "{}\u2028",
1424 "{}\u2029",
1425 } {
1426 _, err := Marshal(marshaledValue(v))
1427 if err == nil {
1428 t.Errorf("expected error for %q", v)
1429 }
1430 }
1431 }
1432
1433
1434
1435
1436 func TestSynctestMarshal(t *testing.T) {
1437 var wg sync.WaitGroup
1438 for range 5 {
1439 wg.Go(func() {
1440 synctest.Test(t, func(t *testing.T) {
1441 _, err := Marshal([]string{})
1442 if err != nil {
1443 t.Errorf("Marshal: %v", err)
1444 }
1445 })
1446 })
1447 }
1448 wg.Wait()
1449 }
1450
View as plain text