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