github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/encoding/json/encode_test.go (about) 1 // Copyright 2011 The Go Authors. 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 json 6 7 import ( 8 "bytes" 9 "fmt" 10 "log" 11 "math" 12 "reflect" 13 "regexp" 14 "strconv" 15 "testing" 16 "unicode" 17 ) 18 19 type Optionals struct { 20 Sr string `json:"sr"` 21 So string `json:"so,omitempty"` 22 Sw string `json:"-"` 23 24 Ir int `json:"omitempty"` // actually named omitempty, not an option 25 Io int `json:"io,omitempty"` 26 27 Slr []string `json:"slr,random"` 28 Slo []string `json:"slo,omitempty"` 29 30 Mr map[string]interface{} `json:"mr"` 31 Mo map[string]interface{} `json:",omitempty"` 32 33 Fr float64 `json:"fr"` 34 Fo float64 `json:"fo,omitempty"` 35 36 Br bool `json:"br"` 37 Bo bool `json:"bo,omitempty"` 38 39 Ur uint `json:"ur"` 40 Uo uint `json:"uo,omitempty"` 41 42 Str struct{} `json:"str"` 43 Sto struct{} `json:"sto,omitempty"` 44 } 45 46 var optionalsExpected = `{ 47 "sr": "", 48 "omitempty": 0, 49 "slr": null, 50 "mr": {}, 51 "fr": 0, 52 "br": false, 53 "ur": 0, 54 "str": {}, 55 "sto": {} 56 }` 57 58 func TestOmitEmpty(t *testing.T) { 59 var o Optionals 60 o.Sw = "something" 61 o.Mr = map[string]interface{}{} 62 o.Mo = map[string]interface{}{} 63 64 got, err := MarshalIndent(&o, "", " ") 65 if err != nil { 66 t.Fatal(err) 67 } 68 if got := string(got); got != optionalsExpected { 69 t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected) 70 } 71 } 72 73 type StringTag struct { 74 BoolStr bool `json:",string"` 75 IntStr int64 `json:",string"` 76 StrStr string `json:",string"` 77 } 78 79 var stringTagExpected = `{ 80 "BoolStr": "true", 81 "IntStr": "42", 82 "StrStr": "\"xzbit\"" 83 }` 84 85 func TestStringTag(t *testing.T) { 86 var s StringTag 87 s.BoolStr = true 88 s.IntStr = 42 89 s.StrStr = "xzbit" 90 got, err := MarshalIndent(&s, "", " ") 91 if err != nil { 92 t.Fatal(err) 93 } 94 if got := string(got); got != stringTagExpected { 95 t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected) 96 } 97 98 // Verify that it round-trips. 99 var s2 StringTag 100 err = NewDecoder(bytes.NewReader(got)).Decode(&s2) 101 if err != nil { 102 t.Fatalf("Decode: %v", err) 103 } 104 if !reflect.DeepEqual(s, s2) { 105 t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2) 106 } 107 } 108 109 // byte slices are special even if they're renamed types. 110 type renamedByte byte 111 type renamedByteSlice []byte 112 type renamedRenamedByteSlice []renamedByte 113 114 func TestEncodeRenamedByteSlice(t *testing.T) { 115 s := renamedByteSlice("abc") 116 result, err := Marshal(s) 117 if err != nil { 118 t.Fatal(err) 119 } 120 expect := `"YWJj"` 121 if string(result) != expect { 122 t.Errorf(" got %s want %s", result, expect) 123 } 124 r := renamedRenamedByteSlice("abc") 125 result, err = Marshal(r) 126 if err != nil { 127 t.Fatal(err) 128 } 129 if string(result) != expect { 130 t.Errorf(" got %s want %s", result, expect) 131 } 132 } 133 134 var unsupportedValues = []interface{}{ 135 math.NaN(), 136 math.Inf(-1), 137 math.Inf(1), 138 } 139 140 func TestUnsupportedValues(t *testing.T) { 141 for _, v := range unsupportedValues { 142 if _, err := Marshal(v); err != nil { 143 if _, ok := err.(*UnsupportedValueError); !ok { 144 t.Errorf("for %v, got %T want UnsupportedValueError", v, err) 145 } 146 } else { 147 t.Errorf("for %v, expected error", v) 148 } 149 } 150 } 151 152 // Ref has Marshaler and Unmarshaler methods with pointer receiver. 153 type Ref int 154 155 func (*Ref) MarshalJSON() ([]byte, error) { 156 return []byte(`"ref"`), nil 157 } 158 159 func (r *Ref) UnmarshalJSON([]byte) error { 160 *r = 12 161 return nil 162 } 163 164 // Val has Marshaler methods with value receiver. 165 type Val int 166 167 func (Val) MarshalJSON() ([]byte, error) { 168 return []byte(`"val"`), nil 169 } 170 171 // RefText has Marshaler and Unmarshaler methods with pointer receiver. 172 type RefText int 173 174 func (*RefText) MarshalText() ([]byte, error) { 175 return []byte(`"ref"`), nil 176 } 177 178 func (r *RefText) UnmarshalText([]byte) error { 179 *r = 13 180 return nil 181 } 182 183 // ValText has Marshaler methods with value receiver. 184 type ValText int 185 186 func (ValText) MarshalText() ([]byte, error) { 187 return []byte(`"val"`), nil 188 } 189 190 func TestRefValMarshal(t *testing.T) { 191 var s = struct { 192 R0 Ref 193 R1 *Ref 194 R2 RefText 195 R3 *RefText 196 V0 Val 197 V1 *Val 198 V2 ValText 199 V3 *ValText 200 }{ 201 R0: 12, 202 R1: new(Ref), 203 R2: 14, 204 R3: new(RefText), 205 V0: 13, 206 V1: new(Val), 207 V2: 15, 208 V3: new(ValText), 209 } 210 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}` 211 b, err := Marshal(&s) 212 if err != nil { 213 t.Fatalf("Marshal: %v", err) 214 } 215 if got := string(b); got != want { 216 t.Errorf("got %q, want %q", got, want) 217 } 218 } 219 220 // C implements Marshaler and returns unescaped JSON. 221 type C int 222 223 func (C) MarshalJSON() ([]byte, error) { 224 return []byte(`"<&>"`), nil 225 } 226 227 // CText implements Marshaler and returns unescaped text. 228 type CText int 229 230 func (CText) MarshalText() ([]byte, error) { 231 return []byte(`"<&>"`), nil 232 } 233 234 func TestMarshalerEscaping(t *testing.T) { 235 var c C 236 want := `"\u003c\u0026\u003e"` 237 b, err := Marshal(c) 238 if err != nil { 239 t.Fatalf("Marshal(c): %v", err) 240 } 241 if got := string(b); got != want { 242 t.Errorf("Marshal(c) = %#q, want %#q", got, want) 243 } 244 245 var ct CText 246 want = `"\"\u003c\u0026\u003e\""` 247 b, err = Marshal(ct) 248 if err != nil { 249 t.Fatalf("Marshal(ct): %v", err) 250 } 251 if got := string(b); got != want { 252 t.Errorf("Marshal(ct) = %#q, want %#q", got, want) 253 } 254 } 255 256 type IntType int 257 258 type MyStruct struct { 259 IntType 260 } 261 262 func TestAnonymousNonstruct(t *testing.T) { 263 var i IntType = 11 264 a := MyStruct{i} 265 const want = `{"IntType":11}` 266 267 b, err := Marshal(a) 268 if err != nil { 269 t.Fatalf("Marshal: %v", err) 270 } 271 if got := string(b); got != want { 272 t.Errorf("got %q, want %q", got, want) 273 } 274 } 275 276 type BugA struct { 277 S string 278 } 279 280 type BugB struct { 281 BugA 282 S string 283 } 284 285 type BugC struct { 286 S string 287 } 288 289 // Legal Go: We never use the repeated embedded field (S). 290 type BugX struct { 291 A int 292 BugA 293 BugB 294 } 295 296 // Issue 5245. 297 func TestEmbeddedBug(t *testing.T) { 298 v := BugB{ 299 BugA{"A"}, 300 "B", 301 } 302 b, err := Marshal(v) 303 if err != nil { 304 t.Fatal("Marshal:", err) 305 } 306 want := `{"S":"B"}` 307 got := string(b) 308 if got != want { 309 t.Fatalf("Marshal: got %s want %s", got, want) 310 } 311 // Now check that the duplicate field, S, does not appear. 312 x := BugX{ 313 A: 23, 314 } 315 b, err = Marshal(x) 316 if err != nil { 317 t.Fatal("Marshal:", err) 318 } 319 want = `{"A":23}` 320 got = string(b) 321 if got != want { 322 t.Fatalf("Marshal: got %s want %s", got, want) 323 } 324 } 325 326 type BugD struct { // Same as BugA after tagging. 327 XXX string `json:"S"` 328 } 329 330 // BugD's tagged S field should dominate BugA's. 331 type BugY struct { 332 BugA 333 BugD 334 } 335 336 // Test that a field with a tag dominates untagged fields. 337 func TestTaggedFieldDominates(t *testing.T) { 338 v := BugY{ 339 BugA{"BugA"}, 340 BugD{"BugD"}, 341 } 342 b, err := Marshal(v) 343 if err != nil { 344 t.Fatal("Marshal:", err) 345 } 346 want := `{"S":"BugD"}` 347 got := string(b) 348 if got != want { 349 t.Fatalf("Marshal: got %s want %s", got, want) 350 } 351 } 352 353 // There are no tags here, so S should not appear. 354 type BugZ struct { 355 BugA 356 BugC 357 BugY // Contains a tagged S field through BugD; should not dominate. 358 } 359 360 func TestDuplicatedFieldDisappears(t *testing.T) { 361 v := BugZ{ 362 BugA{"BugA"}, 363 BugC{"BugC"}, 364 BugY{ 365 BugA{"nested BugA"}, 366 BugD{"nested BugD"}, 367 }, 368 } 369 b, err := Marshal(v) 370 if err != nil { 371 t.Fatal("Marshal:", err) 372 } 373 want := `{}` 374 got := string(b) 375 if got != want { 376 t.Fatalf("Marshal: got %s want %s", got, want) 377 } 378 } 379 380 func TestStringBytes(t *testing.T) { 381 // Test that encodeState.stringBytes and encodeState.string use the same encoding. 382 var r []rune 383 for i := '\u0000'; i <= unicode.MaxRune; i++ { 384 r = append(r, i) 385 } 386 s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too 387 388 for _, escapeHTML := range []bool{true, false} { 389 es := &encodeState{} 390 es.string(s, escapeHTML) 391 392 esBytes := &encodeState{} 393 esBytes.stringBytes([]byte(s), escapeHTML) 394 395 enc := es.Buffer.String() 396 encBytes := esBytes.Buffer.String() 397 if enc != encBytes { 398 i := 0 399 for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] { 400 i++ 401 } 402 enc = enc[i:] 403 encBytes = encBytes[i:] 404 i = 0 405 for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] { 406 i++ 407 } 408 enc = enc[:len(enc)-i] 409 encBytes = encBytes[:len(encBytes)-i] 410 411 if len(enc) > 20 { 412 enc = enc[:20] + "..." 413 } 414 if len(encBytes) > 20 { 415 encBytes = encBytes[:20] + "..." 416 } 417 418 t.Errorf("with escapeHTML=%t, encodings differ at %#q vs %#q", 419 escapeHTML, enc, encBytes) 420 } 421 } 422 } 423 424 func TestIssue6458(t *testing.T) { 425 type Foo struct { 426 M RawMessage 427 } 428 x := Foo{RawMessage(`"foo"`)} 429 430 b, err := Marshal(&x) 431 if err != nil { 432 t.Fatal(err) 433 } 434 if want := `{"M":"foo"}`; string(b) != want { 435 t.Errorf("Marshal(&x) = %#q; want %#q", b, want) 436 } 437 438 b, err = Marshal(x) 439 if err != nil { 440 t.Fatal(err) 441 } 442 443 // Until Go 1.8, this generated `{"M":"ImZvbyI="}`. 444 // See https://github.com/golang/go/issues/14493#issuecomment-255857318 445 if want := `{"M":"foo"}`; string(b) != want { 446 t.Errorf("Marshal(x) = %#q; want %#q", b, want) 447 } 448 } 449 450 func TestIssue10281(t *testing.T) { 451 type Foo struct { 452 N Number 453 } 454 x := Foo{Number(`invalid`)} 455 456 b, err := Marshal(&x) 457 if err == nil { 458 t.Errorf("Marshal(&x) = %#q; want error", b) 459 } 460 } 461 462 func TestHTMLEscape(t *testing.T) { 463 var b, want bytes.Buffer 464 m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}` 465 want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`)) 466 HTMLEscape(&b, []byte(m)) 467 if !bytes.Equal(b.Bytes(), want.Bytes()) { 468 t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes()) 469 } 470 } 471 472 // golang.org/issue/8582 473 func TestEncodePointerString(t *testing.T) { 474 type stringPointer struct { 475 N *int64 `json:"n,string"` 476 } 477 var n int64 = 42 478 b, err := Marshal(stringPointer{N: &n}) 479 if err != nil { 480 t.Fatalf("Marshal: %v", err) 481 } 482 if got, want := string(b), `{"n":"42"}`; got != want { 483 t.Errorf("Marshal = %s, want %s", got, want) 484 } 485 var back stringPointer 486 err = Unmarshal(b, &back) 487 if err != nil { 488 t.Fatalf("Unmarshal: %v", err) 489 } 490 if back.N == nil { 491 t.Fatalf("Unmarshalled nil N field") 492 } 493 if *back.N != 42 { 494 t.Fatalf("*N = %d; want 42", *back.N) 495 } 496 } 497 498 var encodeStringTests = []struct { 499 in string 500 out string 501 }{ 502 {"\x00", `"\u0000"`}, 503 {"\x01", `"\u0001"`}, 504 {"\x02", `"\u0002"`}, 505 {"\x03", `"\u0003"`}, 506 {"\x04", `"\u0004"`}, 507 {"\x05", `"\u0005"`}, 508 {"\x06", `"\u0006"`}, 509 {"\x07", `"\u0007"`}, 510 {"\x08", `"\u0008"`}, 511 {"\x09", `"\t"`}, 512 {"\x0a", `"\n"`}, 513 {"\x0b", `"\u000b"`}, 514 {"\x0c", `"\u000c"`}, 515 {"\x0d", `"\r"`}, 516 {"\x0e", `"\u000e"`}, 517 {"\x0f", `"\u000f"`}, 518 {"\x10", `"\u0010"`}, 519 {"\x11", `"\u0011"`}, 520 {"\x12", `"\u0012"`}, 521 {"\x13", `"\u0013"`}, 522 {"\x14", `"\u0014"`}, 523 {"\x15", `"\u0015"`}, 524 {"\x16", `"\u0016"`}, 525 {"\x17", `"\u0017"`}, 526 {"\x18", `"\u0018"`}, 527 {"\x19", `"\u0019"`}, 528 {"\x1a", `"\u001a"`}, 529 {"\x1b", `"\u001b"`}, 530 {"\x1c", `"\u001c"`}, 531 {"\x1d", `"\u001d"`}, 532 {"\x1e", `"\u001e"`}, 533 {"\x1f", `"\u001f"`}, 534 } 535 536 func TestEncodeString(t *testing.T) { 537 for _, tt := range encodeStringTests { 538 b, err := Marshal(tt.in) 539 if err != nil { 540 t.Errorf("Marshal(%q): %v", tt.in, err) 541 continue 542 } 543 out := string(b) 544 if out != tt.out { 545 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out) 546 } 547 } 548 } 549 550 type jsonbyte byte 551 552 func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) } 553 554 type textbyte byte 555 556 func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) } 557 558 type jsonint int 559 560 func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) } 561 562 type textint int 563 564 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) } 565 566 func tenc(format string, a ...interface{}) ([]byte, error) { 567 var buf bytes.Buffer 568 fmt.Fprintf(&buf, format, a...) 569 return buf.Bytes(), nil 570 } 571 572 // Issue 13783 573 func TestEncodeBytekind(t *testing.T) { 574 testdata := []struct { 575 data interface{} 576 want string 577 }{ 578 {byte(7), "7"}, 579 {jsonbyte(7), `{"JB":7}`}, 580 {textbyte(4), `"TB:4"`}, 581 {jsonint(5), `{"JI":5}`}, 582 {textint(1), `"TI:1"`}, 583 {[]byte{0, 1}, `"AAE="`}, 584 {[]jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`}, 585 {[][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`}, 586 {[]textbyte{2, 3}, `["TB:2","TB:3"]`}, 587 {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`}, 588 {[]textint{9, 3}, `["TI:9","TI:3"]`}, 589 {[]int{9, 3}, `[9,3]`}, 590 } 591 for _, d := range testdata { 592 js, err := Marshal(d.data) 593 if err != nil { 594 t.Error(err) 595 continue 596 } 597 got, want := string(js), d.want 598 if got != want { 599 t.Errorf("got %s, want %s", got, want) 600 } 601 } 602 } 603 604 func TestTextMarshalerMapKeysAreSorted(t *testing.T) { 605 b, err := Marshal(map[unmarshalerText]int{ 606 {"x", "y"}: 1, 607 {"y", "x"}: 2, 608 {"a", "z"}: 3, 609 {"z", "a"}: 4, 610 }) 611 if err != nil { 612 t.Fatalf("Failed to Marshal text.Marshaler: %v", err) 613 } 614 const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}` 615 if string(b) != want { 616 t.Errorf("Marshal map with text.Marshaler keys: got %#q, want %#q", b, want) 617 } 618 } 619 620 var re = regexp.MustCompile 621 622 // syntactic checks on form of marshalled floating point numbers. 623 var badFloatREs = []*regexp.Regexp{ 624 re(`p`), // no binary exponential notation 625 re(`^\+`), // no leading + sign 626 re(`^-?0[^.]`), // no unnecessary leading zeros 627 re(`^-?\.`), // leading zero required before decimal point 628 re(`\.(e|$)`), // no trailing decimal 629 re(`\.[0-9]+0(e|$)`), // no trailing zero in fraction 630 re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa 631 re(`e[0-9]`), // positive exponent must be signed 632 re(`e[+-]0`), // exponent must not have leading zeros 633 re(`e-[1-6]$`), // not tiny enough for exponential notation 634 re(`e+(.|1.|20)$`), // not big enough for exponential notation 635 re(`^-?0\.0000000`), // too tiny, should use exponential notation 636 re(`^-?[0-9]{22}`), // too big, should use exponential notation 637 re(`[1-9][0-9]{16}[1-9]`), // too many significant digits in integer 638 re(`[1-9][0-9.]{17}[1-9]`), // too many significant digits in decimal 639 // below here for float32 only 640 re(`[1-9][0-9]{8}[1-9]`), // too many significant digits in integer 641 re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal 642 } 643 644 func TestMarshalFloat(t *testing.T) { 645 nfail := 0 646 test := func(f float64, bits int) { 647 vf := interface{}(f) 648 if bits == 32 { 649 f = float64(float32(f)) // round 650 vf = float32(f) 651 } 652 bout, err := Marshal(vf) 653 if err != nil { 654 t.Errorf("Marshal(%T(%g)): %v", vf, vf, err) 655 nfail++ 656 return 657 } 658 out := string(bout) 659 660 // result must convert back to the same float 661 g, err := strconv.ParseFloat(out, bits) 662 if err != nil { 663 t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err) 664 nfail++ 665 return 666 } 667 if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0 668 t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf) 669 nfail++ 670 return 671 } 672 673 bad := badFloatREs 674 if bits == 64 { 675 bad = bad[:len(bad)-2] 676 } 677 for _, re := range bad { 678 if re.MatchString(out) { 679 t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re) 680 nfail++ 681 return 682 } 683 } 684 } 685 686 var ( 687 bigger = math.Inf(+1) 688 smaller = math.Inf(-1) 689 ) 690 691 var digits = "1.2345678901234567890123" 692 for i := len(digits); i >= 2; i-- { 693 for exp := -30; exp <= 30; exp++ { 694 for _, sign := range "+-" { 695 for bits := 32; bits <= 64; bits += 32 { 696 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp) 697 f, err := strconv.ParseFloat(s, bits) 698 if err != nil { 699 log.Fatal(err) 700 } 701 next := math.Nextafter 702 if bits == 32 { 703 next = func(g, h float64) float64 { 704 return float64(math.Nextafter32(float32(g), float32(h))) 705 } 706 } 707 test(f, bits) 708 test(next(f, bigger), bits) 709 test(next(f, smaller), bits) 710 if nfail > 50 { 711 t.Fatalf("stopping test early") 712 } 713 } 714 } 715 } 716 } 717 test(0, 64) 718 test(math.Copysign(0, -1), 64) 719 test(0, 32) 720 test(math.Copysign(0, -1), 32) 721 } 722 723 func TestMarshalRawMessageValue(t *testing.T) { 724 const val = "\"some value\"" 725 b, err := Marshal(RawMessage(val)) 726 if err != nil { 727 t.Fatal(err) 728 } 729 if string(b) != val { 730 t.Errorf("got %q; want %q", b, val) 731 } 732 }