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