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