github.com/wI2L/jettison@v0.7.4/json_test.go (about) 1 package jettison 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/rand" 7 "encoding/json" 8 "errors" 9 "fmt" 10 "math" 11 "math/big" 12 "net" 13 "reflect" 14 "regexp" 15 "strconv" 16 "sync" 17 "testing" 18 "time" 19 ) 20 21 type ( 22 jmr string 23 jmv []string 24 ) 25 26 func (*jmr) MarshalJSON() ([]byte, error) { return []byte(`"XYZ"`), nil } 27 func (jmv) MarshalJSON() ([]byte, error) { return []byte(`"ZYX"`), nil } 28 29 type ( 30 mapss struct { 31 M map[string]string 32 } 33 inner struct { 34 M map[string]string 35 } 36 outer struct { 37 M map[string]inner 38 } 39 z struct { 40 S []byte 41 } 42 y struct { 43 P float64 `json:"p,omitempty"` 44 Q uint64 `json:"q,omitempty"` 45 R uint8 46 } 47 x struct { 48 A *string `json:"a,string"` 49 B1 int64 `json:"b1,string"` 50 B2 uint16 `json:"b2"` 51 C *bool `json:"c,string"` 52 D float32 53 E1 *[]int 54 E2 []string 55 E3 []jmr 56 F1 [4]string 57 F2 [1]jmr 58 F3 *[1]jmr 59 G1 map[int]*string 60 G2 map[string]*map[string]string 61 G3 map[int]map[string]map[int]string 62 G4 map[string]mapss 63 G5 outer 64 G6 map[int]jmr 65 G7 map[int]*jmr 66 G8 map[int]bool `json:",omitempty"` 67 H1 jmr 68 H2 *jmr 69 H3 jmv 70 H4 *jmv 71 I time.Time 72 J time.Duration 73 K json.Number 74 L json.RawMessage 75 M1 interface{} 76 M2 interface{} 77 N struct{} 78 X *x 79 *y 80 z `json:"z"` 81 } 82 ) 83 84 var ( 85 s = "Loreum" 86 b = true 87 m = map[string]string{"b": "c"} 88 xx = x{ 89 A: &s, 90 B1: -42, 91 B2: 42, 92 C: &b, 93 D: math.MaxFloat32, 94 E1: &[]int{1, 2, 3}, 95 E2: []string{"x", "y", "z"}, 96 E3: []jmr{"1"}, 97 F1: [4]string{"a", "b", "c", "d"}, 98 F2: [1]jmr{"1"}, 99 F3: &[1]jmr{"1"}, 100 G1: map[int]*string{2: &s, 3: new(string)}, 101 G2: map[string]*map[string]string{"a": &m}, 102 G3: map[int]map[string]map[int]string{1: {"a": {2: "b"}}}, 103 G4: map[string]mapss{"1": {M: map[string]string{"2": "3"}}}, 104 G5: outer{map[string]inner{"outer": {map[string]string{"key": "val"}}}}, 105 G6: map[int]jmr{1: "jmr"}, 106 G7: map[int]*jmr{1: new(jmr)}, 107 G8: map[int]bool{}, 108 H1: "jmp", 109 H2: nil, 110 H3: nil, 111 H4: nil, 112 I: time.Now(), 113 J: 3 * time.Minute, 114 K: "3.14", 115 L: []byte(`{ "a":"b" }`), 116 M1: uint32(255), 117 M2: &s, 118 X: &x{H1: "jmv"}, 119 y: &y{R: math.MaxUint8}, 120 z: z{S: []byte("Loreum")}, 121 } 122 ) 123 124 // marshalCompare compares the JSON encoding 125 // of v between Jettison and encoding/json. 126 func marshalCompare(t *testing.T, v interface{}, name string) { 127 jb1, err := Marshal(v) 128 if err != nil { 129 t.Fatal(err) 130 } 131 jb2, err := MarshalOpts(v) 132 if err != nil { 133 t.Fatal(err) 134 } 135 if !bytes.Equal(jb1, jb2) { 136 t.Error("non-equal outputs for Marshal and MarshalOpts") 137 } 138 jb3, err := Append([]byte(nil), v) 139 if err != nil { 140 t.Fatal(err) 141 } 142 if !bytes.Equal(jb1, jb3) { 143 t.Error("non-equal outputs for Marshal and Append") 144 } 145 sb, err := json.Marshal(v) 146 if err != nil { 147 t.Fatal(err) 148 } 149 t.Logf("standard: %s", string(sb)) 150 t.Logf("jettison: %s", string(jb1)) 151 152 if !bytes.Equal(jb1, sb) { 153 t.Errorf("%s: non-equal outputs", name) 154 } 155 } 156 157 func marshalCompareError(t *testing.T, v interface{}, name string) { 158 _, errj := Marshal(v) 159 if errj == nil { 160 t.Fatalf("expected non-nil error") 161 } 162 _, errs := json.Marshal(v) 163 if errs == nil { 164 t.Fatalf("expected non-nil error") 165 } 166 t.Logf("standard: %s", errs) 167 t.Logf("jettison: %s", errj) 168 169 if errs.Error() != errj.Error() { 170 t.Errorf("%s: non-equal outputs", name) 171 } 172 } 173 174 func TestAll(t *testing.T) { 175 marshalCompare(t, nil, "nil") 176 marshalCompare(t, xx, "non-pointer") 177 marshalCompare(t, &xx, "pointer") 178 } 179 180 func TestInvalidEncodeOpts(t *testing.T) { 181 for _, opt := range []Option{ 182 TimeLayout(""), 183 DurationFormat(DurationFmt(-1)), 184 DurationFormat(DurationFmt(6)), 185 WithContext(nil), // nolint:staticcheck 186 } { 187 _, err1 := MarshalOpts(struct{}{}, opt) 188 _, err2 := AppendOpts([]byte(nil), struct{}{}, opt) 189 190 for _, err := range []error{err1, err2} { 191 if err != nil { 192 e, ok := err.(*InvalidOptionError) 193 if !ok { 194 t.Errorf("got %T, want InvalidOptionError", err) 195 } 196 if e.Error() == "" { 197 t.Errorf("expected non-empty error message") 198 } 199 } else { 200 t.Error("expected non-nil error") 201 } 202 } 203 } 204 } 205 206 // TestBasicTypes tests the marshaling of basic types. 207 func TestBasicTypes(t *testing.T) { 208 testdata := []interface{}{ 209 true, 210 false, 211 "Loreum", 212 int8(math.MaxInt8), 213 int16(math.MaxInt16), 214 int32(math.MaxInt32), 215 int64(math.MaxInt64), 216 uint8(math.MaxUint8), 217 uint16(math.MaxUint16), 218 uint32(math.MaxUint32), 219 uint64(math.MaxUint64), 220 uintptr(0xBEEF), 221 (*bool)(nil), 222 (*int)(nil), 223 (*string)(nil), 224 } 225 for _, v := range testdata { 226 marshalCompare(t, v, "") 227 } 228 } 229 230 // TestCompositeTypes tests the marshaling of composite types. 231 func TestCompositeTypes(t *testing.T) { 232 var ( 233 jmref = jmr("jmr") 234 jmval = jmv([]string{"a", "b", "c"}) 235 ) 236 testdata := []interface{}{ 237 []uint{}, 238 []int{1, 2, 3}, 239 []int(nil), 240 (*[]int)(nil), 241 []string{"a", "b", "c"}, 242 [2]bool{true, false}, 243 (*[4]string)(nil), 244 map[string]int{"a": 1, "b": 2}, 245 &map[int]string{1: "a", 2: "b"}, 246 (map[string]int)(nil), 247 time.Now(), 248 3*time.Minute + 35*time.Second, 249 jmref, 250 &jmref, 251 jmval, 252 &jmval, 253 } 254 for _, v := range testdata { 255 marshalCompare(t, v, "") 256 } 257 } 258 259 // TestUnsupportedTypes tests that marshaling an 260 // unsupported type such as channel, complex, and 261 // function value returns an UnsupportedTypeError. 262 // The error message is compared with the one that 263 // is returned by json.Marshal. 264 func TestUnsupportedTypes(t *testing.T) { 265 testdata := []interface{}{ 266 make(chan int), 267 func() {}, 268 complex64(0), 269 complex128(0), 270 make([]chan int, 1), 271 [1]complex64{}, 272 &[1]complex128{}, 273 map[int]chan bool{1: make(chan bool)}, 274 struct{ F func() }{func() {}}, 275 &struct{ C complex64 }{0}, 276 } 277 for _, v := range testdata { 278 marshalCompareError(t, v, "") 279 } 280 } 281 282 // TestInvalidFloatValues tests that encoding an 283 // invalid float value returns UnsupportedValueError. 284 func TestInvalidFloatValues(t *testing.T) { 285 for _, v := range []float64{ 286 math.NaN(), 287 math.Inf(-1), 288 math.Inf(1), 289 } { 290 _, err := Marshal(v) 291 if err != nil { 292 if _, ok := err.(*UnsupportedValueError); !ok { 293 t.Errorf("got %T, want UnsupportedValueError", err) 294 } 295 } else { 296 t.Error("got nil, want non-nil error") 297 } 298 // Error message must be the same as 299 // the one of the standard library. 300 marshalCompareError(t, v, "") 301 } 302 } 303 304 // TestJSONNumber tests that a json.Number literal value 305 // can be marshaled, and that an error is returned if it 306 // isn't a valid number according to the JSON grammar. 307 func TestJSONNumber(t *testing.T) { 308 valid := []json.Number{ 309 "42", 310 "-42", 311 "24.42", 312 "-666.66", 313 "3.14", 314 "-3.14", 315 "1e3", 316 "1E-6", 317 "1E+42", 318 // Special case to keep backward 319 // compatibility with Go1.5, that 320 // encodes the empty string as "0". 321 "", 322 } 323 for _, v := range valid { 324 marshalCompare(t, v, "valid") 325 } 326 invalid := []json.Number{ 327 "1E+4.0", 328 "084", 329 "-03.14", 330 "-", 331 "invalid", 332 } 333 for _, v := range invalid { 334 marshalCompareError(t, v, "invalid") 335 } 336 } 337 338 func TestInvalidTime(t *testing.T) { 339 // Special case to test error when the year 340 // of the date is outside of range [0.9999]. 341 // see golang.org/issue/4556#c15. 342 for _, tm := range []time.Time{ 343 time.Date(-1, time.January, 1, 0, 0, 0, 0, time.UTC), 344 time.Date(10000, time.January, 1, 0, 0, 0, 0, time.UTC), 345 } { 346 _, err := Marshal(tm) 347 if err != nil { 348 want := "time: year outside of range [0,9999]" 349 if err.Error() != want { 350 t.Errorf("got %q, want %q", err.Error(), want) 351 } 352 } else { 353 t.Error("got nil, want non-nil error") 354 } 355 } 356 } 357 358 // TestRenamedByteSlice tests that a name type 359 // that represents a slice of bytes is marshaled 360 // the same way as a regular byte slice. 361 func TestRenamedByteSlice(t *testing.T) { 362 type ( 363 b byte 364 b1 []byte 365 b2 []b 366 ) 367 testdata := []interface{}{ 368 b1("byte slice 1"), 369 b2("byte slice 2"), 370 } 371 for _, v := range testdata { 372 marshalCompare(t, v, "") 373 } 374 } 375 376 func TestByteSliceSizes(t *testing.T) { 377 makeSlice := func(size int) []byte { 378 b := make([]byte, size) 379 if _, err := rand.Read(b); err != nil { 380 t.Fatal(err) 381 } 382 return b 383 } 384 for _, v := range []interface{}{ 385 makeSlice(0), 386 makeSlice(1024), 387 makeSlice(2048), 388 makeSlice(4096), 389 makeSlice(8192), 390 } { 391 marshalCompare(t, v, "") 392 } 393 } 394 395 // TestSortedSyncMap tests the marshaling 396 // of a sorted sync.Map value. 397 func TestSortedSyncMap(t *testing.T) { 398 var sm sync.Map 399 400 sm.Store(1, "one") 401 sm.Store("a", 42) 402 sm.Store("b", false) 403 sm.Store(mkvstrMarshaler("c"), -42) 404 sm.Store(mkrstrMarshaler("d"), true) 405 sm.Store(mkvintMarshaler(42), 1) 406 sm.Store(mkrintMarshaler(42), 2) 407 408 b, err := Marshal(&sm) 409 if err != nil { 410 t.Fatal(err) 411 } 412 want := `{"1":"one","42":2,"MKVINT":1,"a":42,"b":false,"c":-42,"d":true}` 413 414 if !bytes.Equal(b, []byte(want)) { 415 t.Errorf("got %#q, want %#q", b, want) 416 } 417 } 418 419 // TestUnsortedSyncMap tests the marshaling 420 // of an unsorted sync.Map value. 421 func TestUnsortedSyncMap(t *testing.T) { 422 // entries maps each interface k/v 423 // pair to the string representation 424 // of the key in payload. 425 entries := map[string]struct { 426 key interface{} 427 val interface{} 428 }{ 429 "1": {1, "one"}, 430 "a": {"a", 42}, 431 "b": {"b", false}, 432 "c": {mkvstrMarshaler("c"), -42}, 433 "d": {mkrstrMarshaler("d"), true}, 434 "MKVINT": {mkvintMarshaler(42), 1}, 435 "42": {mkrintMarshaler(42), 2}, 436 } 437 var sm sync.Map 438 for _, e := range entries { 439 sm.Store(e.key, e.val) 440 } 441 bts, err := MarshalOpts(&sm, UnsortedMap()) 442 if err != nil { 443 t.Fatal(err) 444 } 445 m := make(map[string]interface{}) 446 if err := json.Unmarshal(bts, &m); err != nil { 447 t.Fatal(err) 448 } 449 // Unmarshaled map must contains exactly the 450 // number of entries added to the sync map. 451 if g, w := len(m), len(entries); g != w { 452 t.Errorf("invalid lengths: got %d, want %d", g, w) 453 } 454 for k, v := range m { 455 // Compare the marshaled representation 456 // of each value to avoid false-positive 457 // between integer and float types. 458 b1, err1 := json.Marshal(v) 459 b2, err2 := json.Marshal(entries[k].val) 460 if err1 != nil { 461 t.Fatal(err) 462 } 463 if err2 != nil { 464 t.Fatal(err2) 465 } 466 if !bytes.Equal(b1, b2) { 467 t.Errorf("for key %s: got %v, want %v", k, b1, b2) 468 } 469 } 470 } 471 472 // TestInvalidSyncMapKeys tests that marshaling a 473 // sync.Map with unsupported key types returns an 474 // error. 475 func TestInvalidSyncMapKeys(t *testing.T) { 476 testInvalidSyncMapKeys(t, true) 477 testInvalidSyncMapKeys(t, false) 478 } 479 480 func testInvalidSyncMapKeys(t *testing.T, sorted bool) { 481 for _, f := range []func(sm *sync.Map){ 482 func(sm *sync.Map) { sm.Store(false, nil) }, 483 func(sm *sync.Map) { sm.Store(new(int), nil) }, 484 func(sm *sync.Map) { sm.Store(nil, nil) }, 485 } { 486 var ( 487 sm sync.Map 488 err error 489 ) 490 f(&sm) // add entries to sm 491 if sorted { 492 _, err = Marshal(&sm) 493 } else { 494 _, err = MarshalOpts(&sm, UnsortedMap()) 495 } 496 if err == nil { 497 t.Error("expected a non-nil error") 498 } 499 } 500 } 501 502 // TestCompositeMapValue tests the marshaling 503 // of maps with composite values. 504 func TestCompositeMapValue(t *testing.T) { 505 type x struct { 506 A string `json:"a"` 507 B int `json:"b"` 508 C bool `json:"c"` 509 } 510 type y []uint32 511 512 for _, v := range []interface{}{ 513 map[string]x{ 514 "1": {A: "A", B: 42, C: true}, 515 "2": {A: "A", B: 84, C: false}, 516 }, 517 map[string]y{ 518 "3": {7, 8, 9}, 519 "2": {4, 5, 6}, 520 "1": nil, 521 }, 522 map[string]*x{ 523 "b": {A: "A", B: 128, C: true}, 524 "a": nil, 525 "c": {}, 526 }, 527 map[string]interface{}{ 528 "1": 42, 529 "2": "two", 530 "3": nil, 531 "4": (*int64)(nil), 532 "5": x{A: "A"}, 533 "6": &x{A: "A", B: 256, C: true}, 534 }, 535 } { 536 marshalCompare(t, v, "") 537 } 538 } 539 540 type ( 541 mkstr string 542 mkint int64 543 mkvstrMarshaler string 544 mkrstrMarshaler string 545 mkvintMarshaler uint64 546 mkrintMarshaler int 547 mkvcmpMarshaler struct{} 548 ) 549 550 func (mkvstrMarshaler) MarshalText() ([]byte, error) { return []byte("MKVSTR"), nil } 551 func (*mkrstrMarshaler) MarshalText() ([]byte, error) { return []byte("MKRSTR"), nil } 552 func (mkvintMarshaler) MarshalText() ([]byte, error) { return []byte("MKVINT"), nil } 553 func (*mkrintMarshaler) MarshalText() ([]byte, error) { return []byte("MKRINT"), nil } 554 func (mkvcmpMarshaler) MarshalText() ([]byte, error) { return []byte("MKVCMP"), nil } 555 556 // TestMapKeyPrecedence tests that the precedence 557 // order of map key types is respected during marshaling. 558 func TestMapKeyPrecedence(t *testing.T) { 559 testdata := []interface{}{ 560 map[mkstr]string{"K": "V"}, 561 map[mkint]string{1: "V"}, 562 map[mkvstrMarshaler]string{"K": "V"}, 563 map[mkrstrMarshaler]string{"K": "V"}, 564 map[mkvintMarshaler]string{42: "V"}, 565 map[mkrintMarshaler]string{1: "one"}, 566 map[mkvcmpMarshaler]string{{}: "V"}, 567 } 568 for _, v := range testdata { 569 marshalCompare(t, v, "") 570 } 571 } 572 573 // TestJSONMarshaler tests that a type implementing the 574 // json.Marshaler interface is marshaled using the result 575 // of its MarshalJSON method call result. 576 // Because the types big.Int and time.Time also implements 577 // the encoding.TextMarshaler interface, the test ensures 578 // that MarshalJSON has priority. 579 func TestJSONMarshaler(t *testing.T) { 580 type x struct { 581 T1 time.Time `json:""` 582 T2 time.Time `json:",omitempty"` 583 T3 *time.Time `json:""` 584 T4 *time.Time `json:""` // nil 585 T5 *time.Time `json:",omitempty"` // nil 586 S1 bvjm `json:",omitempty"` 587 S2 bvjm `json:",omitempty"` 588 S3 bvjm `json:""` 589 S4 *bvjm `json:""` 590 S5 *bvjm `json:""` // nil 591 S6 *bvjm `json:",omitempty"` // nil 592 I1 big.Int `json:""` 593 I2 big.Int `json:",omitempty"` 594 I3 *big.Int `json:""` 595 I4 *big.Int `json:""` // nil 596 I5 *big.Int `json:",omitempty"` // nil 597 P1 brjm `json:",omitempty"` 598 P2 brjm `json:",omitempty"` 599 P3 brjm `json:""` 600 P4 *brjm `json:""` 601 P5 *brjm `json:""` // nil 602 P6 *brjm `json:",omitempty"` // nil 603 604 // NOTE 605 // time.Time = Non-pointer receiver of composite type. 606 // bvjm = Non-pointer receiver of basic type. 607 // big.Int = Pointer receiver of composite type. 608 // brjm = Pointer receiver of basic type. 609 } 610 var ( 611 now = time.Now() 612 bval = bvjm("bval") 613 bref = brjm("bref") 614 xx = x{ 615 T1: now, 616 T3: &now, 617 S1: "S1", 618 S4: &bval, 619 I1: *big.NewInt(math.MaxInt64), 620 I3: big.NewInt(math.MaxInt64), 621 P1: "P1", 622 P4: &bref, 623 } 624 ) 625 marshalCompare(t, xx, "non-pointer") 626 marshalCompare(t, &xx, "pointer") 627 } 628 629 // TestTextMarshaler tests that a type implementing 630 // the encoding.TextMarshaler interface encodes to a 631 // quoted string of its MashalText method result. 632 func TestTextMarshaler(t *testing.T) { 633 type x struct { 634 S1 net.IP `json:""` 635 S2 net.IP `json:",omitempty"` 636 S3 *net.IP `json:""` 637 S4 *net.IP `json:""` // nil 638 S5 *net.IP `json:",omitempty"` // nil 639 I1 bvtm `json:",omitempty"` 640 I2 bvtm `json:",omitempty"` 641 I3 bvtm `json:""` 642 I4 *bvtm `json:""` 643 I5 *bvtm `json:""` // nil 644 I6 *bvtm `json:",omitempty"` // nil 645 F1 big.Float `json:""` 646 F2 big.Float `json:",omitempty"` 647 F3 *big.Float `json:""` 648 F4 *big.Float `json:""` // nil 649 F5 *big.Float `json:",omitempty"` // nil 650 P1 brtm `json:",omitempty"` 651 P2 brtm `json:",omitempty"` 652 P3 brtm `json:""` 653 P4 *brtm `json:""` 654 P5 *brtm `json:""` // nil 655 P6 *brtm `json:",omitempty"` // nil 656 657 // NOTE 658 // net.IP = Non-pointer receiver of composite type. 659 // bvtm = Non-pointer receiver of basic type. 660 // big.Float = Pointer receiver of composite type. 661 // brtm = Pointer receiver of basic type. 662 } 663 var ( 664 bval = bvtm(42) 665 bref = brtm(42) 666 xx = x{ 667 S1: net.IP{192, 168, 0, 1}, 668 S3: &net.IP{127, 0, 0, 1}, 669 I1: 42, 670 I4: &bval, 671 F1: *big.NewFloat(math.MaxFloat64), 672 F3: big.NewFloat(math.MaxFloat64), 673 P1: 42, 674 P4: &bref, 675 } 676 ) 677 marshalCompare(t, xx, "non-pointer") 678 marshalCompare(t, &xx, "pointer") 679 } 680 681 type ( 682 bvm string 683 brm string 684 cvm struct{} 685 crm struct{} 686 ) 687 688 func (m bvm) AppendJSON(dst []byte) ([]byte, error) { 689 return append(dst, strconv.Quote(string(m))...), nil 690 } 691 func (m *brm) AppendJSON(dst []byte) ([]byte, error) { 692 return append(dst, strconv.Quote(string(*m))...), nil 693 } 694 func (m bvm) MarshalJSON() ([]byte, error) { return []byte(strconv.Quote(string(m))), nil } 695 func (m *brm) MarshalJSON() ([]byte, error) { return []byte(strconv.Quote(string(*m))), nil } 696 func (cvm) AppendJSON(dst []byte) ([]byte, error) { return append(dst, `"X"`...), nil } 697 func (cvm) MarshalJSON() ([]byte, error) { return []byte(`"X"`), nil } 698 func (*crm) AppendJSON(dst []byte) ([]byte, error) { return append(dst, `"Y"`...), nil } 699 func (*crm) MarshalJSON() ([]byte, error) { return []byte(`"Y"`), nil } 700 701 //nolint:dupl 702 func TestMarshaler(t *testing.T) { 703 type x struct { 704 S1 cvm `json:""` 705 S2 cvm `json:",omitempty"` 706 S3 *cvm `json:""` 707 S4 *cvm `json:""` // nil 708 S5 *cvm `json:",omitempty"` // nil 709 I1 bvm `json:",omitempty"` 710 I2 bvm `json:",omitempty"` 711 I3 bvm `json:""` 712 I4 *bvm `json:""` 713 I5 *bvm `json:""` // nil 714 I6 *bvm `json:",omitempty"` // nil 715 F1 crm `json:""` 716 F2 crm `json:",omitempty"` 717 F3 *crm `json:""` 718 F4 *crm `json:""` // nil 719 F5 *crm `json:",omitempty"` // nil 720 P1 brm `json:",omitempty"` 721 P2 brm `json:",omitempty"` 722 P3 brm `json:""` 723 P4 *brm `json:""` 724 P5 *brm `json:""` // nil 725 P6 *brm `json:",omitempty"` // nil 726 727 // NOTE 728 // cvm = Non-pointer receiver of composite type. 729 // bvm = Non-pointer receiver of basic type. 730 // crm = Pointer receiver of composite type. 731 // brm = Pointer receiver of basic type. 732 } 733 var ( 734 bval = bvm("bval") 735 bref = brm("bref") 736 xx = x{ 737 S1: cvm{}, 738 S3: &cvm{}, 739 I1: "I1", 740 I4: &bval, 741 F1: crm{}, 742 F3: &crm{}, 743 P1: "P1", 744 P4: &bref, 745 } 746 ) 747 marshalCompare(t, xx, "non-pointer") 748 marshalCompare(t, &xx, "pointer") 749 } 750 751 type ( 752 bvmctx string 753 brmctx string 754 cvmctx struct{} 755 crmctx struct{} 756 ) 757 758 func (m bvmctx) AppendJSONContext(_ context.Context, dst []byte) ([]byte, error) { 759 return append(dst, strconv.Quote(string(m))...), nil 760 } 761 func (m bvmctx) MarshalJSON() ([]byte, error) { 762 return []byte(strconv.Quote(string(m))), nil 763 } 764 func (m *brmctx) AppendJSONContext(_ context.Context, dst []byte) ([]byte, error) { 765 return append(dst, strconv.Quote(string(*m))...), nil 766 } 767 func (m *brmctx) MarshalJSON() ([]byte, error) { 768 return []byte(strconv.Quote(string(*m))), nil 769 } 770 func (cvmctx) AppendJSONContext(_ context.Context, dst []byte) ([]byte, error) { 771 return append(dst, `"X"`...), nil 772 } 773 func (cvmctx) MarshalJSON() ([]byte, error) { 774 return []byte(`"X"`), nil 775 } 776 func (*crmctx) AppendJSONContext(_ context.Context, dst []byte) ([]byte, error) { 777 return append(dst, `"Y"`...), nil 778 } 779 func (*crmctx) MarshalJSON() ([]byte, error) { 780 return []byte(`"Y"`), nil 781 } 782 783 //nolint:dupl 784 func TestMarshalerCtx(t *testing.T) { 785 type x struct { 786 S1 cvmctx `json:""` 787 S2 cvmctx `json:",omitempty"` 788 S3 *cvmctx `json:""` 789 S4 *cvmctx `json:""` // nil 790 S5 *cvmctx `json:",omitempty"` // nil 791 I1 bvmctx `json:",omitempty"` 792 I2 bvmctx `json:",omitempty"` 793 I3 bvmctx `json:""` 794 I4 *bvmctx `json:""` 795 I5 *bvmctx `json:""` // nil 796 I6 *bvmctx `json:",omitempty"` // nil 797 F1 crmctx `json:""` 798 F2 crmctx `json:",omitempty"` 799 F3 *crmctx `json:""` 800 F4 *crmctx `json:""` // nil 801 F5 *crmctx `json:",omitempty"` // nil 802 P1 brmctx `json:",omitempty"` 803 P2 brmctx `json:",omitempty"` 804 P3 brmctx `json:""` 805 P4 *brmctx `json:""` 806 P5 *brmctx `json:""` // nil 807 P6 *brmctx `json:",omitempty"` // nil 808 809 // NOTE 810 // cvmctx = Non-pointer receiver of composite type. 811 // bvmctx = Non-pointer receiver of basic type. 812 // crmctx = Pointer receiver of composite type. 813 // brmctx = Pointer receiver of basic type. 814 } 815 var ( 816 bval = bvmctx("bval") 817 bref = brmctx("bref") 818 xx = x{ 819 S1: cvmctx{}, 820 S3: &cvmctx{}, 821 I1: "I1", 822 I4: &bval, 823 F1: crmctx{}, 824 F3: &crmctx{}, 825 P1: "P1", 826 P4: &bref, 827 } 828 ) 829 marshalCompare(t, xx, "non-pointer") 830 marshalCompare(t, &xx, "pointer") 831 } 832 833 type ( 834 niljetim string // jettison.Marshaler 835 nilmjctx string // jettison.MarshalerCtx 836 niljsonm string // json.Marshaler 837 niltextm string // encoding.TextMarshaler 838 ) 839 840 // comboMarshaler combines the json.Marshaler 841 // and jettison.AppendMarshaler interfaces so 842 // that tests outputs can be compared. 843 type comboMarshaler interface { 844 AppendMarshaler 845 json.Marshaler 846 } 847 848 // comboMarshalerCtx combines the json.Marshaler 849 // and jettison.AppendMarshalerCtx interfaces so 850 // that tests outputs can be compared. 851 type comboMarshalerCtx interface { 852 AppendMarshalerCtx 853 json.Marshaler 854 } 855 856 func (*niljetim) MarshalJSON() ([]byte, error) { return []byte(`"W"`), nil } 857 func (*nilmjctx) MarshalJSON() ([]byte, error) { return []byte(`"X"`), nil } 858 func (*niljsonm) MarshalJSON() ([]byte, error) { return []byte(`"Y"`), nil } 859 func (*niltextm) MarshalText() ([]byte, error) { return []byte("Z"), nil } 860 861 func (*niljetim) AppendJSON(dst []byte) ([]byte, error) { 862 return append(dst, `"W"`...), nil 863 } 864 func (*nilmjctx) AppendJSONContext(_ context.Context, dst []byte) ([]byte, error) { 865 return append(dst, `"X"`...), nil 866 } 867 868 type ( 869 errvjm struct{} 870 errrjm struct{} 871 errvtm struct{} 872 errrtm struct{} 873 errvm struct{} 874 errrm struct{} 875 errvmctx struct{} 876 errrmctx struct{} 877 ) 878 879 var errMarshaler = errors.New("error") 880 881 func (errvjm) MarshalJSON() ([]byte, error) { return nil, errMarshaler } 882 func (*errrjm) MarshalJSON() ([]byte, error) { return nil, errMarshaler } 883 func (errvtm) MarshalText() ([]byte, error) { return nil, errMarshaler } 884 func (*errrtm) MarshalText() ([]byte, error) { return nil, errMarshaler } 885 func (errvm) AppendJSON(dst []byte) ([]byte, error) { return dst, errMarshaler } 886 func (*errrm) AppendJSON(dst []byte) ([]byte, error) { return dst, errMarshaler } 887 888 func (errvmctx) AppendJSONContext(_ context.Context, dst []byte) ([]byte, error) { 889 return dst, errMarshaler 890 } 891 func (*errrmctx) AppendJSONContext(_ context.Context, dst []byte) ([]byte, error) { 892 return dst, errMarshaler 893 } 894 895 // TestMarshalerError tests that a MarshalerError is 896 // returned when a MarshalText, MarshalJSON, WriteJSON 897 // or WriteJSONContext method returns an error. 898 func TestMarshalerError(t *testing.T) { 899 testdata := []interface{}{ 900 errvjm{}, 901 &errrjm{}, 902 errvtm{}, 903 &errrtm{}, 904 errvm{}, 905 &errrm{}, 906 errvmctx{}, 907 &errrmctx{}, 908 } 909 for _, v := range testdata { 910 _, err := Marshal(v) 911 if err != nil { 912 me, ok := err.(*MarshalerError) 913 if !ok { 914 t.Fatalf("got %T, want MarshalerError", err) 915 } 916 typ := reflect.TypeOf(v) 917 if me.Type != typ { 918 t.Errorf("got %s, want %s", me.Type, typ) 919 } 920 if err := me.Unwrap(); err == nil { 921 t.Error("expected non-nil error") 922 } 923 if me.Error() == "" { 924 t.Error("expected non-empty error message") 925 } 926 } else { 927 t.Error("got nil, want non-nil error") 928 } 929 } 930 } 931 932 // TestStructFieldName tests that invalid struct 933 // field names are ignored during marshaling. 934 func TestStructFieldName(t *testing.T) { 935 //nolint:staticcheck 936 type x struct { 937 A string `json:" "` // valid, spaces 938 B string `json:"0123"` // valid, digits 939 C int `json:","` // invalid, comma 940 D int8 `json:"\\"` // invalid, backslash, 941 E int16 `json:"\""` // invalid, quotation mark 942 F int `json:"Вилиам"` // valid, UTF-8 runes 943 G bool `json:"<ben&jerry>"` // valid, HTML-escaped chars 944 Aβ int 945 } 946 marshalCompare(t, x{}, "") 947 } 948 949 // TestStructFieldOmitempty tests that the fields of 950 // a struct with the omitempty option are not encoded 951 // when they have the zero-value of their type. 952 func TestStructFieldOmitempty(t *testing.T) { 953 type x struct { 954 A string `json:",omitempty"` 955 B string `json:",omitempty"` 956 C *string `json:",omitempty"` 957 Ca *string `json:"a,omitempty"` 958 D *string `json:",omitempty"` 959 E bool `json:",omitempty"` 960 F int `json:",omitempty"` 961 F1 int8 `json:",omitempty"` 962 F2 int16 `json:",omitempty"` 963 F3 int32 `json:",omitempty"` 964 F4 int64 `json:",omitempty"` 965 G1 uint `json:",omitempty"` 966 G2 uint8 `json:",omitempty"` 967 G3 uint16 `json:",omitempty"` 968 G4 uint32 `json:",omitempty"` 969 G5 uint64 `json:",omitempty"` 970 G6 uintptr `json:",omitempty"` 971 H float32 `json:",omitempty"` 972 I float64 `json:",omitempty"` 973 J1 map[int]int `json:",omitempty"` 974 J2 map[int]int `json:",omitempty"` 975 J3 map[int]int `json:",omitempty"` 976 K1 []string `json:",omitempty"` 977 K2 []string `json:",omitempty"` 978 L1 [0]int `json:",omitempty"` 979 L2 [2]int `json:",omitempty"` 980 M1 interface{} `json:",omitempty"` 981 M2 interface{} `json:",omitempty"` 982 } 983 var ( 984 s1 = "Loreum" 985 s2 = "" 986 xx = &x{ 987 A: "A", 988 B: "", 989 C: &s1, 990 Ca: &s2, 991 D: nil, 992 J2: map[int]int{}, 993 J3: map[int]int{1: 42}, 994 K2: []string{"K2"}, 995 M2: (*int)(nil), 996 } 997 ) 998 marshalCompare(t, xx, "") 999 } 1000 1001 // TestStructFieldOmitnil tests that the fields of a 1002 // struct with the omitnil option are not encoded 1003 // when they have a nil value. 1004 func TestStructFieldOmitnil(t *testing.T) { 1005 // nolint:staticcheck 1006 type x struct { 1007 Sn string `json:"sn,omitnil"` 1008 In int `json:"in,omitnil"` 1009 Un uint `json:"un,omitnil"` 1010 Fn float64 `json:"fn,omitnil"` 1011 Bn bool `json:"bn,omitnil"` 1012 Sln []string `json:"sln,omitnil"` 1013 Mpn map[string]interface{} `json:"mpn,omitnil"` 1014 Stn struct{} `json:"stn,omitnil"` 1015 Ptn *string `json:"ptn,omitnil"` 1016 Ifn interface{} `json:"ifn,omitnil"` 1017 } 1018 var ( 1019 xx = x{} 1020 before = `{"sn":"","in":0,"un":0,"fn":0,"bn":false,"stn":{}}` 1021 after = `{"sn":"","in":0,"un":0,"fn":0,"bn":false,"sln":[],"mpn":{},"stn":{},"ptn":"Loreum","ifn":42}` 1022 ) 1023 b, err := Marshal(xx) 1024 if err != nil { 1025 t.Fatal(err) 1026 } 1027 if got := string(b); got != before { 1028 t.Errorf("before: got: %#q, want: %#q", got, before) 1029 } 1030 s := "Loreum" 1031 1032 xx.Sln = make([]string, 0) 1033 xx.Mpn = map[string]interface{}{} 1034 xx.Stn = struct{}{} 1035 xx.Ptn = &s 1036 xx.Ifn = 42 1037 1038 b, err = Marshal(xx) 1039 if err != nil { 1040 t.Fatal(err) 1041 } 1042 if got := string(b); got != after { 1043 t.Errorf("after: got: %#q, want: %#q", got, after) 1044 } 1045 } 1046 1047 // TestQuotedStructFields tests that the fields of 1048 // a struct with the string option are quoted during 1049 // marshaling if the type support it. 1050 //nolint:staticcheck 1051 func TestQuotedStructFields(t *testing.T) { 1052 type x struct { 1053 A1 int `json:",string"` 1054 A2 *int `json:",string"` 1055 A3 *int `json:",string"` 1056 B uint `json:",string"` 1057 C1 bool `json:",string"` 1058 C2 *bool `json:",string"` 1059 D float32 `json:",string"` 1060 E string `json:",string"` 1061 F []int `json:",string"` 1062 G map[int]int `json:",string"` 1063 } 1064 var ( 1065 i = 84 1066 b = false 1067 xx = &x{ 1068 A1: -42, 1069 A2: nil, 1070 A3: &i, 1071 B: 42, 1072 C1: true, 1073 C2: &b, 1074 D: math.Pi, 1075 E: "E", 1076 F: []int{1, 2, 3}, 1077 G: map[int]int{1: 2}, 1078 } 1079 ) 1080 marshalCompare(t, xx, "") 1081 } 1082 1083 // TestBasicStructFieldTypes tests that struct 1084 // fields of basic types can be marshaled. 1085 func TestBasicStructFieldTypes(t *testing.T) { 1086 type x struct { 1087 A string `json:"a"` 1088 B1 int `json:"b1"` 1089 B2 int8 `json:"b2"` 1090 B3 int16 `json:"b3"` 1091 B4 int32 `json:"b4"` 1092 B5 int64 `json:"b5"` 1093 C1 uint `json:"c1"` 1094 C2 uint8 `json:"c2"` 1095 C3 uint16 `json:"c3"` 1096 C4 uint32 `json:"c4"` 1097 C5 uint64 `json:"c5"` 1098 D1 bool `json:"d1"` 1099 D2 bool `json:"d2"` 1100 E float32 `json:"e"` 1101 F float64 `json:"f"` 1102 G string `json:"-"` // ignored 1103 H string `json:"-,"` // use "-" as key 1104 i string 1105 } 1106 xx := &x{ 1107 A: "A", 1108 B1: -42, 1109 B2: math.MinInt8, 1110 B3: math.MinInt16, 1111 B4: math.MinInt32, 1112 B5: math.MinInt64, 1113 C1: 42, 1114 C2: math.MaxUint8, 1115 C3: math.MaxUint16, 1116 C4: math.MaxUint32, 1117 C5: math.MaxUint64, 1118 D1: true, 1119 D2: false, 1120 E: 3.14169, 1121 F: math.MaxFloat64, 1122 G: "ignored", 1123 H: "not-ignored", 1124 i: "unexported", 1125 } 1126 marshalCompare(t, xx, "non-pointer") 1127 marshalCompare(t, &xx, "pointer") 1128 } 1129 1130 // TestBasicStructFieldPointerTypes tests 1131 // that nil and non-nil struct field pointers 1132 // of basic types can be marshaled. 1133 func TestBasicStructFieldPointerTypes(t *testing.T) { 1134 type x struct { 1135 A *string `json:"a"` 1136 B *int `json:"b"` 1137 C *uint64 `json:"c"` 1138 D *bool `json:"d"` 1139 E *float32 `json:"e"` 1140 F *float64 `json:"f"` 1141 } 1142 var ( 1143 a = "a" 1144 b = 42 1145 d = true 1146 f = math.MaxFloat64 1147 xx = x{A: &a, B: &b, C: nil, D: &d, E: nil, F: &f} 1148 ) 1149 marshalCompare(t, xx, "non-pointer") 1150 marshalCompare(t, &xx, "pointer") 1151 } 1152 1153 // TestCompositeStructFieldTypes tests that struct 1154 // fields of composite types, such as struct, slice, 1155 // array and map can be marshaled. 1156 func TestCompositeStructFieldTypes(t *testing.T) { 1157 type y struct { 1158 X string `json:"x"` 1159 } 1160 type x struct { 1161 A y `json:"a"` 1162 B1 *y 1163 B2 *y 1164 b3 *y 1165 c1 []string 1166 C2 []string 1167 D []int 1168 E []bool 1169 F []float32 1170 G []*uint 1171 H [3]string 1172 I [1]int 1173 J [0]bool 1174 K1 []byte 1175 K2 []byte 1176 L []*int 1177 M1 []y 1178 M2 *[]y 1179 N1 []*y 1180 N2 []*y 1181 O1 [3]*int 1182 O2 *[3]*bool 1183 P [3]*y 1184 Q [][]int 1185 R [2][2]string 1186 S1 map[int]string 1187 S2 map[int]string 1188 S3 map[int]string 1189 S4 map[string]interface{} 1190 T1 *map[string]int 1191 T2 *map[string]int 1192 T3 *map[string]int 1193 U1 interface{} 1194 U2 interface{} 1195 U3 interface{} 1196 U4 interface{} 1197 U5 interface{} 1198 U6 interface{} 1199 u7 interface{} 1200 } 1201 k := make([]byte, 32) 1202 if _, err := rand.Read(k); err != nil { 1203 t.Error(err) 1204 } 1205 var ( 1206 l1 = 0 1207 l2 = 42 1208 m1 = y{X: "X"} 1209 m2 = y{} 1210 i0 = 42 1211 i1 = &i0 1212 i2 = &i1 1213 i3 = &i2 1214 xx = x{ 1215 A: y{X: "X"}, 1216 B1: nil, 1217 B2: &y{X: "Ipsum"}, 1218 b3: nil, 1219 c1: nil, 1220 C2: []string{"one", "two", "three"}, 1221 D: []int{1, 2, 3}, 1222 E: []bool{}, 1223 H: [3]string{"alpha", "beta", "gamma"}, 1224 I: [1]int{42}, 1225 K1: k, 1226 K2: []byte(nil), 1227 L: []*int{&l1, &l2, nil}, 1228 M1: []y{m1, m2}, 1229 N1: []*y{&m1, &m2, nil}, 1230 N2: []*y{}, 1231 O1: [3]*int{&l1, &l2, nil}, 1232 P: [3]*y{&m1, &m2, nil}, 1233 Q: [][]int{{1, 2}, {3, 4}}, 1234 R: [2][2]string{{"a", "b"}, {"c", "d"}}, 1235 S1: nil, 1236 S3: map[int]string{1: "x", 2: "y", 3: "z"}, 1237 S4: map[string]interface{}{"a": 1, "b": "2"}, 1238 T3: &map[string]int{"x": 1, "y": 2, "z": 3}, 1239 U1: "U1", 1240 U2: &l2, 1241 U3: nil, 1242 U4: false, 1243 U5: (*int)(nil), // typed nil 1244 U6: i3, // chain of pointers 1245 u7: nil, 1246 } 1247 ) 1248 marshalCompare(t, xx, "non-pointer") 1249 marshalCompare(t, &xx, "pointer") 1250 } 1251 1252 // TestEmbeddedTypes tests that composite and basic 1253 // embedded struct fields types are encoded whether 1254 // they are exported. 1255 func TestEmbeddedTypes(t *testing.T) { 1256 type ( 1257 P1 int 1258 P2 string 1259 P3 bool 1260 p4 uint32 1261 C1 map[string]int 1262 C2 [3]string 1263 C3 []int 1264 c4 []bool 1265 ) 1266 type x struct { 1267 P1 1268 P2 1269 P3 1270 p4 1271 C1 1272 C2 1273 C3 1274 c4 `json:"c4"` 1275 } 1276 xx := &x{ 1277 P1: P1(42), 1278 P2: P2("P2"), 1279 P3: P3(true), 1280 p4: p4(math.MaxUint32), 1281 C1: C1{"A": 1, "B": 2}, 1282 C2: C2{"A", "B", "C"}, 1283 C3: C3{1, 2, 3}, 1284 c4: c4{true, false}, 1285 } 1286 marshalCompare(t, xx, "") 1287 } 1288 1289 // TestRecursiveType tests the marshaling of 1290 // recursive types. 1291 func TestRecursiveType(t *testing.T) { 1292 type x struct { 1293 A string `json:"a"` 1294 X *x `json:"x"` 1295 } 1296 xx := &x{ 1297 A: "A1", 1298 X: &x{A: "A2"}, 1299 } 1300 marshalCompare(t, xx, "") 1301 } 1302 1303 // TestTaggedFieldDominates tests that a struct 1304 // field with a tag dominates untagged fields. 1305 func TestTaggedFieldDominates(t *testing.T) { 1306 type ( 1307 A struct{ S string } 1308 D struct { 1309 XXX string `json:"S"` 1310 } 1311 Y struct { 1312 A 1313 D 1314 } 1315 ) 1316 y := Y{ 1317 A{"A"}, 1318 D{"D"}, 1319 } 1320 marshalCompare(t, y, "") 1321 } 1322 1323 // TestDuplicatedFieldDisappears tests that 1324 // duplicate struct field at the same level 1325 // of embedding are ignored. 1326 func TestDuplicatedFieldDisappears(t *testing.T) { 1327 type ( 1328 A struct{ S string } 1329 C struct{ S string } 1330 D struct { 1331 XXX string `json:"S"` 1332 } 1333 Y struct { 1334 A 1335 D 1336 } 1337 Z struct { 1338 A 1339 C 1340 Y 1341 } 1342 ) 1343 z := Z{A{"A"}, C{"C"}, Y{A{"S"}, D{"D"}}} 1344 1345 marshalCompare(t, z, "") 1346 } 1347 1348 // TestEmbeddedStructs tests that named and unnamed 1349 // embedded structs fields can be marshaled. 1350 func TestEmbeddedStructs(t *testing.T) { 1351 type ( 1352 r struct { 1353 J string `json:"j"` 1354 } 1355 v struct { 1356 H bool `json:"h,omitempty"` 1357 I string `json:"i"` 1358 } 1359 y struct { 1360 D int8 `json:"d"` 1361 E uint8 `json:"e,omitempty"` 1362 r 1363 v 1364 } 1365 z struct { 1366 F int16 `json:"f,omitempty"` 1367 G uint16 `json:"g"` 1368 y 1369 v 1370 } 1371 // According to the Go rules for embedded fields, 1372 // y.r.J should be encoded while z.y.r.J is not, 1373 // because is one-level up. 1374 // However, y.v.H and z.v.H are present at the same 1375 // level, and therefore are both hidden. 1376 x1 struct { 1377 A string `json:"a,omitempty"` 1378 y 1379 B string `json:"b"` 1380 v `json:"v"` 1381 C string `json:"c,omitempty"` 1382 z `json:",omitempty"` 1383 *x1 1384 } 1385 // x2 is a variant of the x1 type without 1386 // the omitempty option on the first field. 1387 x2 struct { 1388 A int16 `json:"a"` 1389 v `json:"v"` 1390 } 1391 ) 1392 xx1 := &x1{ 1393 A: "A", 1394 y: y{ 1395 D: math.MinInt8, 1396 r: r{J: "J"}, 1397 v: v{H: false}, 1398 }, 1399 z: z{ 1400 G: math.MaxUint16, 1401 y: y{D: 21, r: r{J: "J"}}, 1402 v: v{H: true}, 1403 }, 1404 x1: &x1{ 1405 A: "A", 1406 }, 1407 } 1408 xx2 := &x2{A: 42, v: v{I: "I"}} 1409 1410 marshalCompare(t, xx1, "") 1411 marshalCompare(t, xx2, "") 1412 } 1413 1414 // TestAnonymousFields tests the marshaling of 1415 // advanced cases for anonymous struct fields. 1416 // Adapted from the encoding/json testsuite. 1417 func TestAnonymousFields(t *testing.T) { 1418 testdata := []struct { 1419 label string 1420 input func() []interface{} 1421 }{{ 1422 // Both S1 and S2 have a field named X. 1423 // From the perspective of S, it is 1424 // ambiguous which one X refers to. 1425 // This should not encode either field. 1426 label: "AmbiguousField", 1427 input: func() []interface{} { 1428 type ( 1429 S1 struct{ x, X int } 1430 S2 struct{ x, X int } 1431 S struct { 1432 S1 1433 S2 1434 } 1435 ) 1436 return []interface{}{ 1437 S{S1{1, 2}, S2{3, 4}}, 1438 &S{S1{5, 6}, S2{7, 8}}, 1439 } 1440 }, 1441 }, { 1442 // Both S1 and S2 have a field named X, but 1443 // since S has an X field as well, it takes 1444 // precedence over S1.X and S2.X. 1445 label: "DominantField", 1446 input: func() []interface{} { 1447 type ( 1448 S1 struct{ x, X int } 1449 S2 struct{ x, X int } 1450 S struct { 1451 S1 1452 S2 1453 x, X int 1454 } 1455 ) 1456 return []interface{}{ 1457 S{S1{1, 2}, S2{3, 4}, 5, 6}, 1458 &S{S1{6, 5}, S2{4, 3}, 2, 1}, 1459 } 1460 }, 1461 }, { 1462 // Unexported embedded field of non-struct type 1463 // should not be serialized. 1464 label: "UnexportedEmbeddedInt", 1465 input: func() []interface{} { 1466 type ( 1467 i int 1468 S struct{ i } 1469 ) 1470 return []interface{}{S{5}, &S{6}} 1471 }, 1472 }, { 1473 // Exported embedded field of non-struct type 1474 // should be serialized. 1475 label: "ExportedEmbeddedInt", 1476 input: func() []interface{} { 1477 type ( 1478 I int 1479 S struct{ I } 1480 ) 1481 return []interface{}{S{5}, &S{6}} 1482 }, 1483 }, { 1484 // Unexported embedded field of pointer to 1485 // non-struct type should not be serialized. 1486 label: "UnexportedEmbeddedIntPointer", 1487 input: func() []interface{} { 1488 type ( 1489 i int 1490 S struct{ *i } 1491 ) 1492 s := S{new(i)} 1493 *s.i = 5 1494 return []interface{}{s, &s} 1495 }, 1496 }, { 1497 // Exported embedded field of pointer to 1498 // non-struct type should be serialized. 1499 label: "ExportedEmbeddedIntPointer", 1500 input: func() []interface{} { 1501 type ( 1502 I int 1503 S struct{ *I } 1504 ) 1505 s := S{new(I)} 1506 *s.I = 5 1507 return []interface{}{s, &s} 1508 }, 1509 }, { 1510 // Exported embedded field of nil pointer 1511 // to non-struct type should be serialized. 1512 label: "ExportedEmbeddedNilIntPointer", 1513 input: func() []interface{} { 1514 type ( 1515 I int 1516 S struct{ *I } 1517 ) 1518 s := S{new(I)} 1519 s.I = nil 1520 return []interface{}{s, &s} 1521 }, 1522 }, { 1523 // Exported embedded field of nil pointer to 1524 // non-struct type should not be serialized 1525 // if it has the omitempty option. 1526 label: "ExportedEmbeddedNilIntPointerOmitempty", 1527 input: func() []interface{} { 1528 type ( 1529 I int 1530 S struct { 1531 *I `json:",omitempty"` 1532 } 1533 ) 1534 s := S{new(I)} 1535 s.I = nil 1536 return []interface{}{s, &s} 1537 }, 1538 }, { 1539 // Exported embedded field of pointer to 1540 // struct type should be serialized. 1541 label: "ExportedEmbeddedStructPointer", 1542 input: func() []interface{} { 1543 type ( 1544 S struct{ X string } 1545 T struct{ *S } 1546 ) 1547 t := T{S: &S{ 1548 X: "X", 1549 }} 1550 return []interface{}{t, &t} 1551 }, 1552 }, { 1553 // Exported fields of embedded structs should 1554 // have their exported fields be serialized 1555 // regardless of whether the struct types 1556 // themselves are exported. 1557 label: "EmbeddedStructNonPointer", 1558 input: func() []interface{} { 1559 type ( 1560 s1 struct{ x, X int } 1561 S2 struct{ y, Y int } 1562 S struct { 1563 s1 1564 S2 1565 } 1566 ) 1567 return []interface{}{ 1568 S{s1{1, 2}, S2{3, 4}}, 1569 &S{s1{5, 6}, S2{7, 8}}, 1570 } 1571 }, 1572 }, { 1573 // Exported fields of pointers to embedded 1574 // structs should have their exported fields 1575 // be serialized regardless of whether the 1576 // struct types themselves are exported. 1577 label: "EmbeddedStructPointer", 1578 input: func() []interface{} { 1579 type ( 1580 s1 struct{ x, X int } 1581 S2 struct{ y, Y int } 1582 S struct { 1583 *s1 1584 *S2 1585 } 1586 ) 1587 return []interface{}{ 1588 S{&s1{1, 2}, &S2{3, 4}}, 1589 &S{&s1{5, 6}, &S2{7, 8}}, 1590 } 1591 }, 1592 }, { 1593 // Exported fields on embedded unexported 1594 // structs at multiple levels of nesting 1595 // should still be serialized. 1596 label: "NestedStructAndInts", 1597 input: func() []interface{} { 1598 type ( 1599 I1 int 1600 I2 int 1601 i int 1602 s2 struct { 1603 I2 1604 i 1605 } 1606 s1 struct { 1607 I1 1608 i 1609 s2 1610 } 1611 S struct { 1612 s1 1613 i 1614 } 1615 ) 1616 return []interface{}{ 1617 S{s1{1, 2, s2{3, 4}}, 5}, 1618 &S{s1{5, 4, s2{3, 2}}, 1}, 1619 } 1620 }, 1621 }, { 1622 // If an anonymous struct pointer field is nil, 1623 // we should ignore the embedded fields behind it. 1624 // Not properly doing so may result in the wrong 1625 // output or a panic. 1626 label: "EmbeddedFieldBehindNilPointer", 1627 input: func() []interface{} { 1628 type ( 1629 S2 struct{ Field string } 1630 S struct{ *S2 } 1631 ) 1632 return []interface{}{S{}, &S{}} 1633 }, 1634 }, { 1635 // A field behind a chain of pointer and 1636 // non-pointer embedded fields should be 1637 // accessible and serialized. 1638 label: "BasicEmbeddedFieldChain", 1639 input: func() []interface{} { 1640 type ( 1641 A struct { 1642 X1 string 1643 X2 *string 1644 } 1645 B struct{ *A } 1646 C struct{ B } 1647 D struct{ *C } 1648 E struct{ D } 1649 F struct{ *E } 1650 ) 1651 s := "Loreum" 1652 f := F{E: &E{D: D{C: &C{B: B{A: &A{X1: "X1", X2: &s}}}}}} 1653 return []interface{}{f, &f} 1654 }, 1655 }, { 1656 // Variant of the test above, with embedded 1657 // fields of type struct that contain one or 1658 // more fields themselves. 1659 label: "ComplexEmbeddedFieldChain", 1660 input: func() []interface{} { 1661 type ( 1662 A struct { 1663 X1 string `json:",omitempty"` 1664 X2 string 1665 } 1666 B struct { 1667 Z3 *bool 1668 A 1669 } 1670 C struct{ B } 1671 D struct { 1672 *C 1673 Z2 int 1674 } 1675 E struct{ *D } 1676 F struct { 1677 Z1 string `json:",omitempty"` 1678 *E 1679 } 1680 ) 1681 f := F{Z1: "Z1", E: &E{D: &D{C: &C{B: B{A: A{X2: "X2"}, Z3: new(bool)}}, Z2: 1}}} 1682 return []interface{}{f, &f} 1683 }, 1684 }} 1685 for i := range testdata { 1686 e := testdata[i] 1687 t.Run(e.label, func(t *testing.T) { 1688 for i, input := range e.input() { 1689 input := input 1690 var label string 1691 if i == 0 { 1692 label = "non-pointer" 1693 } else { 1694 label = "pointer" 1695 } 1696 t.Run(label, func(t *testing.T) { 1697 marshalCompare(t, input, label) 1698 }) 1699 } 1700 }) 1701 } 1702 } 1703 1704 func TestBytesEscaping(t *testing.T) { 1705 testdata := []struct { 1706 in, out string 1707 }{ 1708 {"\x00", `"\u0000"`}, 1709 {"\x01", `"\u0001"`}, 1710 {"\x02", `"\u0002"`}, 1711 {"\x03", `"\u0003"`}, 1712 {"\x04", `"\u0004"`}, 1713 {"\x05", `"\u0005"`}, 1714 {"\x06", `"\u0006"`}, 1715 {"\x07", `"\u0007"`}, 1716 {"\x08", `"\u0008"`}, 1717 {"\x09", `"\t"`}, 1718 {"\x0a", `"\n"`}, 1719 {"\x0b", `"\u000b"`}, 1720 {"\x0c", `"\u000c"`}, 1721 {"\x0d", `"\r"`}, 1722 {"\x0e", `"\u000e"`}, 1723 {"\x0f", `"\u000f"`}, 1724 {"\x10", `"\u0010"`}, 1725 {"\x11", `"\u0011"`}, 1726 {"\x12", `"\u0012"`}, 1727 {"\x13", `"\u0013"`}, 1728 {"\x14", `"\u0014"`}, 1729 {"\x15", `"\u0015"`}, 1730 {"\x16", `"\u0016"`}, 1731 {"\x17", `"\u0017"`}, 1732 {"\x18", `"\u0018"`}, 1733 {"\x19", `"\u0019"`}, 1734 {"\x1a", `"\u001a"`}, 1735 {"\x1b", `"\u001b"`}, 1736 {"\x1c", `"\u001c"`}, 1737 {"\x1d", `"\u001d"`}, 1738 {"\x1e", `"\u001e"`}, 1739 {"\x1f", `"\u001f"`}, 1740 } 1741 for _, tt := range testdata { 1742 b, err := Marshal(tt.in) 1743 if err != nil { 1744 t.Error(err) 1745 } 1746 if s := string(b); s != tt.out { 1747 t.Errorf("got %#q, want %#q", s, tt.out) 1748 } 1749 } 1750 } 1751 1752 // TestStringEscaping tests that control and reserved 1753 // JSON characters are properly escaped when a string 1754 // is marshaled. 1755 func TestStringEscaping(t *testing.T) { 1756 b := []byte{ 1757 'A', 1, 2, 3, 1758 '"', '\\', '/', '\b', '\f', '\n', '\r', '\t', 1759 0xC7, 0xA3, 0xE2, 0x80, 0xA8, 0xE2, 0x80, 0xA9, 1760 } 1761 testdata := []struct { 1762 b []byte 1763 s string 1764 opt Option 1765 cmp bool 1766 }{ 1767 {b, `"A\u0001\u0002\u0003\"\\/\u0008\u000c\n\r\tǣ\u2028\u2029"`, nil, true}, 1768 {b, `"` + string(b) + `"`, NoStringEscaping(), false}, 1769 } 1770 for _, tt := range testdata { 1771 b, err := MarshalOpts(string(tt.b), tt.opt) 1772 if err != nil { 1773 t.Error(err) 1774 } 1775 if s := string(b); s != tt.s { 1776 t.Errorf("got %#q, want %#q", s, tt.s) 1777 } 1778 if tt.cmp { 1779 bs, err := json.Marshal(string(tt.b)) 1780 if err != nil { 1781 t.Error(err) 1782 } 1783 if !bytes.Equal(bs, b) { 1784 t.Logf("standard: %s", bs) 1785 t.Logf("jettison: %s", b) 1786 t.Errorf("expected equal outputs") 1787 } 1788 } 1789 } 1790 } 1791 1792 // TestStringHTMLEscaping tests that HTML characters 1793 // are properly escaped when a string is marshaled. 1794 func TestStringHTMLEscaping(t *testing.T) { 1795 htmlChars := []byte{'<', '>', '&'} 1796 testdata := []struct { 1797 b []byte 1798 s string 1799 opts []Option 1800 }{ 1801 {htmlChars, `"\u003c\u003e\u0026"`, nil}, 1802 {htmlChars, `"<>&"`, []Option{NoHTMLEscaping()}}, 1803 1804 // NoHTMLEscaping is ignored when NoStringEscaping 1805 // is set, because it's part of the escaping options. 1806 {htmlChars, `"<>&"`, []Option{NoStringEscaping()}}, 1807 {htmlChars, `"<>&"`, []Option{NoStringEscaping(), NoHTMLEscaping()}}, 1808 } 1809 for _, tt := range testdata { 1810 b, err := MarshalOpts(string(tt.b), tt.opts...) 1811 if err != nil { 1812 t.Error(err) 1813 } 1814 if s := string(b); s != tt.s { 1815 t.Errorf("got %#q, want %#q", s, tt.s) 1816 } 1817 } 1818 } 1819 1820 // TestStringUTF8Coercion tests that invalid bytes 1821 // are replaced by the Unicode replacement rune when 1822 // a string is marshaled. 1823 func TestStringUTF8Coercion(t *testing.T) { 1824 utf8Seq := string([]byte{'H', 'e', 'l', 'l', 'o', ',', ' ', 0xff, 0xfe, 0xff}) 1825 testdata := []struct { 1826 b string 1827 s string 1828 opt Option 1829 }{ 1830 {utf8Seq, `"Hello, \ufffd\ufffd\ufffd"`, nil}, 1831 {utf8Seq, `"` + utf8Seq + `"`, NoUTF8Coercion()}, 1832 } 1833 for _, tt := range testdata { 1834 b, err := MarshalOpts(tt.b, tt.opt) 1835 if err != nil { 1836 t.Error(err) 1837 } 1838 if s := string(b); s != tt.s { 1839 t.Errorf("got %#q, want %#q", s, tt.s) 1840 } 1841 } 1842 } 1843 1844 func TestMarshalFloat(t *testing.T) { 1845 // Taken from encoding/json. 1846 t.Parallel() 1847 1848 nf := 0 1849 mc := regexp.MustCompile 1850 re := []*regexp.Regexp{ 1851 mc(`p`), 1852 mc(`^\+`), 1853 mc(`^-?0[^.]`), 1854 mc(`^-?\.`), 1855 mc(`\.(e|$)`), 1856 mc(`\.[0-9]+0(e|$)`), 1857 mc(`^-?(0|[0-9]{2,})\..*e`), 1858 mc(`e[0-9]`), 1859 mc(`e[+-]0`), 1860 mc(`e-[1-6]$`), 1861 mc(`e+(.|1.|20)$`), 1862 mc(`^-?0\.0000000`), 1863 mc(`^-?[0-9]{22}`), 1864 mc(`[1-9][0-9]{16}[1-9]`), 1865 mc(`[1-9][0-9.]{17}[1-9]`), 1866 mc(`[1-9][0-9]{8}[1-9]`), 1867 mc(`[1-9][0-9.]{9}[1-9]`), 1868 } 1869 fn := func(f float64, bits int) { 1870 vf := interface{}(f) 1871 if bits == 32 { 1872 f = float64(float32(f)) // round 1873 vf = float32(f) 1874 } 1875 bout, err := Marshal(vf) 1876 if err != nil { 1877 t.Errorf("Encode(%T(%g)): %v", vf, vf, err) 1878 nf++ 1879 return 1880 } 1881 out := string(bout) 1882 1883 // Result must convert back to the same float. 1884 g, err := strconv.ParseFloat(out, bits) 1885 if err != nil { 1886 t.Errorf("%T(%g) = %q, cannot parse back: %v", vf, vf, out, err) 1887 nf++ 1888 return 1889 } 1890 if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0 1891 t.Errorf("%T(%g) = %q (is %g, not %g)", vf, vf, out, float32(g), vf) 1892 nf++ 1893 return 1894 } 1895 bad := re 1896 if bits == 64 { 1897 // Last two regexps are for 32-bits values only. 1898 bad = bad[:len(bad)-2] 1899 } 1900 for _, re := range bad { 1901 if re.MatchString(out) { 1902 t.Errorf("%T(%g) = %q, must not match /%s/", vf, vf, out, re) 1903 nf++ 1904 return 1905 } 1906 } 1907 } 1908 fn(0, 64) 1909 fn(math.Copysign(0, -1), 64) 1910 fn(0, 32) 1911 fn(math.Copysign(0, -1), 32) 1912 1913 var ( 1914 bigger = math.Inf(+1) 1915 smaller = math.Inf(-1) 1916 digits = "1.2345678901234567890123" 1917 ) 1918 for i := len(digits); i >= 2; i-- { 1919 if testing.Short() && i < len(digits)-4 { 1920 break 1921 } 1922 for exp := -30; exp <= 30; exp++ { 1923 for _, sign := range "+-" { 1924 for bits := 32; bits <= 64; bits += 32 { 1925 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp) 1926 f, err := strconv.ParseFloat(s, bits) 1927 if err != nil { 1928 t.Fatal(err) 1929 } 1930 next := math.Nextafter 1931 if bits == 32 { 1932 next = func(g, h float64) float64 { 1933 return float64(math.Nextafter32(float32(g), float32(h))) 1934 } 1935 } 1936 fn(f, bits) 1937 fn(next(f, bigger), bits) 1938 fn(next(f, smaller), bits) 1939 1940 if nf > 50 { 1941 t.Fatalf("too many fails, stopping tests early") 1942 } 1943 } 1944 } 1945 } 1946 } 1947 }