github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/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 "math" 10 "reflect" 11 "testing" 12 "unicode" 13 ) 14 15 type Optionals struct { 16 Sr string `json:"sr"` 17 So string `json:"so,omitempty"` 18 Sw string `json:"-"` 19 20 Ir int `json:"omitempty"` // actually named omitempty, not an option 21 Io int `json:"io,omitempty"` 22 23 Slr []string `json:"slr,random"` 24 Slo []string `json:"slo,omitempty"` 25 26 Mr map[string]interface{} `json:"mr"` 27 Mo map[string]interface{} `json:",omitempty"` 28 29 Fr float64 `json:"fr"` 30 Fo float64 `json:"fo,omitempty"` 31 32 Br bool `json:"br"` 33 Bo bool `json:"bo,omitempty"` 34 35 Ur uint `json:"ur"` 36 Uo uint `json:"uo,omitempty"` 37 38 Str struct{} `json:"str"` 39 Sto struct{} `json:"sto,omitempty"` 40 } 41 42 var optionalsExpected = `{ 43 "sr": "", 44 "omitempty": 0, 45 "slr": null, 46 "mr": {}, 47 "fr": 0, 48 "br": false, 49 "ur": 0, 50 "str": {}, 51 "sto": {} 52 }` 53 54 func TestOmitEmpty(t *testing.T) { 55 var o Optionals 56 o.Sw = "something" 57 o.Mr = map[string]interface{}{} 58 o.Mo = map[string]interface{}{} 59 60 got, err := MarshalIndent(&o, "", " ") 61 if err != nil { 62 t.Fatal(err) 63 } 64 if got := string(got); got != optionalsExpected { 65 t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected) 66 } 67 } 68 69 type StringTag struct { 70 BoolStr bool `json:",string"` 71 IntStr int64 `json:",string"` 72 StrStr string `json:",string"` 73 } 74 75 var stringTagExpected = `{ 76 "BoolStr": "true", 77 "IntStr": "42", 78 "StrStr": "\"xzbit\"" 79 }` 80 81 func TestStringTag(t *testing.T) { 82 var s StringTag 83 s.BoolStr = true 84 s.IntStr = 42 85 s.StrStr = "xzbit" 86 got, err := MarshalIndent(&s, "", " ") 87 if err != nil { 88 t.Fatal(err) 89 } 90 if got := string(got); got != stringTagExpected { 91 t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected) 92 } 93 94 // Verify that it round-trips. 95 var s2 StringTag 96 err = NewDecoder(bytes.NewReader(got)).Decode(&s2) 97 if err != nil { 98 t.Fatalf("Decode: %v", err) 99 } 100 if !reflect.DeepEqual(s, s2) { 101 t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2) 102 } 103 } 104 105 // byte slices are special even if they're renamed types. 106 type renamedByte byte 107 type renamedByteSlice []byte 108 type renamedRenamedByteSlice []renamedByte 109 110 func TestEncodeRenamedByteSlice(t *testing.T) { 111 s := renamedByteSlice("abc") 112 result, err := Marshal(s) 113 if err != nil { 114 t.Fatal(err) 115 } 116 expect := `"YWJj"` 117 if string(result) != expect { 118 t.Errorf(" got %s want %s", result, expect) 119 } 120 r := renamedRenamedByteSlice("abc") 121 result, err = Marshal(r) 122 if err != nil { 123 t.Fatal(err) 124 } 125 if string(result) != expect { 126 t.Errorf(" got %s want %s", result, expect) 127 } 128 } 129 130 var unsupportedValues = []interface{}{ 131 math.NaN(), 132 math.Inf(-1), 133 math.Inf(1), 134 } 135 136 func TestUnsupportedValues(t *testing.T) { 137 for _, v := range unsupportedValues { 138 if _, err := Marshal(v); err != nil { 139 if _, ok := err.(*UnsupportedValueError); !ok { 140 t.Errorf("for %v, got %T want UnsupportedValueError", v, err) 141 } 142 } else { 143 t.Errorf("for %v, expected error", v) 144 } 145 } 146 } 147 148 // Ref has Marshaler and Unmarshaler methods with pointer receiver. 149 type Ref int 150 151 func (*Ref) MarshalJSON() ([]byte, error) { 152 return []byte(`"ref"`), nil 153 } 154 155 func (r *Ref) UnmarshalJSON([]byte) error { 156 *r = 12 157 return nil 158 } 159 160 // Val has Marshaler methods with value receiver. 161 type Val int 162 163 func (Val) MarshalJSON() ([]byte, error) { 164 return []byte(`"val"`), nil 165 } 166 167 // RefText has Marshaler and Unmarshaler methods with pointer receiver. 168 type RefText int 169 170 func (*RefText) MarshalText() ([]byte, error) { 171 return []byte(`"ref"`), nil 172 } 173 174 func (r *RefText) UnmarshalText([]byte) error { 175 *r = 13 176 return nil 177 } 178 179 // ValText has Marshaler methods with value receiver. 180 type ValText int 181 182 func (ValText) MarshalText() ([]byte, error) { 183 return []byte(`"val"`), nil 184 } 185 186 func TestRefValMarshal(t *testing.T) { 187 var s = struct { 188 R0 Ref 189 R1 *Ref 190 R2 RefText 191 R3 *RefText 192 V0 Val 193 V1 *Val 194 V2 ValText 195 V3 *ValText 196 }{ 197 R0: 12, 198 R1: new(Ref), 199 R2: 14, 200 R3: new(RefText), 201 V0: 13, 202 V1: new(Val), 203 V2: 15, 204 V3: new(ValText), 205 } 206 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}` 207 b, err := Marshal(&s) 208 if err != nil { 209 t.Fatalf("Marshal: %v", err) 210 } 211 if got := string(b); got != want { 212 t.Errorf("got %q, want %q", got, want) 213 } 214 } 215 216 // C implements Marshaler and returns unescaped JSON. 217 type C int 218 219 func (C) MarshalJSON() ([]byte, error) { 220 return []byte(`"<&>"`), nil 221 } 222 223 // CText implements Marshaler and returns unescaped text. 224 type CText int 225 226 func (CText) MarshalText() ([]byte, error) { 227 return []byte(`"<&>"`), nil 228 } 229 230 func TestMarshalerEscaping(t *testing.T) { 231 var c C 232 want := `"\u003c\u0026\u003e"` 233 b, err := Marshal(c) 234 if err != nil { 235 t.Fatalf("Marshal(c): %v", err) 236 } 237 if got := string(b); got != want { 238 t.Errorf("Marshal(c) = %#q, want %#q", got, want) 239 } 240 241 var ct CText 242 want = `"\"\u003c\u0026\u003e\""` 243 b, err = Marshal(ct) 244 if err != nil { 245 t.Fatalf("Marshal(ct): %v", err) 246 } 247 if got := string(b); got != want { 248 t.Errorf("Marshal(ct) = %#q, want %#q", got, want) 249 } 250 } 251 252 type IntType int 253 254 type MyStruct struct { 255 IntType 256 } 257 258 func TestAnonymousNonstruct(t *testing.T) { 259 var i IntType = 11 260 a := MyStruct{i} 261 const want = `{"IntType":11}` 262 263 b, err := Marshal(a) 264 if err != nil { 265 t.Fatalf("Marshal: %v", err) 266 } 267 if got := string(b); got != want { 268 t.Errorf("got %q, want %q", got, want) 269 } 270 } 271 272 type BugA struct { 273 S string 274 } 275 276 type BugB struct { 277 BugA 278 S string 279 } 280 281 type BugC struct { 282 S string 283 } 284 285 // Legal Go: We never use the repeated embedded field (S). 286 type BugX struct { 287 A int 288 BugA 289 BugB 290 } 291 292 // Issue 5245. 293 func TestEmbeddedBug(t *testing.T) { 294 v := BugB{ 295 BugA{"A"}, 296 "B", 297 } 298 b, err := Marshal(v) 299 if err != nil { 300 t.Fatal("Marshal:", err) 301 } 302 want := `{"S":"B"}` 303 got := string(b) 304 if got != want { 305 t.Fatalf("Marshal: got %s want %s", got, want) 306 } 307 // Now check that the duplicate field, S, does not appear. 308 x := BugX{ 309 A: 23, 310 } 311 b, err = Marshal(x) 312 if err != nil { 313 t.Fatal("Marshal:", err) 314 } 315 want = `{"A":23}` 316 got = string(b) 317 if got != want { 318 t.Fatalf("Marshal: got %s want %s", got, want) 319 } 320 } 321 322 type BugD struct { // Same as BugA after tagging. 323 XXX string `json:"S"` 324 } 325 326 // BugD's tagged S field should dominate BugA's. 327 type BugY struct { 328 BugA 329 BugD 330 } 331 332 // Test that a field with a tag dominates untagged fields. 333 func TestTaggedFieldDominates(t *testing.T) { 334 v := BugY{ 335 BugA{"BugA"}, 336 BugD{"BugD"}, 337 } 338 b, err := Marshal(v) 339 if err != nil { 340 t.Fatal("Marshal:", err) 341 } 342 want := `{"S":"BugD"}` 343 got := string(b) 344 if got != want { 345 t.Fatalf("Marshal: got %s want %s", got, want) 346 } 347 } 348 349 // There are no tags here, so S should not appear. 350 type BugZ struct { 351 BugA 352 BugC 353 BugY // Contains a tagged S field through BugD; should not dominate. 354 } 355 356 func TestDuplicatedFieldDisappears(t *testing.T) { 357 v := BugZ{ 358 BugA{"BugA"}, 359 BugC{"BugC"}, 360 BugY{ 361 BugA{"nested BugA"}, 362 BugD{"nested BugD"}, 363 }, 364 } 365 b, err := Marshal(v) 366 if err != nil { 367 t.Fatal("Marshal:", err) 368 } 369 want := `{}` 370 got := string(b) 371 if got != want { 372 t.Fatalf("Marshal: got %s want %s", got, want) 373 } 374 } 375 376 func TestStringBytes(t *testing.T) { 377 // Test that encodeState.stringBytes and encodeState.string use the same encoding. 378 es := &encodeState{} 379 var r []rune 380 for i := '\u0000'; i <= unicode.MaxRune; i++ { 381 r = append(r, i) 382 } 383 s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too 384 _, err := es.string(s) 385 if err != nil { 386 t.Fatal(err) 387 } 388 389 esBytes := &encodeState{} 390 _, err = esBytes.stringBytes([]byte(s)) 391 if err != nil { 392 t.Fatal(err) 393 } 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("encodings differ at %#q vs %#q", enc, encBytes) 419 } 420 } 421 422 func TestIssue6458(t *testing.T) { 423 type Foo struct { 424 M RawMessage 425 } 426 x := Foo{RawMessage(`"foo"`)} 427 428 b, err := Marshal(&x) 429 if err != nil { 430 t.Fatal(err) 431 } 432 if want := `{"M":"foo"}`; string(b) != want { 433 t.Errorf("Marshal(&x) = %#q; want %#q", b, want) 434 } 435 436 b, err = Marshal(x) 437 if err != nil { 438 t.Fatal(err) 439 } 440 441 if want := `{"M":"ImZvbyI="}`; string(b) != want { 442 t.Errorf("Marshal(x) = %#q; want %#q", b, want) 443 } 444 } 445 446 func TestHTMLEscape(t *testing.T) { 447 var b, want bytes.Buffer 448 m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}` 449 want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`)) 450 HTMLEscape(&b, []byte(m)) 451 if !bytes.Equal(b.Bytes(), want.Bytes()) { 452 t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes()) 453 } 454 } 455 456 // golang.org/issue/8582 457 func TestEncodePointerString(t *testing.T) { 458 type stringPointer struct { 459 N *int64 `json:"n,string"` 460 } 461 var n int64 = 42 462 b, err := Marshal(stringPointer{N: &n}) 463 if err != nil { 464 t.Fatalf("Marshal: %v", err) 465 } 466 if got, want := string(b), `{"n":"42"}`; got != want { 467 t.Errorf("Marshal = %s, want %s", got, want) 468 } 469 var back stringPointer 470 err = Unmarshal(b, &back) 471 if err != nil { 472 t.Fatalf("Unmarshal: %v", err) 473 } 474 if back.N == nil { 475 t.Fatalf("Unmarshalled nil N field") 476 } 477 if *back.N != 42 { 478 t.Fatalf("*N = %d; want 42", *back.N) 479 } 480 } 481 482 var encodeStringTests = []struct { 483 in string 484 out string 485 }{ 486 {"\x00", `"\u0000"`}, 487 {"\x01", `"\u0001"`}, 488 {"\x02", `"\u0002"`}, 489 {"\x03", `"\u0003"`}, 490 {"\x04", `"\u0004"`}, 491 {"\x05", `"\u0005"`}, 492 {"\x06", `"\u0006"`}, 493 {"\x07", `"\u0007"`}, 494 {"\x08", `"\u0008"`}, 495 {"\x09", `"\t"`}, 496 {"\x0a", `"\n"`}, 497 {"\x0b", `"\u000b"`}, 498 {"\x0c", `"\u000c"`}, 499 {"\x0d", `"\r"`}, 500 {"\x0e", `"\u000e"`}, 501 {"\x0f", `"\u000f"`}, 502 {"\x10", `"\u0010"`}, 503 {"\x11", `"\u0011"`}, 504 {"\x12", `"\u0012"`}, 505 {"\x13", `"\u0013"`}, 506 {"\x14", `"\u0014"`}, 507 {"\x15", `"\u0015"`}, 508 {"\x16", `"\u0016"`}, 509 {"\x17", `"\u0017"`}, 510 {"\x18", `"\u0018"`}, 511 {"\x19", `"\u0019"`}, 512 {"\x1a", `"\u001a"`}, 513 {"\x1b", `"\u001b"`}, 514 {"\x1c", `"\u001c"`}, 515 {"\x1d", `"\u001d"`}, 516 {"\x1e", `"\u001e"`}, 517 {"\x1f", `"\u001f"`}, 518 } 519 520 func TestEncodeString(t *testing.T) { 521 for _, tt := range encodeStringTests { 522 b, err := Marshal(tt.in) 523 if err != nil { 524 t.Errorf("Marshal(%q): %v", tt.in, err) 525 continue 526 } 527 out := string(b) 528 if out != tt.out { 529 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out) 530 } 531 } 532 }