github.com/searKing/golang/go@v1.2.74/encoding/prettyjson/encode_test.go (about) 1 // Copyright 2023 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package prettyjson 6 7 import ( 8 "bytes" 9 "encoding" 10 "encoding/json" 11 "errors" 12 "fmt" 13 "log" 14 "math" 15 "reflect" 16 "regexp" 17 "runtime/debug" 18 "strconv" 19 "testing" 20 "unicode" 21 ) 22 23 type Optionals struct { 24 Sr string `json:"sr"` 25 So string `json:"so,omitempty"` 26 Sw string `json:"-"` 27 28 Ir int `json:"omitempty"` // actually named omitempty, not an option 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 var optionalsExpected = `{ 51 "sr": "", 52 "omitempty": 0, 53 "slr": null, 54 "mr": {}, 55 "fr": 0, 56 "br": false, 57 "ur": 0, 58 "str": {}, 59 "sto": {} 60 }` 61 62 func TestOmitEmpty(t *testing.T) { 63 var o Optionals 64 o.Sw = "something" 65 o.Mr = map[string]any{} 66 o.Mo = map[string]any{} 67 68 got, err := MarshalIndent(&o, "", " ") 69 if err != nil { 70 t.Fatal(err) 71 } 72 if got := string(got); got != optionalsExpected { 73 t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected) 74 } 75 } 76 77 type StringTag struct { 78 BoolStr bool `json:",string"` 79 IntStr int64 `json:",string"` 80 UintptrStr uintptr `json:",string"` 81 StrStr string `json:",string"` 82 NumberStr Number `json:",string"` 83 } 84 85 func TestRoundtripStringTag(t *testing.T) { 86 tests := []struct { 87 name string 88 in StringTag 89 want string // empty to just test that we roundtrip 90 }{ 91 { 92 name: "AllTypes", 93 in: StringTag{ 94 BoolStr: true, 95 IntStr: 42, 96 UintptrStr: 44, 97 StrStr: "xzbit", 98 NumberStr: "46", 99 }, 100 want: `{ 101 "BoolStr": "true", 102 "IntStr": "42", 103 "UintptrStr": "44", 104 "StrStr": "\"xzbit\"", 105 "NumberStr": "46" 106 }`, 107 }, 108 { 109 // See golang.org/issues/38173. 110 name: "StringDoubleEscapes", 111 in: StringTag{ 112 StrStr: "\b\f\n\r\t\"\\", 113 NumberStr: "0", // just to satisfy the roundtrip 114 }, 115 want: `{ 116 "BoolStr": "false", 117 "IntStr": "0", 118 "UintptrStr": "0", 119 "StrStr": "\"\\u0008\\u000c\\n\\r\\t\\\"\\\\\"", 120 "NumberStr": "0" 121 }`, 122 }, 123 } 124 for _, test := range tests { 125 t.Run(test.name, func(t *testing.T) { 126 // Indent with a tab prefix to make the multi-line string 127 // literals in the table nicer to read. 128 got, err := MarshalIndent(&test.in, "\t\t\t", "\t") 129 if err != nil { 130 t.Fatal(err) 131 } 132 if got := string(got); got != test.want { 133 t.Fatalf(" got: %s\nwant: %s\n", got, test.want) 134 } 135 }) 136 } 137 } 138 139 // byte slices are special even if they're renamed types. 140 type renamedByte byte 141 type renamedByteSlice []byte 142 type renamedRenamedByteSlice []renamedByte 143 144 func TestEncodeRenamedByteSlice(t *testing.T) { 145 s := renamedByteSlice("abc") 146 result, err := Marshal(s) 147 if err != nil { 148 t.Fatal(err) 149 } 150 expect := `"YWJj"` 151 if string(result) != expect { 152 t.Errorf(" got %s want %s", result, expect) 153 } 154 r := renamedRenamedByteSlice("abc") 155 result, err = Marshal(r) 156 if err != nil { 157 t.Fatal(err) 158 } 159 if string(result) != expect { 160 t.Errorf(" got %s want %s", result, expect) 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("unexpected error: %v", err) 210 } 211 } 212 213 func TestSliceNoCycle(t *testing.T) { 214 if _, err := Marshal(sliceNoCycle); err != nil { 215 t.Fatalf("unexpected error: %v", err) 216 } 217 } 218 219 var unsupportedValues = []any{ 220 pointerCycle, 221 pointerCycleIndirect, 222 mapCycle, 223 sliceCycle, 224 recursiveSliceCycle, 225 } 226 227 func TestUnsupportedValues(t *testing.T) { 228 for _, v := range unsupportedValues { 229 if _, err := Marshal(v); err != nil { 230 if _, ok := err.(*UnsupportedValueError); !ok { 231 t.Errorf("for %v, got %T want UnsupportedValueError", v, err) 232 } 233 } else { 234 t.Errorf("for %v, expected error", v) 235 } 236 } 237 } 238 239 // Issue 43207 240 func TestMarshalTextFloatMap(t *testing.T) { 241 m := map[textfloat]string{ 242 textfloat(math.NaN()): "1", 243 textfloat(math.NaN()): "1", 244 } 245 got, err := Marshal(m) 246 if err != nil { 247 t.Errorf("Marshal() error: %v", err) 248 } 249 want := `{"TF:NaN":"1","TF:NaN":"1"}` 250 if string(got) != want { 251 t.Errorf("Marshal() = %s, want %s", got, want) 252 } 253 } 254 255 // Ref has Marshaler and Unmarshaler methods with pointer receiver. 256 type Ref int 257 258 func (*Ref) MarshalJSON() ([]byte, error) { 259 return []byte(`"ref"`), nil 260 } 261 262 func (r *Ref) UnmarshalJSON([]byte) error { 263 *r = 12 264 return nil 265 } 266 267 // Val has Marshaler methods with value receiver. 268 type Val int 269 270 func (Val) MarshalJSON() ([]byte, error) { 271 return []byte(`"val"`), nil 272 } 273 274 // RefText has Marshaler and Unmarshaler methods with pointer receiver. 275 type RefText int 276 277 func (*RefText) MarshalText() ([]byte, error) { 278 return []byte(`"ref"`), nil 279 } 280 281 func (r *RefText) UnmarshalText([]byte) error { 282 *r = 13 283 return nil 284 } 285 286 // ValText has Marshaler methods with value receiver. 287 type ValText int 288 289 func (ValText) MarshalText() ([]byte, error) { 290 return []byte(`"val"`), nil 291 } 292 293 func TestRefValMarshal(t *testing.T) { 294 var s = struct { 295 R0 Ref 296 R1 *Ref 297 R2 RefText 298 R3 *RefText 299 V0 Val 300 V1 *Val 301 V2 ValText 302 V3 *ValText 303 }{ 304 R0: 12, 305 R1: new(Ref), 306 R2: 14, 307 R3: new(RefText), 308 V0: 13, 309 V1: new(Val), 310 V2: 15, 311 V3: new(ValText), 312 } 313 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}` 314 b, err := Marshal(&s) 315 if err != nil { 316 t.Fatalf("Marshal: %v", err) 317 } 318 if got := string(b); got != want { 319 t.Errorf("got %q, want %q", got, want) 320 } 321 } 322 323 // C implements Marshaler and returns unescaped JSON. 324 type C int 325 326 func (C) MarshalJSON() ([]byte, error) { 327 return []byte(`"<&>"`), nil 328 } 329 330 // CText implements Marshaler and returns unescaped text. 331 type CText int 332 333 func (CText) MarshalText() ([]byte, error) { 334 return []byte(`"<&>"`), nil 335 } 336 337 func TestMarshalerEscaping(t *testing.T) { 338 var c C 339 want := `"\u003c\u0026\u003e"` 340 b, err := Marshal(c) 341 if err != nil { 342 t.Fatalf("Marshal(c): %v", err) 343 } 344 if got := string(b); got != want { 345 t.Errorf("Marshal(c) = %#q, want %#q", got, want) 346 } 347 348 var ct CText 349 want = `"\"\u003c\u0026\u003e\""` 350 b, err = Marshal(ct) 351 if err != nil { 352 t.Fatalf("Marshal(ct): %v", err) 353 } 354 if got := string(b); got != want { 355 t.Errorf("Marshal(ct) = %#q, want %#q", got, want) 356 } 357 } 358 359 func TestAnonymousFields(t *testing.T) { 360 tests := []struct { 361 label string // Test name 362 makeInput func() any // Function to create input value 363 want string // Expected JSON output 364 }{{ 365 // Both S1 and S2 have a field named X. From the perspective of S, 366 // it is ambiguous which one X refers to. 367 // This should not serialize either field. 368 label: "AmbiguousField", 369 makeInput: func() any { 370 type ( 371 S1 struct{ x, X int } 372 S2 struct{ x, X int } 373 S struct { 374 S1 375 S2 376 } 377 ) 378 return S{S1{1, 2}, S2{3, 4}} 379 }, 380 want: `{}`, 381 }, { 382 label: "DominantField", 383 // Both S1 and S2 have a field named X, but since S has an X field as 384 // well, it takes precedence over S1.X and S2.X. 385 makeInput: func() any { 386 type ( 387 S1 struct{ x, X int } 388 S2 struct{ x, X int } 389 S struct { 390 S1 391 S2 392 x, X int 393 } 394 ) 395 return S{S1{1, 2}, S2{3, 4}, 5, 6} 396 }, 397 want: `{"X":6}`, 398 }, { 399 // Unexported embedded field of non-struct type should not be serialized. 400 label: "UnexportedEmbeddedInt", 401 makeInput: func() any { 402 type ( 403 myInt int 404 S struct{ myInt } 405 ) 406 return S{5} 407 }, 408 want: `{}`, 409 }, { 410 // Exported embedded field of non-struct type should be serialized. 411 label: "ExportedEmbeddedInt", 412 makeInput: func() any { 413 type ( 414 MyInt int 415 S struct{ MyInt } 416 ) 417 return S{5} 418 }, 419 want: `{"MyInt":5}`, 420 }, { 421 // Unexported embedded field of pointer to non-struct type 422 // should not be serialized. 423 label: "UnexportedEmbeddedIntPointer", 424 makeInput: func() any { 425 type ( 426 myInt int 427 S struct{ *myInt } 428 ) 429 s := S{new(myInt)} 430 *s.myInt = 5 431 return s 432 }, 433 want: `{}`, 434 }, { 435 // Exported embedded field of pointer to non-struct type 436 // should be serialized. 437 label: "ExportedEmbeddedIntPointer", 438 makeInput: func() any { 439 type ( 440 MyInt int 441 S struct{ *MyInt } 442 ) 443 s := S{new(MyInt)} 444 *s.MyInt = 5 445 return s 446 }, 447 want: `{"MyInt":5}`, 448 }, { 449 // Exported fields of embedded structs should have their 450 // exported fields be serialized regardless of whether the struct types 451 // themselves are exported. 452 label: "EmbeddedStruct", 453 makeInput: func() any { 454 type ( 455 s1 struct{ x, X int } 456 S2 struct{ y, Y int } 457 S struct { 458 s1 459 S2 460 } 461 ) 462 return S{s1{1, 2}, S2{3, 4}} 463 }, 464 want: `{"X":2,"Y":4}`, 465 }, { 466 // Exported fields of pointers to embedded structs should have their 467 // exported fields be serialized regardless of whether the struct types 468 // themselves are exported. 469 label: "EmbeddedStructPointer", 470 makeInput: func() any { 471 type ( 472 s1 struct{ x, X int } 473 S2 struct{ y, Y int } 474 S struct { 475 *s1 476 *S2 477 } 478 ) 479 return S{&s1{1, 2}, &S2{3, 4}} 480 }, 481 want: `{"X":2,"Y":4}`, 482 }, { 483 // Exported fields on embedded unexported structs at multiple levels 484 // of nesting should still be serialized. 485 label: "NestedStructAndInts", 486 makeInput: func() any { 487 type ( 488 MyInt1 int 489 MyInt2 int 490 myInt int 491 s2 struct { 492 MyInt2 493 myInt 494 } 495 s1 struct { 496 MyInt1 497 myInt 498 s2 499 } 500 S struct { 501 s1 502 myInt 503 } 504 ) 505 return S{s1{1, 2, s2{3, 4}}, 6} 506 }, 507 want: `{"MyInt1":1,"MyInt2":3}`, 508 }, { 509 // If an anonymous struct pointer field is nil, we should ignore 510 // the embedded fields behind it. Not properly doing so may 511 // result in the wrong output or reflect panics. 512 label: "EmbeddedFieldBehindNilPointer", 513 makeInput: func() any { 514 type ( 515 S2 struct{ Field string } 516 S struct{ *S2 } 517 ) 518 return S{} 519 }, 520 want: `{}`, 521 }} 522 523 for _, tt := range tests { 524 t.Run(tt.label, func(t *testing.T) { 525 b, err := Marshal(tt.makeInput()) 526 if err != nil { 527 t.Fatalf("Marshal() = %v, want nil error", err) 528 } 529 if string(b) != tt.want { 530 t.Fatalf("Marshal() = %q, want %q", b, tt.want) 531 } 532 }) 533 } 534 } 535 536 type BugA struct { 537 S string 538 } 539 540 type BugB struct { 541 BugA 542 S string 543 } 544 545 type BugC struct { 546 S string 547 } 548 549 // Legal Go: We never use the repeated embedded field (S). 550 type BugX struct { 551 A int 552 BugA 553 BugB 554 } 555 556 // golang.org/issue/16042. 557 // Even if a nil interface value is passed in, as long as 558 // it implements Marshaler, it should be marshaled. 559 type nilJSONMarshaler string 560 561 func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) { 562 if nm == nil { 563 return Marshal("0zenil0") 564 } 565 return Marshal("zenil:" + string(*nm)) 566 } 567 568 // golang.org/issue/34235. 569 // Even if a nil interface value is passed in, as long as 570 // it implements encoding.TextMarshaler, it should be marshaled. 571 type nilTextMarshaler string 572 573 func (nm *nilTextMarshaler) MarshalText() ([]byte, error) { 574 if nm == nil { 575 return []byte("0zenil0"), nil 576 } 577 return []byte("zenil:" + string(*nm)), nil 578 } 579 580 // See golang.org/issue/16042 and golang.org/issue/34235. 581 func TestNilMarshal(t *testing.T) { 582 testCases := []struct { 583 v any 584 want string 585 }{ 586 {v: nil, want: `null`}, 587 {v: new(float64), want: `0`}, 588 {v: []any(nil), want: `null`}, 589 {v: []string(nil), want: `null`}, 590 {v: map[string]string(nil), want: `null`}, 591 {v: []byte(nil), want: `null`}, 592 {v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`}, 593 {v: struct{ M json.Marshaler }{}, want: `{"M":null}`}, 594 {v: struct{ M json.Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, 595 {v: struct{ M any }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`}, 596 {v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`}, 597 {v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, 598 {v: struct{ M any }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`}, 599 } 600 601 for _, tt := range testCases { 602 out, err := Marshal(tt.v) 603 if err != nil || string(out) != tt.want { 604 t.Errorf("Marshal(%#v) = %#q, %#v, want %#q, nil", tt.v, out, err, tt.want) 605 continue 606 } 607 } 608 } 609 610 // Issue 5245. 611 func TestEmbeddedBug(t *testing.T) { 612 v := BugB{ 613 BugA{"A"}, 614 "B", 615 } 616 b, err := Marshal(v) 617 if err != nil { 618 t.Fatal("Marshal:", err) 619 } 620 want := `{"S":"B"}` 621 got := string(b) 622 if got != want { 623 t.Fatalf("Marshal: got %s want %s", got, want) 624 } 625 // Now check that the duplicate field, S, does not appear. 626 x := BugX{ 627 A: 23, 628 } 629 b, err = Marshal(x) 630 if err != nil { 631 t.Fatal("Marshal:", err) 632 } 633 want = `{"A":23}` 634 got = string(b) 635 if got != want { 636 t.Fatalf("Marshal: got %s want %s", got, want) 637 } 638 } 639 640 type BugD struct { // Same as BugA after tagging. 641 XXX string `json:"S"` 642 } 643 644 // BugD's tagged S field should dominate BugA's. 645 type BugY struct { 646 BugA 647 BugD 648 } 649 650 // Test that a field with a tag dominates untagged fields. 651 func TestTaggedFieldDominates(t *testing.T) { 652 v := BugY{ 653 BugA{"BugA"}, 654 BugD{"BugD"}, 655 } 656 b, err := Marshal(v) 657 if err != nil { 658 t.Fatal("Marshal:", err) 659 } 660 want := `{"S":"BugD"}` 661 got := string(b) 662 if got != want { 663 t.Fatalf("Marshal: got %s want %s", got, want) 664 } 665 } 666 667 // There are no tags here, so S should not appear. 668 type BugZ struct { 669 BugA 670 BugC 671 BugY // Contains a tagged S field through BugD; should not dominate. 672 } 673 674 func TestDuplicatedFieldDisappears(t *testing.T) { 675 v := BugZ{ 676 BugA{"BugA"}, 677 BugC{"BugC"}, 678 BugY{ 679 BugA{"nested BugA"}, 680 BugD{"nested BugD"}, 681 }, 682 } 683 b, err := Marshal(v) 684 if err != nil { 685 t.Fatal("Marshal:", err) 686 } 687 want := `{}` 688 got := string(b) 689 if got != want { 690 t.Fatalf("Marshal: got %s want %s", got, want) 691 } 692 } 693 694 func TestStringBytes(t *testing.T) { 695 t.Parallel() 696 // Test that encodeState.stringBytes and encodeState.string use the same encoding. 697 var r []rune 698 for i := '\u0000'; i <= unicode.MaxRune; i++ { 699 if testing.Short() && i > 1000 { 700 i = unicode.MaxRune 701 } 702 r = append(r, i) 703 } 704 s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too 705 706 for _, escapeHTML := range []bool{true, false} { 707 es := &encodeState{} 708 es.string(s, escapeHTML) 709 710 esBytes := &encodeState{} 711 esBytes.stringBytes([]byte(s), escapeHTML) 712 713 enc := es.Buffer.String() 714 encBytes := esBytes.Buffer.String() 715 if enc != encBytes { 716 i := 0 717 for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] { 718 i++ 719 } 720 enc = enc[i:] 721 encBytes = encBytes[i:] 722 i = 0 723 for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] { 724 i++ 725 } 726 enc = enc[:len(enc)-i] 727 encBytes = encBytes[:len(encBytes)-i] 728 729 if len(enc) > 20 { 730 enc = enc[:20] + "..." 731 } 732 if len(encBytes) > 20 { 733 encBytes = encBytes[:20] + "..." 734 } 735 736 t.Errorf("with escapeHTML=%t, encodings differ at %#q vs %#q", 737 escapeHTML, enc, encBytes) 738 } 739 } 740 } 741 742 func TestIssue10281(t *testing.T) { 743 type Foo struct { 744 N Number 745 } 746 x := Foo{Number(`invalid`)} 747 748 b, err := Marshal(&x) 749 if err != nil { 750 t.Errorf("Marshal(&x) = %#q; want nil error", b) 751 } 752 } 753 754 func TestMarshalErrorAndReuseEncodeState(t *testing.T) { 755 // Disable the GC temporarily to prevent encodeState's in Pool being cleaned away during the test. 756 percent := debug.SetGCPercent(-1) 757 defer debug.SetGCPercent(percent) 758 759 // Trigger an error in Marshal with cyclic data. 760 type Dummy struct { 761 Name string 762 Next *Dummy 763 } 764 dummy := Dummy{Name: "Dummy"} 765 dummy.Next = &dummy 766 if b, err := Marshal(dummy); err == nil { 767 t.Errorf("Marshal(dummy) = %#q; want error", b) 768 } 769 770 type Data struct { 771 A string 772 I int 773 } 774 data := Data{A: "a", I: 1} 775 b, err := Marshal(data) 776 if err != nil { 777 t.Errorf("Marshal(%v) = %v", data, err) 778 } 779 780 _ = b 781 } 782 783 // golang.org/issue/8582 784 func TestEncodePointerString(t *testing.T) { 785 type stringPointer struct { 786 N *int64 `json:"n,string"` 787 } 788 var n int64 = 42 789 b, err := Marshal(stringPointer{N: &n}) 790 if err != nil { 791 t.Fatalf("Marshal: %v", err) 792 } 793 if got, want := string(b), `{"n":"42"}`; got != want { 794 t.Errorf("Marshal = %s, want %s", got, want) 795 } 796 } 797 798 var encodeStringTests = []struct { 799 in string 800 out string 801 }{ 802 {"\x00", `"\u0000"`}, 803 {"\x01", `"\u0001"`}, 804 {"\x02", `"\u0002"`}, 805 {"\x03", `"\u0003"`}, 806 {"\x04", `"\u0004"`}, 807 {"\x05", `"\u0005"`}, 808 {"\x06", `"\u0006"`}, 809 {"\x07", `"\u0007"`}, 810 {"\x08", `"\u0008"`}, 811 {"\x09", `"\t"`}, 812 {"\x0a", `"\n"`}, 813 {"\x0b", `"\u000b"`}, 814 {"\x0c", `"\u000c"`}, 815 {"\x0d", `"\r"`}, 816 {"\x0e", `"\u000e"`}, 817 {"\x0f", `"\u000f"`}, 818 {"\x10", `"\u0010"`}, 819 {"\x11", `"\u0011"`}, 820 {"\x12", `"\u0012"`}, 821 {"\x13", `"\u0013"`}, 822 {"\x14", `"\u0014"`}, 823 {"\x15", `"\u0015"`}, 824 {"\x16", `"\u0016"`}, 825 {"\x17", `"\u0017"`}, 826 {"\x18", `"\u0018"`}, 827 {"\x19", `"\u0019"`}, 828 {"\x1a", `"\u001a"`}, 829 {"\x1b", `"\u001b"`}, 830 {"\x1c", `"\u001c"`}, 831 {"\x1d", `"\u001d"`}, 832 {"\x1e", `"\u001e"`}, 833 {"\x1f", `"\u001f"`}, 834 } 835 836 func TestEncodeString(t *testing.T) { 837 for _, tt := range encodeStringTests { 838 b, err := Marshal(tt.in) 839 if err != nil { 840 t.Errorf("Marshal(%q): %v", tt.in, err) 841 continue 842 } 843 out := string(b) 844 if out != tt.out { 845 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out) 846 } 847 } 848 } 849 850 type jsonbyte byte 851 852 func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) } 853 854 type textbyte byte 855 856 func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) } 857 858 type jsonint int 859 860 func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) } 861 862 type textint int 863 864 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) } 865 866 func tenc(format string, a ...any) ([]byte, error) { 867 var buf bytes.Buffer 868 fmt.Fprintf(&buf, format, a...) 869 return buf.Bytes(), nil 870 } 871 872 type textfloat float64 873 874 func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) } 875 876 // Issue 13783 877 func TestEncodeBytekind(t *testing.T) { 878 testdata := []struct { 879 data any 880 want string 881 }{ 882 {byte(7), "7"}, 883 {jsonbyte(7), `{"JB":7}`}, 884 {textbyte(4), `"TB:4"`}, 885 {jsonint(5), `{"JI":5}`}, 886 {textint(1), `"TI:1"`}, 887 {[]byte{0, 1}, `"AAE="`}, 888 {[]jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`}, 889 {[][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`}, 890 {[]textbyte{2, 3}, `["TB:2","TB:3"]`}, 891 {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`}, 892 {[]textint{9, 3}, `["TI:9","TI:3"]`}, 893 {[]int{9, 3}, `[9,3]`}, 894 {[]textfloat{12, 3}, `["TF:12.00","TF:3.00"]`}, 895 } 896 for _, d := range testdata { 897 js, err := Marshal(d.data) 898 if err != nil { 899 t.Error(err) 900 continue 901 } 902 got, want := string(js), d.want 903 if got != want { 904 t.Errorf("got %s, want %s", got, want) 905 } 906 } 907 } 908 909 type unmarshalerText struct { 910 A, B string 911 } 912 913 // needed for re-marshaling tests 914 func (u unmarshalerText) MarshalText() ([]byte, error) { 915 return []byte(u.A + ":" + u.B), nil 916 } 917 918 func (u *unmarshalerText) UnmarshalText(b []byte) error { 919 pos := bytes.IndexByte(b, ':') 920 if pos == -1 { 921 return errors.New("missing separator") 922 } 923 u.A, u.B = string(b[:pos]), string(b[pos+1:]) 924 return nil 925 } 926 927 var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil) 928 929 func TestTextMarshalerMapKeysAreSorted(t *testing.T) { 930 b, err := Marshal(map[unmarshalerText]int{ 931 {"x", "y"}: 1, 932 {"y", "x"}: 2, 933 {"a", "z"}: 3, 934 {"z", "a"}: 4, 935 }) 936 if err != nil { 937 t.Fatalf("Failed to Marshal text.Marshaler: %v", err) 938 } 939 const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}` 940 if string(b) != want { 941 t.Errorf("Marshal map with text.Marshaler keys: got %#q, want %#q", b, want) 942 } 943 } 944 945 // https://golang.org/issue/33675 946 func TestNilMarshalerTextMapKey(t *testing.T) { 947 b, err := Marshal(map[*unmarshalerText]int{ 948 (*unmarshalerText)(nil): 1, 949 {"A", "B"}: 2, 950 }) 951 if err != nil { 952 t.Fatalf("Failed to Marshal *text.Marshaler: %v", err) 953 } 954 const want = `{"":1,"A:B":2}` 955 if string(b) != want { 956 t.Errorf("Marshal map with *text.Marshaler keys: got %#q, want %#q", b, want) 957 } 958 } 959 960 var re = regexp.MustCompile 961 962 // syntactic checks on form of marshaled floating point numbers. 963 var badFloatREs = []*regexp.Regexp{ 964 re(`p`), // no binary exponential notation 965 re(`^\+`), // no leading + sign 966 re(`^-?0[^.]`), // no unnecessary leading zeros 967 re(`^-?\.`), // leading zero required before decimal point 968 re(`\.(e|$)`), // no trailing decimal 969 re(`\.[0-9]+0(e|$)`), // no trailing zero in fraction 970 re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa 971 re(`e[0-9]`), // positive exponent must be signed 972 re(`e[+-]0`), // exponent must not have leading zeros 973 re(`e-[1-6]$`), // not tiny enough for exponential notation 974 re(`e+(.|1.|20)$`), // not big enough for exponential notation 975 re(`^-?0\.0000000`), // too tiny, should use exponential notation 976 re(`^-?[0-9]{22}`), // too big, should use exponential notation 977 re(`[1-9][0-9]{16}[1-9]`), // too many significant digits in integer 978 re(`[1-9][0-9.]{17}[1-9]`), // too many significant digits in decimal 979 // below here for float32 only 980 re(`[1-9][0-9]{8}[1-9]`), // too many significant digits in integer 981 re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal 982 } 983 984 func TestMarshalFloat(t *testing.T) { 985 t.Parallel() 986 nfail := 0 987 test := func(f float64, bits int) { 988 vf := any(f) 989 if bits == 32 { 990 f = float64(float32(f)) // round 991 vf = float32(f) 992 } 993 bout, err := Marshal(vf) 994 if err != nil { 995 t.Errorf("Marshal(%T(%g)): %v", vf, vf, err) 996 nfail++ 997 return 998 } 999 out := string(bout) 1000 1001 // result must convert back to the same float 1002 g, err := strconv.ParseFloat(out, bits) 1003 if err != nil { 1004 t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err) 1005 nfail++ 1006 return 1007 } 1008 if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0 1009 t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf) 1010 nfail++ 1011 return 1012 } 1013 1014 bad := badFloatREs 1015 if bits == 64 { 1016 bad = bad[:len(bad)-2] 1017 } 1018 for _, re := range bad { 1019 if re.MatchString(out) { 1020 t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re) 1021 nfail++ 1022 return 1023 } 1024 } 1025 } 1026 1027 var ( 1028 bigger = math.Inf(+1) 1029 smaller = math.Inf(-1) 1030 ) 1031 1032 var digits = "1.2345678901234567890123" 1033 for i := len(digits); i >= 2; i-- { 1034 if testing.Short() && i < len(digits)-4 { 1035 break 1036 } 1037 for exp := -30; exp <= 30; exp++ { 1038 for _, sign := range "+-" { 1039 for bits := 32; bits <= 64; bits += 32 { 1040 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp) 1041 f, err := strconv.ParseFloat(s, bits) 1042 if err != nil { 1043 log.Fatal(err) 1044 } 1045 next := math.Nextafter 1046 if bits == 32 { 1047 next = func(g, h float64) float64 { 1048 return float64(math.Nextafter32(float32(g), float32(h))) 1049 } 1050 } 1051 test(f, bits) 1052 test(next(f, bigger), bits) 1053 test(next(f, smaller), bits) 1054 if nfail > 50 { 1055 t.Fatalf("stopping test early") 1056 } 1057 } 1058 } 1059 } 1060 } 1061 test(0, 64) 1062 test(math.Copysign(0, -1), 64) 1063 test(0, 32) 1064 test(math.Copysign(0, -1), 32) 1065 } 1066 1067 func TestMarshalRawMessageValue(t *testing.T) { 1068 type ( 1069 T1 struct { 1070 M json.RawMessage `json:",omitempty"` 1071 } 1072 T2 struct { 1073 M *json.RawMessage `json:",omitempty"` 1074 } 1075 ) 1076 1077 var ( 1078 rawNil = json.RawMessage(nil) 1079 rawEmpty = json.RawMessage([]byte{}) 1080 rawText = json.RawMessage([]byte(`"foo"`)) 1081 ) 1082 1083 tests := []struct { 1084 in any 1085 want string 1086 ok bool 1087 }{ 1088 // Test with nil RawMessage. 1089 {rawNil, "null", true}, 1090 {&rawNil, "null", true}, 1091 {[]any{rawNil}, "[null]", true}, 1092 {&[]any{rawNil}, "[null]", true}, 1093 {[]any{&rawNil}, "[null]", true}, 1094 {&[]any{&rawNil}, "[null]", true}, 1095 {struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true}, 1096 {&struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true}, 1097 {struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true}, 1098 {&struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true}, 1099 {map[string]any{"M": rawNil}, `{"M":null}`, true}, 1100 {&map[string]any{"M": rawNil}, `{"M":null}`, true}, 1101 {map[string]any{"M": &rawNil}, `{"M":null}`, true}, 1102 {&map[string]any{"M": &rawNil}, `{"M":null}`, true}, 1103 {T1{rawNil}, "{}", true}, 1104 {T2{&rawNil}, `{"M":null}`, true}, 1105 {&T1{rawNil}, "{}", true}, 1106 {&T2{&rawNil}, `{"M":null}`, true}, 1107 1108 // Test with empty, but non-nil, RawMessage. 1109 {rawEmpty, "", false}, 1110 {&rawEmpty, "", false}, 1111 {[]any{rawEmpty}, "", false}, 1112 {&[]any{rawEmpty}, "", false}, 1113 {[]any{&rawEmpty}, "", false}, 1114 {&[]any{&rawEmpty}, "", false}, 1115 {struct{ X json.RawMessage }{rawEmpty}, "", false}, 1116 {&struct{ X json.RawMessage }{rawEmpty}, "", false}, 1117 {struct{ X *json.RawMessage }{&rawEmpty}, "", false}, 1118 {&struct{ X *json.RawMessage }{&rawEmpty}, "", false}, 1119 {map[string]any{"nil": rawEmpty}, "", false}, 1120 {&map[string]any{"nil": rawEmpty}, "", false}, 1121 {map[string]any{"nil": &rawEmpty}, "", false}, 1122 {&map[string]any{"nil": &rawEmpty}, "", false}, 1123 {T1{rawEmpty}, "{}", true}, 1124 {T2{&rawEmpty}, "", false}, 1125 {&T1{rawEmpty}, "{}", true}, 1126 {&T2{&rawEmpty}, "", false}, 1127 1128 // Test with RawMessage with some text. 1129 // 1130 // The tests below marked with Issue6458 used to generate "ImZvbyI=" instead "foo". 1131 // This behavior was intentionally changed in Go 1.8. 1132 // See https://golang.org/issues/14493#issuecomment-255857318 1133 {rawText, `"foo"`, true}, // Issue6458 1134 {&rawText, `"foo"`, true}, 1135 {[]any{rawText}, `["foo"]`, true}, // Issue6458 1136 {&[]any{rawText}, `["foo"]`, true}, // Issue6458 1137 {[]any{&rawText}, `["foo"]`, true}, 1138 {&[]any{&rawText}, `["foo"]`, true}, 1139 {struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458 1140 {&struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true}, 1141 {struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true}, 1142 {&struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true}, 1143 {map[string]any{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 1144 {&map[string]any{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 1145 {map[string]any{"M": &rawText}, `{"M":"foo"}`, true}, 1146 {&map[string]any{"M": &rawText}, `{"M":"foo"}`, true}, 1147 {T1{rawText}, `{"M":"foo"}`, true}, // Issue6458 1148 {T2{&rawText}, `{"M":"foo"}`, true}, 1149 {&T1{rawText}, `{"M":"foo"}`, true}, 1150 {&T2{&rawText}, `{"M":"foo"}`, true}, 1151 } 1152 1153 for i, tt := range tests { 1154 b, err := Marshal(tt.in) 1155 if ok := (err == nil); ok != tt.ok { 1156 if err != nil { 1157 t.Errorf("test %d, unexpected failure: %v", i, err) 1158 } else { 1159 t.Errorf("test %d, unexpected success", i) 1160 } 1161 } 1162 if got := string(b); got != tt.want { 1163 t.Errorf("test %d, Marshal(%#v) = %q, want %q", i, tt.in, got, tt.want) 1164 } 1165 } 1166 } 1167 1168 type marshalPanic struct{} 1169 1170 func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) } 1171 1172 func TestMarshalPanic(t *testing.T) { 1173 defer func() { 1174 if got := recover(); !reflect.DeepEqual(got, 0xdead) { 1175 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) 1176 } 1177 }() 1178 Marshal(&marshalPanic{}) 1179 t.Error("Marshal should have panicked") 1180 } 1181 1182 func TestMarshalUncommonFieldNames(t *testing.T) { 1183 v := struct { 1184 A0, À, Aβ int 1185 }{} 1186 b, err := Marshal(v) 1187 if err != nil { 1188 t.Fatal("Marshal:", err) 1189 } 1190 want := `{"A0":0,"À":0,"Aβ":0}` 1191 got := string(b) 1192 if got != want { 1193 t.Fatalf("Marshal: got %s want %s", got, want) 1194 } 1195 } 1196 1197 func TestMarshalerError(t *testing.T) { 1198 s := "test variable" 1199 st := reflect.TypeOf(s) 1200 errText := "json: test error" 1201 1202 tests := []struct { 1203 err *MarshalerError 1204 want string 1205 }{ 1206 { 1207 &MarshalerError{st, fmt.Errorf(errText), ""}, 1208 "json: error calling MarshalJSON for type " + st.String() + ": " + errText, 1209 }, 1210 { 1211 &MarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"}, 1212 "json: error calling TestMarshalerError for type " + st.String() + ": " + errText, 1213 }, 1214 } 1215 1216 for i, tt := range tests { 1217 got := tt.err.Error() 1218 if got != tt.want { 1219 t.Errorf("MarshalerError test %d, got: %s, want: %s", i, got, tt.want) 1220 } 1221 } 1222 } 1223 1224 type marshalTruncate struct { 1225 Sr string `json:"sr"` 1226 1227 Blr []byte `json:"blr,random"` 1228 1229 Slr []string `json:"slr,random"` 1230 1231 Mr map[string]*marshalTruncate `json:"mr"` 1232 1233 Str *marshalTruncate `json:"str"` 1234 } 1235 1236 var truncateExpected = `{ 1237 "sr": "abcdefghihklmnopqrstuvwxyz", 1238 "blr": "YWI= [(52)truncated 50 bytes]", 1239 "slr": [ 1240 "0 [(28)truncated 26 chars]", 1241 "1 [(54)truncated 52 chars]", 1242 "[(7)truncated 5 elems]" 1243 ], 1244 "mr": { 1245 "a": { 1246 "sr": "abcdefghihklmnopqrstuvwxyz", 1247 "blr": "YWI= [(26)truncated 24 bytes]", 1248 "slr": [ 1249 "0 [(28)truncated 26 chars]", 1250 "1 [(54)truncated 52 chars]", 1251 "[(7)truncated 5 elems]" 1252 ], 1253 "mr": null, 1254 "str": null 1255 }, 1256 "b": null, 1257 "[(4)truncated 2 elements]": "4" 1258 }, 1259 "str": { 1260 "sr": "abcdefghihklmnopqrstuvwxyz", 1261 "blr": "YWI= [(26)truncated 24 bytes]", 1262 "slr": [ 1263 "0 [(28)truncated 26 chars]", 1264 "1 [(54)truncated 52 chars]", 1265 "[(7)truncated 5 elems]" 1266 ], 1267 "mr": null, 1268 "str": null 1269 } 1270 }` 1271 1272 func TestTruncateMarshal(t *testing.T) { 1273 var o = marshalTruncate{ 1274 Sr: "abcdefghihklmnopqrstuvwxyz", 1275 Blr: []byte("abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 1276 Slr: []string{"0 abcdefghihklmnopqrstuvwxyz", 1277 "1 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1278 "2 abcdefghihklmnopqrstuvwxyzA", 1279 "3 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1280 "4 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1281 "5 abcdefghihklmnopqrstuvwxyzA", 1282 "6 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}, 1283 Mr: map[string]*marshalTruncate{ 1284 "a": { 1285 Sr: "abcdefghihklmnopqrstuvwxyz", 1286 Blr: []byte("abcdefghihklmnopqrstuvwxyz"), 1287 Slr: []string{"0 abcdefghihklmnopqrstuvwxyz", 1288 "1 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1289 "2 abcdefghihklmnopqrstuvwxyzA", 1290 "3 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1291 "4 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1292 "5 abcdefghihklmnopqrstuvwxyzA", 1293 "6 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}, 1294 Mr: nil, 1295 Str: nil, 1296 }, 1297 "b": nil, 1298 "c": nil, 1299 "d": nil, 1300 }, 1301 Str: &marshalTruncate{ 1302 Sr: "abcdefghihklmnopqrstuvwxyz", 1303 Blr: []byte("abcdefghihklmnopqrstuvwxyz"), 1304 Slr: []string{"0 abcdefghihklmnopqrstuvwxyz", 1305 "1 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1306 "2 abcdefghihklmnopqrstuvwxyzA", 1307 "3 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1308 "4 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 1309 "5 abcdefghihklmnopqrstuvwxyzA", 1310 "6 abcdefghihklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}, 1311 Mr: nil, 1312 Str: nil, 1313 }, 1314 } 1315 1316 got, err := MarshalIndent(&o, "", " ", WithEncOptsTruncate(2)) 1317 if err != nil { 1318 t.Fatal(err) 1319 } 1320 if got := string(got); got != truncateExpected { 1321 t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected) 1322 } 1323 }