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