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 func TestOmitEmpty(t *testing.T) {
48 var want = `{
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 var o Optionals
60 o.Sw = "something"
61 o.Mr = map[string]any{}
62 o.Mo = map[string]any{}
63
64 got, err := MarshalIndent(&o, "", " ")
65 if err != nil {
66 t.Fatalf("MarshalIndent error: %v", err)
67 }
68 if got := string(got); got != want {
69 t.Errorf("MarshalIndent:\n\tgot: %s\n\twant: %s\n", indentNewlines(got), indentNewlines(want))
70 }
71 }
72
73 type StringTag struct {
74 BoolStr bool `json:",string"`
75 IntStr int64 `json:",string"`
76 UintptrStr uintptr `json:",string"`
77 StrStr string `json:",string"`
78 NumberStr Number `json:",string"`
79 }
80
81 func TestRoundtripStringTag(t *testing.T) {
82 tests := []struct {
83 CaseName
84 in StringTag
85 want string
86 }{{
87 CaseName: Name("AllTypes"),
88 in: StringTag{
89 BoolStr: true,
90 IntStr: 42,
91 UintptrStr: 44,
92 StrStr: "xzbit",
93 NumberStr: "46",
94 },
95 want: `{
96 "BoolStr": "true",
97 "IntStr": "42",
98 "UintptrStr": "44",
99 "StrStr": "\"xzbit\"",
100 "NumberStr": "46"
101 }`,
102 }, {
103
104 CaseName: Name("StringDoubleEscapes"),
105 in: StringTag{
106 StrStr: "\b\f\n\r\t\"\\",
107 NumberStr: "0",
108 },
109 want: `{
110 "BoolStr": "false",
111 "IntStr": "0",
112 "UintptrStr": "0",
113 "StrStr": "\"\\b\\f\\n\\r\\t\\\"\\\\\"",
114 "NumberStr": "0"
115 }`,
116 }}
117 for _, tt := range tests {
118 t.Run(tt.Name, func(t *testing.T) {
119 got, err := MarshalIndent(&tt.in, "", "\t")
120 if err != nil {
121 t.Fatalf("%s: MarshalIndent error: %v", tt.Where, err)
122 }
123 if got := string(got); got != tt.want {
124 t.Fatalf("%s: MarshalIndent:\n\tgot: %s\n\twant: %s", tt.Where, stripWhitespace(got), stripWhitespace(tt.want))
125 }
126
127
128 var s2 StringTag
129 if err := Unmarshal(got, &s2); err != nil {
130 t.Fatalf("%s: Decode error: %v", tt.Where, err)
131 }
132 if !reflect.DeepEqual(s2, tt.in) {
133 t.Fatalf("%s: Decode:\n\tinput: %s\n\tgot: %#v\n\twant: %#v", tt.Where, indentNewlines(string(got)), s2, tt.in)
134 }
135 })
136 }
137 }
138
139
140 type renamedByte byte
141 type renamedByteSlice []byte
142 type renamedRenamedByteSlice []renamedByte
143
144 func TestEncodeRenamedByteSlice(t *testing.T) {
145 s := renamedByteSlice("abc")
146 got, err := Marshal(s)
147 if err != nil {
148 t.Fatalf("Marshal error: %v", err)
149 }
150 want := `"YWJj"`
151 if string(got) != want {
152 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
153 }
154 r := renamedRenamedByteSlice("abc")
155 got, err = Marshal(r)
156 if err != nil {
157 t.Fatalf("Marshal error: %v", err)
158 }
159 if string(got) != want {
160 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
161 }
162 }
163
164 type SamePointerNoCycle struct {
165 Ptr1, Ptr2 *SamePointerNoCycle
166 }
167
168 var samePointerNoCycle = &SamePointerNoCycle{}
169
170 type PointerCycle struct {
171 Ptr *PointerCycle
172 }
173
174 var pointerCycle = &PointerCycle{}
175
176 type PointerCycleIndirect struct {
177 Ptrs []any
178 }
179
180 type RecursiveSlice []RecursiveSlice
181
182 var (
183 pointerCycleIndirect = &PointerCycleIndirect{}
184 mapCycle = make(map[string]any)
185 sliceCycle = []any{nil}
186 sliceNoCycle = []any{nil, nil}
187 recursiveSliceCycle = []RecursiveSlice{nil}
188 )
189
190 func init() {
191 ptr := &SamePointerNoCycle{}
192 samePointerNoCycle.Ptr1 = ptr
193 samePointerNoCycle.Ptr2 = ptr
194
195 pointerCycle.Ptr = pointerCycle
196 pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect}
197
198 mapCycle["x"] = mapCycle
199 sliceCycle[0] = sliceCycle
200 sliceNoCycle[1] = sliceNoCycle[:1]
201 for i := startDetectingCyclesAfter; i > 0; i-- {
202 sliceNoCycle = []any{sliceNoCycle}
203 }
204 recursiveSliceCycle[0] = recursiveSliceCycle
205 }
206
207 func TestSamePointerNoCycle(t *testing.T) {
208 if _, err := Marshal(samePointerNoCycle); err != nil {
209 t.Fatalf("Marshal error: %v", err)
210 }
211 }
212
213 func TestSliceNoCycle(t *testing.T) {
214 if _, err := Marshal(sliceNoCycle); err != nil {
215 t.Fatalf("Marshal error: %v", err)
216 }
217 }
218
219 func TestUnsupportedValues(t *testing.T) {
220 tests := []struct {
221 CaseName
222 in any
223 }{
224 {Name(""), math.NaN()},
225 {Name(""), math.Inf(-1)},
226 {Name(""), math.Inf(1)},
227 {Name(""), pointerCycle},
228 {Name(""), pointerCycleIndirect},
229 {Name(""), mapCycle},
230 {Name(""), sliceCycle},
231 {Name(""), recursiveSliceCycle},
232 }
233 for _, tt := range tests {
234 t.Run(tt.Name, func(t *testing.T) {
235 if _, err := Marshal(tt.in); err != nil {
236 if _, ok := err.(*UnsupportedValueError); !ok {
237 t.Errorf("%s: Marshal error:\n\tgot: %T\n\twant: %T", tt.Where, err, new(UnsupportedValueError))
238 }
239 } else {
240 t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)
241 }
242 })
243 }
244 }
245
246
247 func TestMarshalTextFloatMap(t *testing.T) {
248 m := map[textfloat]string{
249 textfloat(math.NaN()): "1",
250 textfloat(math.NaN()): "1",
251 }
252 got, err := Marshal(m)
253 if err != nil {
254 t.Errorf("Marshal error: %v", err)
255 }
256 want := `{"TF:NaN":"1","TF:NaN":"1"}`
257 if string(got) != want {
258 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
259 }
260 }
261
262
263 type Ref int
264
265 func (*Ref) MarshalJSON() ([]byte, error) {
266 return []byte(`"ref"`), nil
267 }
268
269 func (r *Ref) UnmarshalJSON([]byte) error {
270 *r = 12
271 return nil
272 }
273
274
275 type Val int
276
277 func (Val) MarshalJSON() ([]byte, error) {
278 return []byte(`"val"`), nil
279 }
280
281
282 type RefText int
283
284 func (*RefText) MarshalText() ([]byte, error) {
285 return []byte(`"ref"`), nil
286 }
287
288 func (r *RefText) UnmarshalText([]byte) error {
289 *r = 13
290 return nil
291 }
292
293
294 type ValText int
295
296 func (ValText) MarshalText() ([]byte, error) {
297 return []byte(`"val"`), nil
298 }
299
300 func TestRefValMarshal(t *testing.T) {
301 var s = struct {
302 R0 Ref
303 R1 *Ref
304 R2 RefText
305 R3 *RefText
306 V0 Val
307 V1 *Val
308 V2 ValText
309 V3 *ValText
310 }{
311 R0: 12,
312 R1: new(Ref),
313 R2: 14,
314 R3: new(RefText),
315 V0: 13,
316 V1: new(Val),
317 V2: 15,
318 V3: new(ValText),
319 }
320 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
321 b, err := Marshal(&s)
322 if err != nil {
323 t.Fatalf("Marshal error: %v", err)
324 }
325 if got := string(b); got != want {
326 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
327 }
328 }
329
330
331 type C int
332
333 func (C) MarshalJSON() ([]byte, error) {
334 return []byte(`"<&>"`), nil
335 }
336
337
338 type CText int
339
340 func (CText) MarshalText() ([]byte, error) {
341 return []byte(`"<&>"`), nil
342 }
343
344 func TestMarshalerEscaping(t *testing.T) {
345 var c C
346 want := `"\u003c\u0026\u003e"`
347 b, err := Marshal(c)
348 if err != nil {
349 t.Fatalf("Marshal error: %v", err)
350 }
351 if got := string(b); got != want {
352 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
353 }
354
355 var ct CText
356 want = `"\"\u003c\u0026\u003e\""`
357 b, err = Marshal(ct)
358 if err != nil {
359 t.Fatalf("Marshal error: %v", err)
360 }
361 if got := string(b); got != want {
362 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
363 }
364 }
365
366 func TestAnonymousFields(t *testing.T) {
367 tests := []struct {
368 CaseName
369 makeInput func() any
370 want string
371 }{{
372
373
374
375 CaseName: Name("AmbiguousField"),
376 makeInput: func() any {
377 type (
378 S1 struct{ x, X int }
379 S2 struct{ x, X int }
380 S struct {
381 S1
382 S2
383 }
384 )
385 return S{S1{1, 2}, S2{3, 4}}
386 },
387 want: `{}`,
388 }, {
389 CaseName: Name("DominantField"),
390
391
392 makeInput: func() any {
393 type (
394 S1 struct{ x, X int }
395 S2 struct{ x, X int }
396 S struct {
397 S1
398 S2
399 x, X int
400 }
401 )
402 return S{S1{1, 2}, S2{3, 4}, 5, 6}
403 },
404 want: `{"X":6}`,
405 }, {
406
407 CaseName: Name("UnexportedEmbeddedInt"),
408 makeInput: func() any {
409 type (
410 myInt int
411 S struct{ myInt }
412 )
413 return S{5}
414 },
415 want: `{}`,
416 }, {
417
418 CaseName: Name("ExportedEmbeddedInt"),
419 makeInput: func() any {
420 type (
421 MyInt int
422 S struct{ MyInt }
423 )
424 return S{5}
425 },
426 want: `{"MyInt":5}`,
427 }, {
428
429
430 CaseName: Name("UnexportedEmbeddedIntPointer"),
431 makeInput: func() any {
432 type (
433 myInt int
434 S struct{ *myInt }
435 )
436 s := S{new(myInt)}
437 *s.myInt = 5
438 return s
439 },
440 want: `{}`,
441 }, {
442
443
444 CaseName: Name("ExportedEmbeddedIntPointer"),
445 makeInput: func() any {
446 type (
447 MyInt int
448 S struct{ *MyInt }
449 )
450 s := S{new(MyInt)}
451 *s.MyInt = 5
452 return s
453 },
454 want: `{"MyInt":5}`,
455 }, {
456
457
458
459 CaseName: Name("EmbeddedStruct"),
460 makeInput: func() any {
461 type (
462 s1 struct{ x, X int }
463 S2 struct{ y, Y int }
464 S struct {
465 s1
466 S2
467 }
468 )
469 return S{s1{1, 2}, S2{3, 4}}
470 },
471 want: `{"X":2,"Y":4}`,
472 }, {
473
474
475
476 CaseName: Name("EmbeddedStructPointer"),
477 makeInput: func() any {
478 type (
479 s1 struct{ x, X int }
480 S2 struct{ y, Y int }
481 S struct {
482 *s1
483 *S2
484 }
485 )
486 return S{&s1{1, 2}, &S2{3, 4}}
487 },
488 want: `{"X":2,"Y":4}`,
489 }, {
490
491
492 CaseName: Name("NestedStructAndInts"),
493 makeInput: func() any {
494 type (
495 MyInt1 int
496 MyInt2 int
497 myInt int
498 s2 struct {
499 MyInt2
500 myInt
501 }
502 s1 struct {
503 MyInt1
504 myInt
505 s2
506 }
507 S struct {
508 s1
509 myInt
510 }
511 )
512 return S{s1{1, 2, s2{3, 4}}, 6}
513 },
514 want: `{"MyInt1":1,"MyInt2":3}`,
515 }, {
516
517
518
519 CaseName: Name("EmbeddedFieldBehindNilPointer"),
520 makeInput: func() any {
521 type (
522 S2 struct{ Field string }
523 S struct{ *S2 }
524 )
525 return S{}
526 },
527 want: `{}`,
528 }}
529
530 for _, tt := range tests {
531 t.Run(tt.Name, func(t *testing.T) {
532 b, err := Marshal(tt.makeInput())
533 if err != nil {
534 t.Fatalf("%s: Marshal error: %v", tt.Where, err)
535 }
536 if string(b) != tt.want {
537 t.Fatalf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, b, tt.want)
538 }
539 })
540 }
541 }
542
543 type BugA struct {
544 S string
545 }
546
547 type BugB struct {
548 BugA
549 S string
550 }
551
552 type BugC struct {
553 S string
554 }
555
556
557 type BugX struct {
558 A int
559 BugA
560 BugB
561 }
562
563
564
565
566 type nilJSONMarshaler string
567
568 func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {
569 if nm == nil {
570 return Marshal("0zenil0")
571 }
572 return Marshal("zenil:" + string(*nm))
573 }
574
575
576
577
578 type nilTextMarshaler string
579
580 func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {
581 if nm == nil {
582 return []byte("0zenil0"), nil
583 }
584 return []byte("zenil:" + string(*nm)), nil
585 }
586
587
588 func TestNilMarshal(t *testing.T) {
589 tests := []struct {
590 CaseName
591 in any
592 want string
593 }{
594 {Name(""), nil, `null`},
595 {Name(""), new(float64), `0`},
596 {Name(""), []any(nil), `null`},
597 {Name(""), []string(nil), `null`},
598 {Name(""), map[string]string(nil), `null`},
599 {Name(""), []byte(nil), `null`},
600 {Name(""), struct{ M string }{"gopher"}, `{"M":"gopher"}`},
601 {Name(""), struct{ M Marshaler }{}, `{"M":null}`},
602 {Name(""), struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, `{"M":"0zenil0"}`},
603 {Name(""), struct{ M any }{(*nilJSONMarshaler)(nil)}, `{"M":null}`},
604 {Name(""), struct{ M encoding.TextMarshaler }{}, `{"M":null}`},
605 {Name(""), struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, `{"M":"0zenil0"}`},
606 {Name(""), struct{ M any }{(*nilTextMarshaler)(nil)}, `{"M":null}`},
607 }
608 for _, tt := range tests {
609 t.Run(tt.Name, func(t *testing.T) {
610 switch got, err := Marshal(tt.in); {
611 case err != nil:
612 t.Fatalf("%s: Marshal error: %v", tt.Where, err)
613 case string(got) != tt.want:
614 t.Fatalf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want)
615 }
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 error:", err)
629 }
630 want := `{"S":"B"}`
631 got := string(b)
632 if got != want {
633 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %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 error:", err)
642 }
643 want = `{"A":23}`
644 got = string(b)
645 if got != want {
646 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %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 error:", err)
669 }
670 want := `{"S":"BugD"}`
671 got := string(b)
672 if got != want {
673 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %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 error:", err)
696 }
697 want := `{}`
698 got := string(b)
699 if got != want {
700 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
701 }
702 }
703
704 func TestIssue10281(t *testing.T) {
705 type Foo struct {
706 N Number
707 }
708 x := Foo{Number(`invalid`)}
709
710 if _, err := Marshal(&x); err == nil {
711 t.Fatalf("Marshal error: got nil, want non-nil")
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 _, err := Marshal(dummy); err == nil {
728 t.Errorf("Marshal error: got nil, want non-nil")
729 }
730
731 type Data struct {
732 A string
733 I int
734 }
735 want := Data{A: "a", I: 1}
736 b, err := Marshal(want)
737 if err != nil {
738 t.Errorf("Marshal error: %v", err)
739 }
740
741 var got Data
742 if err := Unmarshal(b, &got); err != nil {
743 t.Errorf("Unmarshal error: %v", err)
744 }
745 if got != want {
746 t.Errorf("Unmarshal:\n\tgot: %v\n\twant: %v", got, want)
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:\n\tgot: %s\n\twant: %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 error: %v", err)
769 }
770 if got, want := string(b), `{"n":"42"}`; got != want {
771 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
772 }
773 var back stringPointer
774 switch err = Unmarshal(b, &back); {
775 case err != nil:
776 t.Fatalf("Unmarshal error: %v", err)
777 case back.N == nil:
778 t.Fatalf("Unmarshal: back.N = nil, want non-nil")
779 case *back.N != 42:
780 t.Fatalf("Unmarshal: *back.N = %d, want 42", *back.N)
781 }
782 }
783
784 var encodeStringTests = []struct {
785 in string
786 out string
787 }{
788 {"\x00", `"\u0000"`},
789 {"\x01", `"\u0001"`},
790 {"\x02", `"\u0002"`},
791 {"\x03", `"\u0003"`},
792 {"\x04", `"\u0004"`},
793 {"\x05", `"\u0005"`},
794 {"\x06", `"\u0006"`},
795 {"\x07", `"\u0007"`},
796 {"\x08", `"\b"`},
797 {"\x09", `"\t"`},
798 {"\x0a", `"\n"`},
799 {"\x0b", `"\u000b"`},
800 {"\x0c", `"\f"`},
801 {"\x0d", `"\r"`},
802 {"\x0e", `"\u000e"`},
803 {"\x0f", `"\u000f"`},
804 {"\x10", `"\u0010"`},
805 {"\x11", `"\u0011"`},
806 {"\x12", `"\u0012"`},
807 {"\x13", `"\u0013"`},
808 {"\x14", `"\u0014"`},
809 {"\x15", `"\u0015"`},
810 {"\x16", `"\u0016"`},
811 {"\x17", `"\u0017"`},
812 {"\x18", `"\u0018"`},
813 {"\x19", `"\u0019"`},
814 {"\x1a", `"\u001a"`},
815 {"\x1b", `"\u001b"`},
816 {"\x1c", `"\u001c"`},
817 {"\x1d", `"\u001d"`},
818 {"\x1e", `"\u001e"`},
819 {"\x1f", `"\u001f"`},
820 }
821
822 func TestEncodeString(t *testing.T) {
823 for _, tt := range encodeStringTests {
824 b, err := Marshal(tt.in)
825 if err != nil {
826 t.Errorf("Marshal(%q) error: %v", tt.in, err)
827 continue
828 }
829 out := string(b)
830 if out != tt.out {
831 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
832 }
833 }
834 }
835
836 type jsonbyte byte
837
838 func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }
839
840 type textbyte byte
841
842 func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }
843
844 type jsonint int
845
846 func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }
847
848 type textint int
849
850 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }
851
852 func tenc(format string, a ...any) ([]byte, error) {
853 var buf bytes.Buffer
854 fmt.Fprintf(&buf, format, a...)
855 return buf.Bytes(), nil
856 }
857
858 type textfloat float64
859
860 func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
861
862
863 func TestEncodeBytekind(t *testing.T) {
864 tests := []struct {
865 CaseName
866 in any
867 want string
868 }{
869 {Name(""), byte(7), "7"},
870 {Name(""), jsonbyte(7), `{"JB":7}`},
871 {Name(""), textbyte(4), `"TB:4"`},
872 {Name(""), jsonint(5), `{"JI":5}`},
873 {Name(""), textint(1), `"TI:1"`},
874 {Name(""), []byte{0, 1}, `"AAE="`},
875 {Name(""), []jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},
876 {Name(""), [][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},
877 {Name(""), []textbyte{2, 3}, `["TB:2","TB:3"]`},
878 {Name(""), []jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
879 {Name(""), []textint{9, 3}, `["TI:9","TI:3"]`},
880 {Name(""), []int{9, 3}, `[9,3]`},
881 {Name(""), []textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
882 }
883 for _, tt := range tests {
884 t.Run(tt.Name, func(t *testing.T) {
885 b, err := Marshal(tt.in)
886 if err != nil {
887 t.Errorf("%s: Marshal error: %v", tt.Where, err)
888 }
889 got, want := string(b), tt.want
890 if got != want {
891 t.Errorf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, got, want)
892 }
893 })
894 }
895 }
896
897 func TestTextMarshalerMapKeysAreSorted(t *testing.T) {
898 got, 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("Marshal error: %v", err)
906 }
907 const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}`
908 if string(got) != want {
909 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
910 }
911 }
912
913
914 func TestNilMarshalerTextMapKey(t *testing.T) {
915 got, err := Marshal(map[*unmarshalerText]int{
916 (*unmarshalerText)(nil): 1,
917 {"A", "B"}: 2,
918 })
919 if err != nil {
920 t.Fatalf("Marshal error: %v", err)
921 }
922 const want = `{"":1,"A:B":2}`
923 if string(got) != want {
924 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, 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)) error: %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("ParseFloat(%q) error: %v", out, err)
973 nfail++
974 return
975 }
976 if f != g || fmt.Sprint(f) != fmt.Sprint(g) {
977 t.Errorf("ParseFloat(%q):\n\tgot: %g\n\twant: %g", 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 CaseName
1053 in any
1054 want string
1055 ok bool
1056 }{
1057
1058 {Name(""), rawNil, "null", true},
1059 {Name(""), &rawNil, "null", true},
1060 {Name(""), []any{rawNil}, "[null]", true},
1061 {Name(""), &[]any{rawNil}, "[null]", true},
1062 {Name(""), []any{&rawNil}, "[null]", true},
1063 {Name(""), &[]any{&rawNil}, "[null]", true},
1064 {Name(""), struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1065 {Name(""), &struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1066 {Name(""), struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1067 {Name(""), &struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1068 {Name(""), map[string]any{"M": rawNil}, `{"M":null}`, true},
1069 {Name(""), &map[string]any{"M": rawNil}, `{"M":null}`, true},
1070 {Name(""), map[string]any{"M": &rawNil}, `{"M":null}`, true},
1071 {Name(""), &map[string]any{"M": &rawNil}, `{"M":null}`, true},
1072 {Name(""), T1{rawNil}, "{}", true},
1073 {Name(""), T2{&rawNil}, `{"M":null}`, true},
1074 {Name(""), &T1{rawNil}, "{}", true},
1075 {Name(""), &T2{&rawNil}, `{"M":null}`, true},
1076
1077
1078 {Name(""), rawEmpty, "", false},
1079 {Name(""), &rawEmpty, "", false},
1080 {Name(""), []any{rawEmpty}, "", false},
1081 {Name(""), &[]any{rawEmpty}, "", false},
1082 {Name(""), []any{&rawEmpty}, "", false},
1083 {Name(""), &[]any{&rawEmpty}, "", false},
1084 {Name(""), struct{ X RawMessage }{rawEmpty}, "", false},
1085 {Name(""), &struct{ X RawMessage }{rawEmpty}, "", false},
1086 {Name(""), struct{ X *RawMessage }{&rawEmpty}, "", false},
1087 {Name(""), &struct{ X *RawMessage }{&rawEmpty}, "", false},
1088 {Name(""), map[string]any{"nil": rawEmpty}, "", false},
1089 {Name(""), &map[string]any{"nil": rawEmpty}, "", false},
1090 {Name(""), map[string]any{"nil": &rawEmpty}, "", false},
1091 {Name(""), &map[string]any{"nil": &rawEmpty}, "", false},
1092 {Name(""), T1{rawEmpty}, "{}", true},
1093 {Name(""), T2{&rawEmpty}, "", false},
1094 {Name(""), &T1{rawEmpty}, "{}", true},
1095 {Name(""), &T2{&rawEmpty}, "", false},
1096
1097
1098
1099
1100
1101
1102 {Name(""), rawText, `"foo"`, true},
1103 {Name(""), &rawText, `"foo"`, true},
1104 {Name(""), []any{rawText}, `["foo"]`, true},
1105 {Name(""), &[]any{rawText}, `["foo"]`, true},
1106 {Name(""), []any{&rawText}, `["foo"]`, true},
1107 {Name(""), &[]any{&rawText}, `["foo"]`, true},
1108 {Name(""), struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1109 {Name(""), &struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1110 {Name(""), struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1111 {Name(""), &struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1112 {Name(""), map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1113 {Name(""), &map[string]any{"M": rawText}, `{"M":"foo"}`, true},
1114 {Name(""), map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1115 {Name(""), &map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1116 {Name(""), T1{rawText}, `{"M":"foo"}`, true},
1117 {Name(""), T2{&rawText}, `{"M":"foo"}`, true},
1118 {Name(""), &T1{rawText}, `{"M":"foo"}`, true},
1119 {Name(""), &T2{&rawText}, `{"M":"foo"}`, true},
1120 }
1121
1122 for _, tt := range tests {
1123 t.Run(tt.Name, func(t *testing.T) {
1124 b, err := Marshal(tt.in)
1125 if ok := (err == nil); ok != tt.ok {
1126 if err != nil {
1127 t.Errorf("%s: Marshal error: %v", tt.Where, err)
1128 } else {
1129 t.Errorf("%s: Marshal error: got nil, want non-nil", tt.Where)
1130 }
1131 }
1132 if got := string(b); got != tt.want {
1133 t.Errorf("%s: Marshal:\n\tinput: %#v\n\tgot: %s\n\twant: %s", tt.Where, tt.in, got, tt.want)
1134 }
1135 })
1136 }
1137 }
1138
1139 type marshalPanic struct{}
1140
1141 func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) }
1142
1143 func TestMarshalPanic(t *testing.T) {
1144 defer func() {
1145 if got := recover(); !reflect.DeepEqual(got, 0xdead) {
1146 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
1147 }
1148 }()
1149 Marshal(&marshalPanic{})
1150 t.Error("Marshal should have panicked")
1151 }
1152
1153 func TestMarshalUncommonFieldNames(t *testing.T) {
1154 v := struct {
1155 A0, À, Aβ int
1156 }{}
1157 b, err := Marshal(v)
1158 if err != nil {
1159 t.Fatal("Marshal error:", err)
1160 }
1161 want := `{"A0":0,"À":0,"Aβ":0}`
1162 got := string(b)
1163 if got != want {
1164 t.Fatalf("Marshal:\n\tgot: %s\n\twant: %s", got, want)
1165 }
1166 }
1167
1168 func TestMarshalerError(t *testing.T) {
1169 s := "test variable"
1170 st := reflect.TypeOf(s)
1171 const errText = "json: test error"
1172
1173 tests := []struct {
1174 CaseName
1175 err *MarshalerError
1176 want string
1177 }{{
1178 Name(""),
1179 &MarshalerError{st, fmt.Errorf(errText), ""},
1180 "json: error calling MarshalJSON for type " + st.String() + ": " + errText,
1181 }, {
1182 Name(""),
1183 &MarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"},
1184 "json: error calling TestMarshalerError for type " + st.String() + ": " + errText,
1185 }}
1186
1187 for _, tt := range tests {
1188 t.Run(tt.Name, func(t *testing.T) {
1189 got := tt.err.Error()
1190 if got != tt.want {
1191 t.Errorf("%s: Error:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want)
1192 }
1193 })
1194 }
1195 }
1196
1197 type marshaledValue string
1198
1199 func (v marshaledValue) MarshalJSON() ([]byte, error) {
1200 return []byte(v), nil
1201 }
1202
1203 func TestIssue63379(t *testing.T) {
1204 for _, v := range []string{
1205 "[]<",
1206 "[]>",
1207 "[]&",
1208 "[]\u2028",
1209 "[]\u2029",
1210 "{}<",
1211 "{}>",
1212 "{}&",
1213 "{}\u2028",
1214 "{}\u2029",
1215 } {
1216 _, err := Marshal(marshaledValue(v))
1217 if err == nil {
1218 t.Errorf("expected error for %q", v)
1219 }
1220 }
1221 }
1222
View as plain text