1// Copyright 2010 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 5package json 6 7import ( 8 "bytes" 9 "encoding" 10 "errors" 11 "fmt" 12 "image" 13 "math" 14 "math/big" 15 "net" 16 "reflect" 17 "slices" 18 "strconv" 19 "strings" 20 "testing" 21 "time" 22) 23 24type T struct { 25 X string 26 Y int 27 Z int `json:"-"` 28} 29 30type U struct { 31 Alphabet string `json:"alpha"` 32} 33 34type V struct { 35 F1 any 36 F2 int32 37 F3 Number 38 F4 *VOuter 39} 40 41type VOuter struct { 42 V V 43} 44 45type W struct { 46 S SS 47} 48 49type P struct { 50 PP PP 51} 52 53type PP struct { 54 T T 55 Ts []T 56} 57 58type SS string 59 60func (*SS) UnmarshalJSON(data []byte) error { 61 return &UnmarshalTypeError{Value: "number", Type: reflect.TypeFor[SS]()} 62} 63 64// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and 65// without UseNumber 66var ifaceNumAsFloat64 = map[string]any{ 67 "k1": float64(1), 68 "k2": "s", 69 "k3": []any{float64(1), float64(2.0), float64(3e-3)}, 70 "k4": map[string]any{"kk1": "s", "kk2": float64(2)}, 71} 72 73var ifaceNumAsNumber = map[string]any{ 74 "k1": Number("1"), 75 "k2": "s", 76 "k3": []any{Number("1"), Number("2.0"), Number("3e-3")}, 77 "k4": map[string]any{"kk1": "s", "kk2": Number("2")}, 78} 79 80type tx struct { 81 x int 82} 83 84type u8 uint8 85 86// A type that can unmarshal itself. 87 88type unmarshaler struct { 89 T bool 90} 91 92func (u *unmarshaler) UnmarshalJSON(b []byte) error { 93 *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called. 94 return nil 95} 96 97type ustruct struct { 98 M unmarshaler 99} 100 101type unmarshalerText struct { 102 A, B string 103} 104 105// needed for re-marshaling tests 106func (u unmarshalerText) MarshalText() ([]byte, error) { 107 return []byte(u.A + ":" + u.B), nil 108} 109 110func (u *unmarshalerText) UnmarshalText(b []byte) error { 111 pos := bytes.IndexByte(b, ':') 112 if pos == -1 { 113 return errors.New("missing separator") 114 } 115 u.A, u.B = string(b[:pos]), string(b[pos+1:]) 116 return nil 117} 118 119var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil) 120 121type ustructText struct { 122 M unmarshalerText 123} 124 125// u8marshal is an integer type that can marshal/unmarshal itself. 126type u8marshal uint8 127 128func (u8 u8marshal) MarshalText() ([]byte, error) { 129 return []byte(fmt.Sprintf("u%d", u8)), nil 130} 131 132var errMissingU8Prefix = errors.New("missing 'u' prefix") 133 134func (u8 *u8marshal) UnmarshalText(b []byte) error { 135 if !bytes.HasPrefix(b, []byte{'u'}) { 136 return errMissingU8Prefix 137 } 138 n, err := strconv.Atoi(string(b[1:])) 139 if err != nil { 140 return err 141 } 142 *u8 = u8marshal(n) 143 return nil 144} 145 146var _ encoding.TextUnmarshaler = (*u8marshal)(nil) 147 148var ( 149 umtrue = unmarshaler{true} 150 umslice = []unmarshaler{{true}} 151 umstruct = ustruct{unmarshaler{true}} 152 153 umtrueXY = unmarshalerText{"x", "y"} 154 umsliceXY = []unmarshalerText{{"x", "y"}} 155 umstructXY = ustructText{unmarshalerText{"x", "y"}} 156 157 ummapXY = map[unmarshalerText]bool{{"x", "y"}: true} 158) 159 160// Test data structures for anonymous fields. 161 162type Point struct { 163 Z int 164} 165 166type Top struct { 167 Level0 int 168 Embed0 169 *Embed0a 170 *Embed0b `json:"e,omitempty"` // treated as named 171 Embed0c `json:"-"` // ignored 172 Loop 173 Embed0p // has Point with X, Y, used 174 Embed0q // has Point with Z, used 175 embed // contains exported field 176} 177 178type Embed0 struct { 179 Level1a int // overridden by Embed0a's Level1a with json tag 180 Level1b int // used because Embed0a's Level1b is renamed 181 Level1c int // used because Embed0a's Level1c is ignored 182 Level1d int // annihilated by Embed0a's Level1d 183 Level1e int `json:"x"` // annihilated by Embed0a.Level1e 184} 185 186type Embed0a struct { 187 Level1a int `json:"Level1a,omitempty"` 188 Level1b int `json:"LEVEL1B,omitempty"` 189 Level1c int `json:"-"` 190 Level1d int // annihilated by Embed0's Level1d 191 Level1f int `json:"x"` // annihilated by Embed0's Level1e 192} 193 194type Embed0b Embed0 195 196type Embed0c Embed0 197 198type Embed0p struct { 199 image.Point 200} 201 202type Embed0q struct { 203 Point 204} 205 206type embed struct { 207 Q int 208} 209 210type Loop struct { 211 Loop1 int `json:",omitempty"` 212 Loop2 int `json:",omitempty"` 213 *Loop 214} 215 216// From reflect test: 217// The X in S6 and S7 annihilate, but they also block the X in S8.S9. 218type S5 struct { 219 S6 220 S7 221 S8 222} 223 224type S6 struct { 225 X int 226} 227 228type S7 S6 229 230type S8 struct { 231 S9 232} 233 234type S9 struct { 235 X int 236 Y int 237} 238 239// From reflect test: 240// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. 241type S10 struct { 242 S11 243 S12 244 S13 245} 246 247type S11 struct { 248 S6 249} 250 251type S12 struct { 252 S6 253} 254 255type S13 struct { 256 S8 257} 258 259type Ambig struct { 260 // Given "hello", the first match should win. 261 First int `json:"HELLO"` 262 Second int `json:"Hello"` 263} 264 265type XYZ struct { 266 X any 267 Y any 268 Z any 269} 270 271type unexportedWithMethods struct{} 272 273func (unexportedWithMethods) F() {} 274 275type byteWithMarshalJSON byte 276 277func (b byteWithMarshalJSON) MarshalJSON() ([]byte, error) { 278 return []byte(fmt.Sprintf(`"Z%.2x"`, byte(b))), nil 279} 280 281func (b *byteWithMarshalJSON) UnmarshalJSON(data []byte) error { 282 if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' { 283 return fmt.Errorf("bad quoted string") 284 } 285 i, err := strconv.ParseInt(string(data[2:4]), 16, 8) 286 if err != nil { 287 return fmt.Errorf("bad hex") 288 } 289 *b = byteWithMarshalJSON(i) 290 return nil 291} 292 293type byteWithPtrMarshalJSON byte 294 295func (b *byteWithPtrMarshalJSON) MarshalJSON() ([]byte, error) { 296 return byteWithMarshalJSON(*b).MarshalJSON() 297} 298 299func (b *byteWithPtrMarshalJSON) UnmarshalJSON(data []byte) error { 300 return (*byteWithMarshalJSON)(b).UnmarshalJSON(data) 301} 302 303type byteWithMarshalText byte 304 305func (b byteWithMarshalText) MarshalText() ([]byte, error) { 306 return []byte(fmt.Sprintf(`Z%.2x`, byte(b))), nil 307} 308 309func (b *byteWithMarshalText) UnmarshalText(data []byte) error { 310 if len(data) != 3 || data[0] != 'Z' { 311 return fmt.Errorf("bad quoted string") 312 } 313 i, err := strconv.ParseInt(string(data[1:3]), 16, 8) 314 if err != nil { 315 return fmt.Errorf("bad hex") 316 } 317 *b = byteWithMarshalText(i) 318 return nil 319} 320 321type byteWithPtrMarshalText byte 322 323func (b *byteWithPtrMarshalText) MarshalText() ([]byte, error) { 324 return byteWithMarshalText(*b).MarshalText() 325} 326 327func (b *byteWithPtrMarshalText) UnmarshalText(data []byte) error { 328 return (*byteWithMarshalText)(b).UnmarshalText(data) 329} 330 331type intWithMarshalJSON int 332 333func (b intWithMarshalJSON) MarshalJSON() ([]byte, error) { 334 return []byte(fmt.Sprintf(`"Z%.2x"`, int(b))), nil 335} 336 337func (b *intWithMarshalJSON) UnmarshalJSON(data []byte) error { 338 if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' { 339 return fmt.Errorf("bad quoted string") 340 } 341 i, err := strconv.ParseInt(string(data[2:4]), 16, 8) 342 if err != nil { 343 return fmt.Errorf("bad hex") 344 } 345 *b = intWithMarshalJSON(i) 346 return nil 347} 348 349type intWithPtrMarshalJSON int 350 351func (b *intWithPtrMarshalJSON) MarshalJSON() ([]byte, error) { 352 return intWithMarshalJSON(*b).MarshalJSON() 353} 354 355func (b *intWithPtrMarshalJSON) UnmarshalJSON(data []byte) error { 356 return (*intWithMarshalJSON)(b).UnmarshalJSON(data) 357} 358 359type intWithMarshalText int 360 361func (b intWithMarshalText) MarshalText() ([]byte, error) { 362 return []byte(fmt.Sprintf(`Z%.2x`, int(b))), nil 363} 364 365func (b *intWithMarshalText) UnmarshalText(data []byte) error { 366 if len(data) != 3 || data[0] != 'Z' { 367 return fmt.Errorf("bad quoted string") 368 } 369 i, err := strconv.ParseInt(string(data[1:3]), 16, 8) 370 if err != nil { 371 return fmt.Errorf("bad hex") 372 } 373 *b = intWithMarshalText(i) 374 return nil 375} 376 377type intWithPtrMarshalText int 378 379func (b *intWithPtrMarshalText) MarshalText() ([]byte, error) { 380 return intWithMarshalText(*b).MarshalText() 381} 382 383func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error { 384 return (*intWithMarshalText)(b).UnmarshalText(data) 385} 386 387type mapStringToStringData struct { 388 Data map[string]string `json:"data"` 389} 390 391type B struct { 392 B bool `json:",string"` 393} 394 395type DoublePtr struct { 396 I **int 397 J **int 398} 399 400var unmarshalTests = []struct { 401 CaseName 402 in string 403 ptr any // new(type) 404 out any 405 err error 406 useNumber bool 407 golden bool 408 disallowUnknownFields bool 409}{ 410 // basic types 411 {CaseName: Name(""), in: `true`, ptr: new(bool), out: true}, 412 {CaseName: Name(""), in: `1`, ptr: new(int), out: 1}, 413 {CaseName: Name(""), in: `1.2`, ptr: new(float64), out: 1.2}, 414 {CaseName: Name(""), in: `-5`, ptr: new(int16), out: int16(-5)}, 415 {CaseName: Name(""), in: `2`, ptr: new(Number), out: Number("2"), useNumber: true}, 416 {CaseName: Name(""), in: `2`, ptr: new(Number), out: Number("2")}, 417 {CaseName: Name(""), in: `2`, ptr: new(any), out: float64(2.0)}, 418 {CaseName: Name(""), in: `2`, ptr: new(any), out: Number("2"), useNumber: true}, 419 {CaseName: Name(""), in: `"a\u1234"`, ptr: new(string), out: "a\u1234"}, 420 {CaseName: Name(""), in: `"http:\/\/"`, ptr: new(string), out: "http://"}, 421 {CaseName: Name(""), in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"}, 422 {CaseName: Name(""), in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"}, 423 {CaseName: Name(""), in: "null", ptr: new(any), out: nil}, 424 {CaseName: Name(""), in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeFor[string](), 7, "T", "X"}}, 425 {CaseName: Name(""), in: `{"X": 23}`, ptr: new(T), out: T{}, err: &UnmarshalTypeError{"number", reflect.TypeFor[string](), 8, "T", "X"}}, 426 {CaseName: Name(""), in: `{"x": 1}`, ptr: new(tx), out: tx{}}, 427 {CaseName: Name(""), in: `{"x": 1}`, ptr: new(tx), out: tx{}}, 428 {CaseName: Name(""), in: `{"x": 1}`, ptr: new(tx), err: fmt.Errorf("json: unknown field \"x\""), disallowUnknownFields: true}, 429 {CaseName: Name(""), in: `{"S": 23}`, ptr: new(W), out: W{}, err: &UnmarshalTypeError{"number", reflect.TypeFor[SS](), 0, "W", "S"}}, 430 {CaseName: Name(""), in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}}, 431 {CaseName: Name(""), in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true}, 432 {CaseName: Name(""), in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(any), out: ifaceNumAsFloat64}, 433 {CaseName: Name(""), in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(any), out: ifaceNumAsNumber, useNumber: true}, 434 435 // raw values with whitespace 436 {CaseName: Name(""), in: "\n true ", ptr: new(bool), out: true}, 437 {CaseName: Name(""), in: "\t 1 ", ptr: new(int), out: 1}, 438 {CaseName: Name(""), in: "\r 1.2 ", ptr: new(float64), out: 1.2}, 439 {CaseName: Name(""), in: "\t -5 \n", ptr: new(int16), out: int16(-5)}, 440 {CaseName: Name(""), in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"}, 441 442 // Z has a "-" tag. 443 {CaseName: Name(""), in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}}, 444 {CaseName: Name(""), in: `{"Y": 1, "Z": 2}`, ptr: new(T), err: fmt.Errorf("json: unknown field \"Z\""), disallowUnknownFields: true}, 445 446 {CaseName: Name(""), in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}}, 447 {CaseName: Name(""), in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true}, 448 {CaseName: Name(""), in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}}, 449 {CaseName: Name(""), in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}}, 450 {CaseName: Name(""), in: `{"alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true}, 451 452 // syntax errors 453 {CaseName: Name(""), in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}}, 454 {CaseName: Name(""), in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}}, 455 {CaseName: Name(""), in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true}, 456 {CaseName: Name(""), in: `[2, 3`, err: &SyntaxError{msg: "unexpected end of JSON input", Offset: 5}}, 457 {CaseName: Name(""), in: `{"F3": -}`, ptr: new(V), out: V{F3: Number("-")}, err: &SyntaxError{msg: "invalid character '}' in numeric literal", Offset: 9}}, 458 459 // raw value errors 460 {CaseName: Name(""), in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, 461 {CaseName: Name(""), in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}}, 462 {CaseName: Name(""), in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, 463 {CaseName: Name(""), in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}}, 464 {CaseName: Name(""), in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, 465 {CaseName: Name(""), in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}}, 466 {CaseName: Name(""), in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}}, 467 {CaseName: Name(""), in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}}, 468 469 // array tests 470 {CaseName: Name(""), in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}}, 471 {CaseName: Name(""), in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}}, 472 {CaseName: Name(""), in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}}, 473 {CaseName: Name(""), in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")}, 474 475 // empty array to interface test 476 {CaseName: Name(""), in: `[]`, ptr: new([]any), out: []any{}}, 477 {CaseName: Name(""), in: `null`, ptr: new([]any), out: []any(nil)}, 478 {CaseName: Name(""), in: `{"T":[]}`, ptr: new(map[string]any), out: map[string]any{"T": []any{}}}, 479 {CaseName: Name(""), in: `{"T":null}`, ptr: new(map[string]any), out: map[string]any{"T": any(nil)}}, 480 481 // composite tests 482 {CaseName: Name(""), in: allValueIndent, ptr: new(All), out: allValue}, 483 {CaseName: Name(""), in: allValueCompact, ptr: new(All), out: allValue}, 484 {CaseName: Name(""), in: allValueIndent, ptr: new(*All), out: &allValue}, 485 {CaseName: Name(""), in: allValueCompact, ptr: new(*All), out: &allValue}, 486 {CaseName: Name(""), in: pallValueIndent, ptr: new(All), out: pallValue}, 487 {CaseName: Name(""), in: pallValueCompact, ptr: new(All), out: pallValue}, 488 {CaseName: Name(""), in: pallValueIndent, ptr: new(*All), out: &pallValue}, 489 {CaseName: Name(""), in: pallValueCompact, ptr: new(*All), out: &pallValue}, 490 491 // unmarshal interface test 492 {CaseName: Name(""), in: `{"T":false}`, ptr: new(unmarshaler), out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called 493 {CaseName: Name(""), in: `{"T":false}`, ptr: new(*unmarshaler), out: &umtrue}, 494 {CaseName: Name(""), in: `[{"T":false}]`, ptr: new([]unmarshaler), out: umslice}, 495 {CaseName: Name(""), in: `[{"T":false}]`, ptr: new(*[]unmarshaler), out: &umslice}, 496 {CaseName: Name(""), in: `{"M":{"T":"x:y"}}`, ptr: new(ustruct), out: umstruct}, 497 498 // UnmarshalText interface test 499 {CaseName: Name(""), in: `"x:y"`, ptr: new(unmarshalerText), out: umtrueXY}, 500 {CaseName: Name(""), in: `"x:y"`, ptr: new(*unmarshalerText), out: &umtrueXY}, 501 {CaseName: Name(""), in: `["x:y"]`, ptr: new([]unmarshalerText), out: umsliceXY}, 502 {CaseName: Name(""), in: `["x:y"]`, ptr: new(*[]unmarshalerText), out: &umsliceXY}, 503 {CaseName: Name(""), in: `{"M":"x:y"}`, ptr: new(ustructText), out: umstructXY}, 504 505 // integer-keyed map test 506 { 507 CaseName: Name(""), 508 in: `{"-1":"a","0":"b","1":"c"}`, 509 ptr: new(map[int]string), 510 out: map[int]string{-1: "a", 0: "b", 1: "c"}, 511 }, 512 { 513 CaseName: Name(""), 514 in: `{"0":"a","10":"c","9":"b"}`, 515 ptr: new(map[u8]string), 516 out: map[u8]string{0: "a", 9: "b", 10: "c"}, 517 }, 518 { 519 CaseName: Name(""), 520 in: `{"-9223372036854775808":"min","9223372036854775807":"max"}`, 521 ptr: new(map[int64]string), 522 out: map[int64]string{math.MinInt64: "min", math.MaxInt64: "max"}, 523 }, 524 { 525 CaseName: Name(""), 526 in: `{"18446744073709551615":"max"}`, 527 ptr: new(map[uint64]string), 528 out: map[uint64]string{math.MaxUint64: "max"}, 529 }, 530 { 531 CaseName: Name(""), 532 in: `{"0":false,"10":true}`, 533 ptr: new(map[uintptr]bool), 534 out: map[uintptr]bool{0: false, 10: true}, 535 }, 536 537 // Check that MarshalText and UnmarshalText take precedence 538 // over default integer handling in map keys. 539 { 540 CaseName: Name(""), 541 in: `{"u2":4}`, 542 ptr: new(map[u8marshal]int), 543 out: map[u8marshal]int{2: 4}, 544 }, 545 { 546 CaseName: Name(""), 547 in: `{"2":4}`, 548 ptr: new(map[u8marshal]int), 549 err: errMissingU8Prefix, 550 }, 551 552 // integer-keyed map errors 553 { 554 CaseName: Name(""), 555 in: `{"abc":"abc"}`, 556 ptr: new(map[int]string), 557 err: &UnmarshalTypeError{Value: "number abc", Type: reflect.TypeFor[int](), Offset: 2}, 558 }, 559 { 560 CaseName: Name(""), 561 in: `{"256":"abc"}`, 562 ptr: new(map[uint8]string), 563 err: &UnmarshalTypeError{Value: "number 256", Type: reflect.TypeFor[uint8](), Offset: 2}, 564 }, 565 { 566 CaseName: Name(""), 567 in: `{"128":"abc"}`, 568 ptr: new(map[int8]string), 569 err: &UnmarshalTypeError{Value: "number 128", Type: reflect.TypeFor[int8](), Offset: 2}, 570 }, 571 { 572 CaseName: Name(""), 573 in: `{"-1":"abc"}`, 574 ptr: new(map[uint8]string), 575 err: &UnmarshalTypeError{Value: "number -1", Type: reflect.TypeFor[uint8](), Offset: 2}, 576 }, 577 { 578 CaseName: Name(""), 579 in: `{"F":{"a":2,"3":4}}`, 580 ptr: new(map[string]map[int]int), 581 err: &UnmarshalTypeError{Value: "number a", Type: reflect.TypeFor[int](), Offset: 7}, 582 }, 583 { 584 CaseName: Name(""), 585 in: `{"F":{"a":2,"3":4}}`, 586 ptr: new(map[string]map[uint]int), 587 err: &UnmarshalTypeError{Value: "number a", Type: reflect.TypeFor[uint](), Offset: 7}, 588 }, 589 590 // Map keys can be encoding.TextUnmarshalers. 591 {CaseName: Name(""), in: `{"x:y":true}`, ptr: new(map[unmarshalerText]bool), out: ummapXY}, 592 // If multiple values for the same key exists, only the most recent value is used. 593 {CaseName: Name(""), in: `{"x:y":false,"x:y":true}`, ptr: new(map[unmarshalerText]bool), out: ummapXY}, 594 595 { 596 CaseName: Name(""), 597 in: `{ 598 "Level0": 1, 599 "Level1b": 2, 600 "Level1c": 3, 601 "x": 4, 602 "Level1a": 5, 603 "LEVEL1B": 6, 604 "e": { 605 "Level1a": 8, 606 "Level1b": 9, 607 "Level1c": 10, 608 "Level1d": 11, 609 "x": 12 610 }, 611 "Loop1": 13, 612 "Loop2": 14, 613 "X": 15, 614 "Y": 16, 615 "Z": 17, 616 "Q": 18 617 }`, 618 ptr: new(Top), 619 out: Top{ 620 Level0: 1, 621 Embed0: Embed0{ 622 Level1b: 2, 623 Level1c: 3, 624 }, 625 Embed0a: &Embed0a{ 626 Level1a: 5, 627 Level1b: 6, 628 }, 629 Embed0b: &Embed0b{ 630 Level1a: 8, 631 Level1b: 9, 632 Level1c: 10, 633 Level1d: 11, 634 Level1e: 12, 635 }, 636 Loop: Loop{ 637 Loop1: 13, 638 Loop2: 14, 639 }, 640 Embed0p: Embed0p{ 641 Point: image.Point{X: 15, Y: 16}, 642 }, 643 Embed0q: Embed0q{ 644 Point: Point{Z: 17}, 645 }, 646 embed: embed{ 647 Q: 18, 648 }, 649 }, 650 }, 651 { 652 CaseName: Name(""), 653 in: `{"hello": 1}`, 654 ptr: new(Ambig), 655 out: Ambig{First: 1}, 656 }, 657 658 { 659 CaseName: Name(""), 660 in: `{"X": 1,"Y":2}`, 661 ptr: new(S5), 662 out: S5{S8: S8{S9: S9{Y: 2}}}, 663 }, 664 { 665 CaseName: Name(""), 666 in: `{"X": 1,"Y":2}`, 667 ptr: new(S5), 668 err: fmt.Errorf("json: unknown field \"X\""), 669 disallowUnknownFields: true, 670 }, 671 { 672 CaseName: Name(""), 673 in: `{"X": 1,"Y":2}`, 674 ptr: new(S10), 675 out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}}, 676 }, 677 { 678 CaseName: Name(""), 679 in: `{"X": 1,"Y":2}`, 680 ptr: new(S10), 681 err: fmt.Errorf("json: unknown field \"X\""), 682 disallowUnknownFields: true, 683 }, 684 { 685 CaseName: Name(""), 686 in: `{"I": 0, "I": null, "J": null}`, 687 ptr: new(DoublePtr), 688 out: DoublePtr{I: nil, J: nil}, 689 }, 690 691 // invalid UTF-8 is coerced to valid UTF-8. 692 { 693 CaseName: Name(""), 694 in: "\"hello\xffworld\"", 695 ptr: new(string), 696 out: "hello\ufffdworld", 697 }, 698 { 699 CaseName: Name(""), 700 in: "\"hello\xc2\xc2world\"", 701 ptr: new(string), 702 out: "hello\ufffd\ufffdworld", 703 }, 704 { 705 CaseName: Name(""), 706 in: "\"hello\xc2\xffworld\"", 707 ptr: new(string), 708 out: "hello\ufffd\ufffdworld", 709 }, 710 { 711 CaseName: Name(""), 712 in: "\"hello\\ud800world\"", 713 ptr: new(string), 714 out: "hello\ufffdworld", 715 }, 716 { 717 CaseName: Name(""), 718 in: "\"hello\\ud800\\ud800world\"", 719 ptr: new(string), 720 out: "hello\ufffd\ufffdworld", 721 }, 722 { 723 CaseName: Name(""), 724 in: "\"hello\\ud800\\ud800world\"", 725 ptr: new(string), 726 out: "hello\ufffd\ufffdworld", 727 }, 728 { 729 CaseName: Name(""), 730 in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"", 731 ptr: new(string), 732 out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld", 733 }, 734 735 // Used to be issue 8305, but time.Time implements encoding.TextUnmarshaler so this works now. 736 { 737 CaseName: Name(""), 738 in: `{"2009-11-10T23:00:00Z": "hello world"}`, 739 ptr: new(map[time.Time]string), 740 out: map[time.Time]string{time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC): "hello world"}, 741 }, 742 743 // issue 8305 744 { 745 CaseName: Name(""), 746 in: `{"2009-11-10T23:00:00Z": "hello world"}`, 747 ptr: new(map[Point]string), 748 err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeFor[map[Point]string](), Offset: 1}, 749 }, 750 { 751 CaseName: Name(""), 752 in: `{"asdf": "hello world"}`, 753 ptr: new(map[unmarshaler]string), 754 err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeFor[map[unmarshaler]string](), Offset: 1}, 755 }, 756 757 // related to issue 13783. 758 // Go 1.7 changed marshaling a slice of typed byte to use the methods on the byte type, 759 // similar to marshaling a slice of typed int. 760 // These tests check that, assuming the byte type also has valid decoding methods, 761 // either the old base64 string encoding or the new per-element encoding can be 762 // successfully unmarshaled. The custom unmarshalers were accessible in earlier 763 // versions of Go, even though the custom marshaler was not. 764 { 765 CaseName: Name(""), 766 in: `"AQID"`, 767 ptr: new([]byteWithMarshalJSON), 768 out: []byteWithMarshalJSON{1, 2, 3}, 769 }, 770 { 771 CaseName: Name(""), 772 in: `["Z01","Z02","Z03"]`, 773 ptr: new([]byteWithMarshalJSON), 774 out: []byteWithMarshalJSON{1, 2, 3}, 775 golden: true, 776 }, 777 { 778 CaseName: Name(""), 779 in: `"AQID"`, 780 ptr: new([]byteWithMarshalText), 781 out: []byteWithMarshalText{1, 2, 3}, 782 }, 783 { 784 CaseName: Name(""), 785 in: `["Z01","Z02","Z03"]`, 786 ptr: new([]byteWithMarshalText), 787 out: []byteWithMarshalText{1, 2, 3}, 788 golden: true, 789 }, 790 { 791 CaseName: Name(""), 792 in: `"AQID"`, 793 ptr: new([]byteWithPtrMarshalJSON), 794 out: []byteWithPtrMarshalJSON{1, 2, 3}, 795 }, 796 { 797 CaseName: Name(""), 798 in: `["Z01","Z02","Z03"]`, 799 ptr: new([]byteWithPtrMarshalJSON), 800 out: []byteWithPtrMarshalJSON{1, 2, 3}, 801 golden: true, 802 }, 803 { 804 CaseName: Name(""), 805 in: `"AQID"`, 806 ptr: new([]byteWithPtrMarshalText), 807 out: []byteWithPtrMarshalText{1, 2, 3}, 808 }, 809 { 810 CaseName: Name(""), 811 in: `["Z01","Z02","Z03"]`, 812 ptr: new([]byteWithPtrMarshalText), 813 out: []byteWithPtrMarshalText{1, 2, 3}, 814 golden: true, 815 }, 816 817 // ints work with the marshaler but not the base64 []byte case 818 { 819 CaseName: Name(""), 820 in: `["Z01","Z02","Z03"]`, 821 ptr: new([]intWithMarshalJSON), 822 out: []intWithMarshalJSON{1, 2, 3}, 823 golden: true, 824 }, 825 { 826 CaseName: Name(""), 827 in: `["Z01","Z02","Z03"]`, 828 ptr: new([]intWithMarshalText), 829 out: []intWithMarshalText{1, 2, 3}, 830 golden: true, 831 }, 832 { 833 CaseName: Name(""), 834 in: `["Z01","Z02","Z03"]`, 835 ptr: new([]intWithPtrMarshalJSON), 836 out: []intWithPtrMarshalJSON{1, 2, 3}, 837 golden: true, 838 }, 839 { 840 CaseName: Name(""), 841 in: `["Z01","Z02","Z03"]`, 842 ptr: new([]intWithPtrMarshalText), 843 out: []intWithPtrMarshalText{1, 2, 3}, 844 golden: true, 845 }, 846 847 {CaseName: Name(""), in: `0.000001`, ptr: new(float64), out: 0.000001, golden: true}, 848 {CaseName: Name(""), in: `1e-7`, ptr: new(float64), out: 1e-7, golden: true}, 849 {CaseName: Name(""), in: `100000000000000000000`, ptr: new(float64), out: 100000000000000000000.0, golden: true}, 850 {CaseName: Name(""), in: `1e+21`, ptr: new(float64), out: 1e21, golden: true}, 851 {CaseName: Name(""), in: `-0.000001`, ptr: new(float64), out: -0.000001, golden: true}, 852 {CaseName: Name(""), in: `-1e-7`, ptr: new(float64), out: -1e-7, golden: true}, 853 {CaseName: Name(""), in: `-100000000000000000000`, ptr: new(float64), out: -100000000000000000000.0, golden: true}, 854 {CaseName: Name(""), in: `-1e+21`, ptr: new(float64), out: -1e21, golden: true}, 855 {CaseName: Name(""), in: `999999999999999900000`, ptr: new(float64), out: 999999999999999900000.0, golden: true}, 856 {CaseName: Name(""), in: `9007199254740992`, ptr: new(float64), out: 9007199254740992.0, golden: true}, 857 {CaseName: Name(""), in: `9007199254740993`, ptr: new(float64), out: 9007199254740992.0, golden: false}, 858 859 { 860 CaseName: Name(""), 861 in: `{"V": {"F2": "hello"}}`, 862 ptr: new(VOuter), 863 err: &UnmarshalTypeError{ 864 Value: "string", 865 Struct: "V", 866 Field: "V.F2", 867 Type: reflect.TypeFor[int32](), 868 Offset: 20, 869 }, 870 }, 871 { 872 CaseName: Name(""), 873 in: `{"V": {"F4": {}, "F2": "hello"}}`, 874 ptr: new(VOuter), 875 err: &UnmarshalTypeError{ 876 Value: "string", 877 Struct: "V", 878 Field: "V.F2", 879 Type: reflect.TypeFor[int32](), 880 Offset: 30, 881 }, 882 }, 883 884 // issue 15146. 885 // invalid inputs in wrongStringTests below. 886 {CaseName: Name(""), in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true}, 887 {CaseName: Name(""), in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true}, 888 {CaseName: Name(""), in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "maybe" into bool`)}, 889 {CaseName: Name(""), in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "tru" into bool`)}, 890 {CaseName: Name(""), in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)}, 891 {CaseName: Name(""), in: `{"B": "null"}`, ptr: new(B), out: B{false}}, 892 {CaseName: Name(""), in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)}, 893 {CaseName: Name(""), in: `{"B": [2, 3]}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal unquoted value into bool`)}, 894 895 // additional tests for disallowUnknownFields 896 { 897 CaseName: Name(""), 898 in: `{ 899 "Level0": 1, 900 "Level1b": 2, 901 "Level1c": 3, 902 "x": 4, 903 "Level1a": 5, 904 "LEVEL1B": 6, 905 "e": { 906 "Level1a": 8, 907 "Level1b": 9, 908 "Level1c": 10, 909 "Level1d": 11, 910 "x": 12 911 }, 912 "Loop1": 13, 913 "Loop2": 14, 914 "X": 15, 915 "Y": 16, 916 "Z": 17, 917 "Q": 18, 918 "extra": true 919 }`, 920 ptr: new(Top), 921 err: fmt.Errorf("json: unknown field \"extra\""), 922 disallowUnknownFields: true, 923 }, 924 { 925 CaseName: Name(""), 926 in: `{ 927 "Level0": 1, 928 "Level1b": 2, 929 "Level1c": 3, 930 "x": 4, 931 "Level1a": 5, 932 "LEVEL1B": 6, 933 "e": { 934 "Level1a": 8, 935 "Level1b": 9, 936 "Level1c": 10, 937 "Level1d": 11, 938 "x": 12, 939 "extra": null 940 }, 941 "Loop1": 13, 942 "Loop2": 14, 943 "X": 15, 944 "Y": 16, 945 "Z": 17, 946 "Q": 18 947 }`, 948 ptr: new(Top), 949 err: fmt.Errorf("json: unknown field \"extra\""), 950 disallowUnknownFields: true, 951 }, 952 // issue 26444 953 // UnmarshalTypeError without field & struct values 954 { 955 CaseName: Name(""), 956 in: `{"data":{"test1": "bob", "test2": 123}}`, 957 ptr: new(mapStringToStringData), 958 err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeFor[string](), Offset: 37, Struct: "mapStringToStringData", Field: "data"}, 959 }, 960 { 961 CaseName: Name(""), 962 in: `{"data":{"test1": 123, "test2": "bob"}}`, 963 ptr: new(mapStringToStringData), 964 err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeFor[string](), Offset: 21, Struct: "mapStringToStringData", Field: "data"}, 965 }, 966 967 // trying to decode JSON arrays or objects via TextUnmarshaler 968 { 969 CaseName: Name(""), 970 in: `[1, 2, 3]`, 971 ptr: new(MustNotUnmarshalText), 972 err: &UnmarshalTypeError{Value: "array", Type: reflect.TypeFor[*MustNotUnmarshalText](), Offset: 1}, 973 }, 974 { 975 CaseName: Name(""), 976 in: `{"foo": "bar"}`, 977 ptr: new(MustNotUnmarshalText), 978 err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeFor[*MustNotUnmarshalText](), Offset: 1}, 979 }, 980 // #22369 981 { 982 CaseName: Name(""), 983 in: `{"PP": {"T": {"Y": "bad-type"}}}`, 984 ptr: new(P), 985 err: &UnmarshalTypeError{ 986 Value: "string", 987 Struct: "T", 988 Field: "PP.T.Y", 989 Type: reflect.TypeFor[int](), 990 Offset: 29, 991 }, 992 }, 993 { 994 CaseName: Name(""), 995 in: `{"Ts": [{"Y": 1}, {"Y": 2}, {"Y": "bad-type"}]}`, 996 ptr: new(PP), 997 err: &UnmarshalTypeError{ 998 Value: "string", 999 Struct: "T", 1000 Field: "Ts.Y", 1001 Type: reflect.TypeFor[int](), 1002 Offset: 29, 1003 }, 1004 }, 1005 // #14702 1006 { 1007 CaseName: Name(""), 1008 in: `invalid`, 1009 ptr: new(Number), 1010 err: &SyntaxError{ 1011 msg: "invalid character 'i' looking for beginning of value", 1012 Offset: 1, 1013 }, 1014 }, 1015 { 1016 CaseName: Name(""), 1017 in: `"invalid"`, 1018 ptr: new(Number), 1019 err: fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", `"invalid"`), 1020 }, 1021 { 1022 CaseName: Name(""), 1023 in: `{"A":"invalid"}`, 1024 ptr: new(struct{ A Number }), 1025 err: fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", `"invalid"`), 1026 }, 1027 { 1028 CaseName: Name(""), 1029 in: `{"A":"invalid"}`, 1030 ptr: new(struct { 1031 A Number `json:",string"` 1032 }), 1033 err: fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into json.Number", `invalid`), 1034 }, 1035 { 1036 CaseName: Name(""), 1037 in: `{"A":"invalid"}`, 1038 ptr: new(map[string]Number), 1039 err: fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", `"invalid"`), 1040 }, 1041} 1042 1043func TestMarshal(t *testing.T) { 1044 b, err := Marshal(allValue) 1045 if err != nil { 1046 t.Fatalf("Marshal error: %v", err) 1047 } 1048 if string(b) != allValueCompact { 1049 t.Errorf("Marshal:") 1050 diff(t, b, []byte(allValueCompact)) 1051 return 1052 } 1053 1054 b, err = Marshal(pallValue) 1055 if err != nil { 1056 t.Fatalf("Marshal error: %v", err) 1057 } 1058 if string(b) != pallValueCompact { 1059 t.Errorf("Marshal:") 1060 diff(t, b, []byte(pallValueCompact)) 1061 return 1062 } 1063} 1064 1065func TestMarshalInvalidUTF8(t *testing.T) { 1066 tests := []struct { 1067 CaseName 1068 in string 1069 want string 1070 }{ 1071 {Name(""), "hello\xffworld", `"hello\ufffdworld"`}, 1072 {Name(""), "", `""`}, 1073 {Name(""), "\xff", `"\ufffd"`}, 1074 {Name(""), "\xff\xff", `"\ufffd\ufffd"`}, 1075 {Name(""), "a\xffb", `"a\ufffdb"`}, 1076 {Name(""), "\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`}, 1077 } 1078 for _, tt := range tests { 1079 t.Run(tt.Name, func(t *testing.T) { 1080 got, err := Marshal(tt.in) 1081 if string(got) != tt.want || err != nil { 1082 t.Errorf("%s: Marshal(%q):\n\tgot: (%q, %v)\n\twant: (%q, nil)", tt.Where, tt.in, got, err, tt.want) 1083 } 1084 }) 1085 } 1086} 1087 1088func TestMarshalNumberZeroVal(t *testing.T) { 1089 var n Number 1090 out, err := Marshal(n) 1091 if err != nil { 1092 t.Fatalf("Marshal error: %v", err) 1093 } 1094 got := string(out) 1095 if got != "0" { 1096 t.Fatalf("Marshal: got %s, want 0", got) 1097 } 1098} 1099 1100func TestMarshalEmbeds(t *testing.T) { 1101 top := &Top{ 1102 Level0: 1, 1103 Embed0: Embed0{ 1104 Level1b: 2, 1105 Level1c: 3, 1106 }, 1107 Embed0a: &Embed0a{ 1108 Level1a: 5, 1109 Level1b: 6, 1110 }, 1111 Embed0b: &Embed0b{ 1112 Level1a: 8, 1113 Level1b: 9, 1114 Level1c: 10, 1115 Level1d: 11, 1116 Level1e: 12, 1117 }, 1118 Loop: Loop{ 1119 Loop1: 13, 1120 Loop2: 14, 1121 }, 1122 Embed0p: Embed0p{ 1123 Point: image.Point{X: 15, Y: 16}, 1124 }, 1125 Embed0q: Embed0q{ 1126 Point: Point{Z: 17}, 1127 }, 1128 embed: embed{ 1129 Q: 18, 1130 }, 1131 } 1132 got, err := Marshal(top) 1133 if err != nil { 1134 t.Fatalf("Marshal error: %v", err) 1135 } 1136 want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}" 1137 if string(got) != want { 1138 t.Errorf("Marshal:\n\tgot: %s\n\twant: %s", got, want) 1139 } 1140} 1141 1142func equalError(a, b error) bool { 1143 if a == nil || b == nil { 1144 return a == nil && b == nil 1145 } 1146 return a.Error() == b.Error() 1147} 1148 1149func TestUnmarshal(t *testing.T) { 1150 for _, tt := range unmarshalTests { 1151 t.Run(tt.Name, func(t *testing.T) { 1152 in := []byte(tt.in) 1153 var scan scanner 1154 if err := checkValid(in, &scan); err != nil { 1155 if !equalError(err, tt.err) { 1156 t.Fatalf("%s: checkValid error: %#v", tt.Where, err) 1157 } 1158 } 1159 if tt.ptr == nil { 1160 return 1161 } 1162 1163 typ := reflect.TypeOf(tt.ptr) 1164 if typ.Kind() != reflect.Pointer { 1165 t.Fatalf("%s: unmarshalTest.ptr %T is not a pointer type", tt.Where, tt.ptr) 1166 } 1167 typ = typ.Elem() 1168 1169 // v = new(right-type) 1170 v := reflect.New(typ) 1171 1172 if !reflect.DeepEqual(tt.ptr, v.Interface()) { 1173 // There's no reason for ptr to point to non-zero data, 1174 // as we decode into new(right-type), so the data is 1175 // discarded. 1176 // This can easily mean tests that silently don't test 1177 // what they should. To test decoding into existing 1178 // data, see TestPrefilled. 1179 t.Fatalf("%s: unmarshalTest.ptr %#v is not a pointer to a zero value", tt.Where, tt.ptr) 1180 } 1181 1182 dec := NewDecoder(bytes.NewReader(in)) 1183 if tt.useNumber { 1184 dec.UseNumber() 1185 } 1186 if tt.disallowUnknownFields { 1187 dec.DisallowUnknownFields() 1188 } 1189 if err := dec.Decode(v.Interface()); !equalError(err, tt.err) { 1190 t.Fatalf("%s: Decode error:\n\tgot: %v\n\twant: %v", tt.Where, err, tt.err) 1191 } else if err != nil { 1192 return 1193 } 1194 if got := v.Elem().Interface(); !reflect.DeepEqual(got, tt.out) { 1195 gotJSON, _ := Marshal(got) 1196 wantJSON, _ := Marshal(tt.out) 1197 t.Fatalf("%s: Decode:\n\tgot: %#+v\n\twant: %#+v\n\n\tgotJSON: %s\n\twantJSON: %s", tt.Where, got, tt.out, gotJSON, wantJSON) 1198 } 1199 1200 // Check round trip also decodes correctly. 1201 if tt.err == nil { 1202 enc, err := Marshal(v.Interface()) 1203 if err != nil { 1204 t.Fatalf("%s: Marshal error after roundtrip: %v", tt.Where, err) 1205 } 1206 if tt.golden && !bytes.Equal(enc, in) { 1207 t.Errorf("%s: Marshal:\n\tgot: %s\n\twant: %s", tt.Where, enc, in) 1208 } 1209 vv := reflect.New(reflect.TypeOf(tt.ptr).Elem()) 1210 dec = NewDecoder(bytes.NewReader(enc)) 1211 if tt.useNumber { 1212 dec.UseNumber() 1213 } 1214 if err := dec.Decode(vv.Interface()); err != nil { 1215 t.Fatalf("%s: Decode(%#q) error after roundtrip: %v", tt.Where, enc, err) 1216 } 1217 if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) { 1218 t.Fatalf("%s: Decode:\n\tgot: %#+v\n\twant: %#+v\n\n\tgotJSON: %s\n\twantJSON: %s", 1219 tt.Where, v.Elem().Interface(), vv.Elem().Interface(), 1220 stripWhitespace(string(enc)), stripWhitespace(string(in))) 1221 } 1222 } 1223 }) 1224 } 1225} 1226 1227func TestUnmarshalMarshal(t *testing.T) { 1228 initBig() 1229 var v any 1230 if err := Unmarshal(jsonBig, &v); err != nil { 1231 t.Fatalf("Unmarshal error: %v", err) 1232 } 1233 b, err := Marshal(v) 1234 if err != nil { 1235 t.Fatalf("Marshal error: %v", err) 1236 } 1237 if !bytes.Equal(jsonBig, b) { 1238 t.Errorf("Marshal:") 1239 diff(t, b, jsonBig) 1240 return 1241 } 1242} 1243 1244// Independent of Decode, basic coverage of the accessors in Number 1245func TestNumberAccessors(t *testing.T) { 1246 tests := []struct { 1247 CaseName 1248 in string 1249 i int64 1250 intErr string 1251 f float64 1252 floatErr string 1253 }{ 1254 {CaseName: Name(""), in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1}, 1255 {CaseName: Name(""), in: "-12", i: -12, f: -12.0}, 1256 {CaseName: Name(""), in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"}, 1257 } 1258 for _, tt := range tests { 1259 t.Run(tt.Name, func(t *testing.T) { 1260 n := Number(tt.in) 1261 if got := n.String(); got != tt.in { 1262 t.Errorf("%s: Number(%q).String() = %s, want %s", tt.Where, tt.in, got, tt.in) 1263 } 1264 if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i { 1265 t.Errorf("%s: Number(%q).Int64() = %d, want %d", tt.Where, tt.in, i, tt.i) 1266 } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) { 1267 t.Errorf("%s: Number(%q).Int64() error:\n\tgot: %v\n\twant: %v", tt.Where, tt.in, err, tt.intErr) 1268 } 1269 if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f { 1270 t.Errorf("%s: Number(%q).Float64() = %g, want %g", tt.Where, tt.in, f, tt.f) 1271 } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) { 1272 t.Errorf("%s: Number(%q).Float64() error:\n\tgot %v\n\twant: %v", tt.Where, tt.in, err, tt.floatErr) 1273 } 1274 }) 1275 } 1276} 1277 1278func TestLargeByteSlice(t *testing.T) { 1279 s0 := make([]byte, 2000) 1280 for i := range s0 { 1281 s0[i] = byte(i) 1282 } 1283 b, err := Marshal(s0) 1284 if err != nil { 1285 t.Fatalf("Marshal error: %v", err) 1286 } 1287 var s1 []byte 1288 if err := Unmarshal(b, &s1); err != nil { 1289 t.Fatalf("Unmarshal error: %v", err) 1290 } 1291 if !bytes.Equal(s0, s1) { 1292 t.Errorf("Marshal:") 1293 diff(t, s0, s1) 1294 } 1295} 1296 1297type Xint struct { 1298 X int 1299} 1300 1301func TestUnmarshalInterface(t *testing.T) { 1302 var xint Xint 1303 var i any = &xint 1304 if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil { 1305 t.Fatalf("Unmarshal error: %v", err) 1306 } 1307 if xint.X != 1 { 1308 t.Fatalf("xint.X = %d, want 1", xint.X) 1309 } 1310} 1311 1312func TestUnmarshalPtrPtr(t *testing.T) { 1313 var xint Xint 1314 pxint := &xint 1315 if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil { 1316 t.Fatalf("Unmarshal: %v", err) 1317 } 1318 if xint.X != 1 { 1319 t.Fatalf("xint.X = %d, want 1", xint.X) 1320 } 1321} 1322 1323func TestEscape(t *testing.T) { 1324 const input = `"foobar"<html>` + " [\u2028 \u2029]" 1325 const want = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"` 1326 got, err := Marshal(input) 1327 if err != nil { 1328 t.Fatalf("Marshal error: %v", err) 1329 } 1330 if string(got) != want { 1331 t.Errorf("Marshal(%#q):\n\tgot: %s\n\twant: %s", input, got, want) 1332 } 1333} 1334 1335// If people misuse the ,string modifier, the error message should be 1336// helpful, telling the user that they're doing it wrong. 1337func TestErrorMessageFromMisusedString(t *testing.T) { 1338 // WrongString is a struct that's misusing the ,string modifier. 1339 type WrongString struct { 1340 Message string `json:"result,string"` 1341 } 1342 tests := []struct { 1343 CaseName 1344 in, err string 1345 }{ 1346 {Name(""), `{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`}, 1347 {Name(""), `{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`}, 1348 {Name(""), `{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`}, 1349 {Name(""), `{"result":123}`, `json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string`}, 1350 {Name(""), `{"result":"\""}`, `json: invalid use of ,string struct tag, trying to unmarshal "\"" into string`}, 1351 {Name(""), `{"result":"\"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "\"foo" into string`}, 1352 } 1353 for _, tt := range tests { 1354 t.Run(tt.Name, func(t *testing.T) { 1355 r := strings.NewReader(tt.in) 1356 var s WrongString 1357 err := NewDecoder(r).Decode(&s) 1358 got := fmt.Sprintf("%v", err) 1359 if got != tt.err { 1360 t.Errorf("%s: Decode error:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.err) 1361 } 1362 }) 1363 } 1364} 1365 1366type All struct { 1367 Bool bool 1368 Int int 1369 Int8 int8 1370 Int16 int16 1371 Int32 int32 1372 Int64 int64 1373 Uint uint 1374 Uint8 uint8 1375 Uint16 uint16 1376 Uint32 uint32 1377 Uint64 uint64 1378 Uintptr uintptr 1379 Float32 float32 1380 Float64 float64 1381 1382 Foo string `json:"bar"` 1383 Foo2 string `json:"bar2,dummyopt"` 1384 1385 IntStr int64 `json:",string"` 1386 UintptrStr uintptr `json:",string"` 1387 1388 PBool *bool 1389 PInt *int 1390 PInt8 *int8 1391 PInt16 *int16 1392 PInt32 *int32 1393 PInt64 *int64 1394 PUint *uint 1395 PUint8 *uint8 1396 PUint16 *uint16 1397 PUint32 *uint32 1398 PUint64 *uint64 1399 PUintptr *uintptr 1400 PFloat32 *float32 1401 PFloat64 *float64 1402 1403 String string 1404 PString *string 1405 1406 Map map[string]Small 1407 MapP map[string]*Small 1408 PMap *map[string]Small 1409 PMapP *map[string]*Small 1410 1411 EmptyMap map[string]Small 1412 NilMap map[string]Small 1413 1414 Slice []Small 1415 SliceP []*Small 1416 PSlice *[]Small 1417 PSliceP *[]*Small 1418 1419 EmptySlice []Small 1420 NilSlice []Small 1421 1422 StringSlice []string 1423 ByteSlice []byte 1424 1425 Small Small 1426 PSmall *Small 1427 PPSmall **Small 1428 1429 Interface any 1430 PInterface *any 1431 1432 unexported int 1433} 1434 1435type Small struct { 1436 Tag string 1437} 1438 1439var allValue = All{ 1440 Bool: true, 1441 Int: 2, 1442 Int8: 3, 1443 Int16: 4, 1444 Int32: 5, 1445 Int64: 6, 1446 Uint: 7, 1447 Uint8: 8, 1448 Uint16: 9, 1449 Uint32: 10, 1450 Uint64: 11, 1451 Uintptr: 12, 1452 Float32: 14.1, 1453 Float64: 15.1, 1454 Foo: "foo", 1455 Foo2: "foo2", 1456 IntStr: 42, 1457 UintptrStr: 44, 1458 String: "16", 1459 Map: map[string]Small{ 1460 "17": {Tag: "tag17"}, 1461 "18": {Tag: "tag18"}, 1462 }, 1463 MapP: map[string]*Small{ 1464 "19": {Tag: "tag19"}, 1465 "20": nil, 1466 }, 1467 EmptyMap: map[string]Small{}, 1468 Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}}, 1469 SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}}, 1470 EmptySlice: []Small{}, 1471 StringSlice: []string{"str24", "str25", "str26"}, 1472 ByteSlice: []byte{27, 28, 29}, 1473 Small: Small{Tag: "tag30"}, 1474 PSmall: &Small{Tag: "tag31"}, 1475 Interface: 5.2, 1476} 1477 1478var pallValue = All{ 1479 PBool: &allValue.Bool, 1480 PInt: &allValue.Int, 1481 PInt8: &allValue.Int8, 1482 PInt16: &allValue.Int16, 1483 PInt32: &allValue.Int32, 1484 PInt64: &allValue.Int64, 1485 PUint: &allValue.Uint, 1486 PUint8: &allValue.Uint8, 1487 PUint16: &allValue.Uint16, 1488 PUint32: &allValue.Uint32, 1489 PUint64: &allValue.Uint64, 1490 PUintptr: &allValue.Uintptr, 1491 PFloat32: &allValue.Float32, 1492 PFloat64: &allValue.Float64, 1493 PString: &allValue.String, 1494 PMap: &allValue.Map, 1495 PMapP: &allValue.MapP, 1496 PSlice: &allValue.Slice, 1497 PSliceP: &allValue.SliceP, 1498 PPSmall: &allValue.PSmall, 1499 PInterface: &allValue.Interface, 1500} 1501 1502var allValueIndent = `{ 1503 "Bool": true, 1504 "Int": 2, 1505 "Int8": 3, 1506 "Int16": 4, 1507 "Int32": 5, 1508 "Int64": 6, 1509 "Uint": 7, 1510 "Uint8": 8, 1511 "Uint16": 9, 1512 "Uint32": 10, 1513 "Uint64": 11, 1514 "Uintptr": 12, 1515 "Float32": 14.1, 1516 "Float64": 15.1, 1517 "bar": "foo", 1518 "bar2": "foo2", 1519 "IntStr": "42", 1520 "UintptrStr": "44", 1521 "PBool": null, 1522 "PInt": null, 1523 "PInt8": null, 1524 "PInt16": null, 1525 "PInt32": null, 1526 "PInt64": null, 1527 "PUint": null, 1528 "PUint8": null, 1529 "PUint16": null, 1530 "PUint32": null, 1531 "PUint64": null, 1532 "PUintptr": null, 1533 "PFloat32": null, 1534 "PFloat64": null, 1535 "String": "16", 1536 "PString": null, 1537 "Map": { 1538 "17": { 1539 "Tag": "tag17" 1540 }, 1541 "18": { 1542 "Tag": "tag18" 1543 } 1544 }, 1545 "MapP": { 1546 "19": { 1547 "Tag": "tag19" 1548 }, 1549 "20": null 1550 }, 1551 "PMap": null, 1552 "PMapP": null, 1553 "EmptyMap": {}, 1554 "NilMap": null, 1555 "Slice": [ 1556 { 1557 "Tag": "tag20" 1558 }, 1559 { 1560 "Tag": "tag21" 1561 } 1562 ], 1563 "SliceP": [ 1564 { 1565 "Tag": "tag22" 1566 }, 1567 null, 1568 { 1569 "Tag": "tag23" 1570 } 1571 ], 1572 "PSlice": null, 1573 "PSliceP": null, 1574 "EmptySlice": [], 1575 "NilSlice": null, 1576 "StringSlice": [ 1577 "str24", 1578 "str25", 1579 "str26" 1580 ], 1581 "ByteSlice": "Gxwd", 1582 "Small": { 1583 "Tag": "tag30" 1584 }, 1585 "PSmall": { 1586 "Tag": "tag31" 1587 }, 1588 "PPSmall": null, 1589 "Interface": 5.2, 1590 "PInterface": null 1591}` 1592 1593var allValueCompact = stripWhitespace(allValueIndent) 1594 1595var pallValueIndent = `{ 1596 "Bool": false, 1597 "Int": 0, 1598 "Int8": 0, 1599 "Int16": 0, 1600 "Int32": 0, 1601 "Int64": 0, 1602 "Uint": 0, 1603 "Uint8": 0, 1604 "Uint16": 0, 1605 "Uint32": 0, 1606 "Uint64": 0, 1607 "Uintptr": 0, 1608 "Float32": 0, 1609 "Float64": 0, 1610 "bar": "", 1611 "bar2": "", 1612 "IntStr": "0", 1613 "UintptrStr": "0", 1614 "PBool": true, 1615 "PInt": 2, 1616 "PInt8": 3, 1617 "PInt16": 4, 1618 "PInt32": 5, 1619 "PInt64": 6, 1620 "PUint": 7, 1621 "PUint8": 8, 1622 "PUint16": 9, 1623 "PUint32": 10, 1624 "PUint64": 11, 1625 "PUintptr": 12, 1626 "PFloat32": 14.1, 1627 "PFloat64": 15.1, 1628 "String": "", 1629 "PString": "16", 1630 "Map": null, 1631 "MapP": null, 1632 "PMap": { 1633 "17": { 1634 "Tag": "tag17" 1635 }, 1636 "18": { 1637 "Tag": "tag18" 1638 } 1639 }, 1640 "PMapP": { 1641 "19": { 1642 "Tag": "tag19" 1643 }, 1644 "20": null 1645 }, 1646 "EmptyMap": null, 1647 "NilMap": null, 1648 "Slice": null, 1649 "SliceP": null, 1650 "PSlice": [ 1651 { 1652 "Tag": "tag20" 1653 }, 1654 { 1655 "Tag": "tag21" 1656 } 1657 ], 1658 "PSliceP": [ 1659 { 1660 "Tag": "tag22" 1661 }, 1662 null, 1663 { 1664 "Tag": "tag23" 1665 } 1666 ], 1667 "EmptySlice": null, 1668 "NilSlice": null, 1669 "StringSlice": null, 1670 "ByteSlice": null, 1671 "Small": { 1672 "Tag": "" 1673 }, 1674 "PSmall": null, 1675 "PPSmall": { 1676 "Tag": "tag31" 1677 }, 1678 "Interface": null, 1679 "PInterface": 5.2 1680}` 1681 1682var pallValueCompact = stripWhitespace(pallValueIndent) 1683 1684func TestRefUnmarshal(t *testing.T) { 1685 type S struct { 1686 // Ref is defined in encode_test.go. 1687 R0 Ref 1688 R1 *Ref 1689 R2 RefText 1690 R3 *RefText 1691 } 1692 want := S{ 1693 R0: 12, 1694 R1: new(Ref), 1695 R2: 13, 1696 R3: new(RefText), 1697 } 1698 *want.R1 = 12 1699 *want.R3 = 13 1700 1701 var got S 1702 if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil { 1703 t.Fatalf("Unmarshal error: %v", err) 1704 } 1705 if !reflect.DeepEqual(got, want) { 1706 t.Errorf("Unmarsha:\n\tgot: %+v\n\twant: %+v", got, want) 1707 } 1708} 1709 1710// Test that the empty string doesn't panic decoding when ,string is specified 1711// Issue 3450 1712func TestEmptyString(t *testing.T) { 1713 type T2 struct { 1714 Number1 int `json:",string"` 1715 Number2 int `json:",string"` 1716 } 1717 data := `{"Number1":"1", "Number2":""}` 1718 dec := NewDecoder(strings.NewReader(data)) 1719 var got T2 1720 switch err := dec.Decode(&got); { 1721 case err == nil: 1722 t.Fatalf("Decode error: got nil, want non-nil") 1723 case got.Number1 != 1: 1724 t.Fatalf("Decode: got.Number1 = %d, want 1", got.Number1) 1725 } 1726} 1727 1728// Test that a null for ,string is not replaced with the previous quoted string (issue 7046). 1729// It should also not be an error (issue 2540, issue 8587). 1730func TestNullString(t *testing.T) { 1731 type T struct { 1732 A int `json:",string"` 1733 B int `json:",string"` 1734 C *int `json:",string"` 1735 } 1736 data := []byte(`{"A": "1", "B": null, "C": null}`) 1737 var s T 1738 s.B = 1 1739 s.C = new(int) 1740 *s.C = 2 1741 switch err := Unmarshal(data, &s); { 1742 case err != nil: 1743 t.Fatalf("Unmarshal error: %v", err) 1744 case s.B != 1: 1745 t.Fatalf("Unmarshal: s.B = %d, want 1", s.B) 1746 case s.C != nil: 1747 t.Fatalf("Unmarshal: s.C = %d, want non-nil", s.C) 1748 } 1749} 1750 1751func intp(x int) *int { 1752 p := new(int) 1753 *p = x 1754 return p 1755} 1756 1757func intpp(x *int) **int { 1758 pp := new(*int) 1759 *pp = x 1760 return pp 1761} 1762 1763func TestInterfaceSet(t *testing.T) { 1764 tests := []struct { 1765 CaseName 1766 pre any 1767 json string 1768 post any 1769 }{ 1770 {Name(""), "foo", `"bar"`, "bar"}, 1771 {Name(""), "foo", `2`, 2.0}, 1772 {Name(""), "foo", `true`, true}, 1773 {Name(""), "foo", `null`, nil}, 1774 1775 {Name(""), nil, `null`, nil}, 1776 {Name(""), new(int), `null`, nil}, 1777 {Name(""), (*int)(nil), `null`, nil}, 1778 {Name(""), new(*int), `null`, new(*int)}, 1779 {Name(""), (**int)(nil), `null`, nil}, 1780 {Name(""), intp(1), `null`, nil}, 1781 {Name(""), intpp(nil), `null`, intpp(nil)}, 1782 {Name(""), intpp(intp(1)), `null`, intpp(nil)}, 1783 } 1784 for _, tt := range tests { 1785 t.Run(tt.Name, func(t *testing.T) { 1786 b := struct{ X any }{tt.pre} 1787 blob := `{"X":` + tt.json + `}` 1788 if err := Unmarshal([]byte(blob), &b); err != nil { 1789 t.Fatalf("%s: Unmarshal(%#q) error: %v", tt.Where, blob, err) 1790 } 1791 if !reflect.DeepEqual(b.X, tt.post) { 1792 t.Errorf("%s: Unmarshal(%#q):\n\tpre.X: %#v\n\tgot.X: %#v\n\twant.X: %#v", tt.Where, blob, tt.pre, b.X, tt.post) 1793 } 1794 }) 1795 } 1796} 1797 1798type NullTest struct { 1799 Bool bool 1800 Int int 1801 Int8 int8 1802 Int16 int16 1803 Int32 int32 1804 Int64 int64 1805 Uint uint 1806 Uint8 uint8 1807 Uint16 uint16 1808 Uint32 uint32 1809 Uint64 uint64 1810 Float32 float32 1811 Float64 float64 1812 String string 1813 PBool *bool 1814 Map map[string]string 1815 Slice []string 1816 Interface any 1817 1818 PRaw *RawMessage 1819 PTime *time.Time 1820 PBigInt *big.Int 1821 PText *MustNotUnmarshalText 1822 PBuffer *bytes.Buffer // has methods, just not relevant ones 1823 PStruct *struct{} 1824 1825 Raw RawMessage 1826 Time time.Time 1827 BigInt big.Int 1828 Text MustNotUnmarshalText 1829 Buffer bytes.Buffer 1830 Struct struct{} 1831} 1832 1833// JSON null values should be ignored for primitives and string values instead of resulting in an error. 1834// Issue 2540 1835func TestUnmarshalNulls(t *testing.T) { 1836 // Unmarshal docs: 1837 // The JSON null value unmarshals into an interface, map, pointer, or slice 1838 // by setting that Go value to nil. Because null is often used in JSON to mean 1839 // ``not present,'' unmarshaling a JSON null into any other Go type has no effect 1840 // on the value and produces no error. 1841 1842 jsonData := []byte(`{ 1843 "Bool" : null, 1844 "Int" : null, 1845 "Int8" : null, 1846 "Int16" : null, 1847 "Int32" : null, 1848 "Int64" : null, 1849 "Uint" : null, 1850 "Uint8" : null, 1851 "Uint16" : null, 1852 "Uint32" : null, 1853 "Uint64" : null, 1854 "Float32" : null, 1855 "Float64" : null, 1856 "String" : null, 1857 "PBool": null, 1858 "Map": null, 1859 "Slice": null, 1860 "Interface": null, 1861 "PRaw": null, 1862 "PTime": null, 1863 "PBigInt": null, 1864 "PText": null, 1865 "PBuffer": null, 1866 "PStruct": null, 1867 "Raw": null, 1868 "Time": null, 1869 "BigInt": null, 1870 "Text": null, 1871 "Buffer": null, 1872 "Struct": null 1873 }`) 1874 nulls := NullTest{ 1875 Bool: true, 1876 Int: 2, 1877 Int8: 3, 1878 Int16: 4, 1879 Int32: 5, 1880 Int64: 6, 1881 Uint: 7, 1882 Uint8: 8, 1883 Uint16: 9, 1884 Uint32: 10, 1885 Uint64: 11, 1886 Float32: 12.1, 1887 Float64: 13.1, 1888 String: "14", 1889 PBool: new(bool), 1890 Map: map[string]string{}, 1891 Slice: []string{}, 1892 Interface: new(MustNotUnmarshalJSON), 1893 PRaw: new(RawMessage), 1894 PTime: new(time.Time), 1895 PBigInt: new(big.Int), 1896 PText: new(MustNotUnmarshalText), 1897 PStruct: new(struct{}), 1898 PBuffer: new(bytes.Buffer), 1899 Raw: RawMessage("123"), 1900 Time: time.Unix(123456789, 0), 1901 BigInt: *big.NewInt(123), 1902 } 1903 1904 before := nulls.Time.String() 1905 1906 err := Unmarshal(jsonData, &nulls) 1907 if err != nil { 1908 t.Errorf("Unmarshal of null values failed: %v", err) 1909 } 1910 if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 || 1911 nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 || 1912 nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" { 1913 t.Errorf("Unmarshal of null values affected primitives") 1914 } 1915 1916 if nulls.PBool != nil { 1917 t.Errorf("Unmarshal of null did not clear nulls.PBool") 1918 } 1919 if nulls.Map != nil { 1920 t.Errorf("Unmarshal of null did not clear nulls.Map") 1921 } 1922 if nulls.Slice != nil { 1923 t.Errorf("Unmarshal of null did not clear nulls.Slice") 1924 } 1925 if nulls.Interface != nil { 1926 t.Errorf("Unmarshal of null did not clear nulls.Interface") 1927 } 1928 if nulls.PRaw != nil { 1929 t.Errorf("Unmarshal of null did not clear nulls.PRaw") 1930 } 1931 if nulls.PTime != nil { 1932 t.Errorf("Unmarshal of null did not clear nulls.PTime") 1933 } 1934 if nulls.PBigInt != nil { 1935 t.Errorf("Unmarshal of null did not clear nulls.PBigInt") 1936 } 1937 if nulls.PText != nil { 1938 t.Errorf("Unmarshal of null did not clear nulls.PText") 1939 } 1940 if nulls.PBuffer != nil { 1941 t.Errorf("Unmarshal of null did not clear nulls.PBuffer") 1942 } 1943 if nulls.PStruct != nil { 1944 t.Errorf("Unmarshal of null did not clear nulls.PStruct") 1945 } 1946 1947 if string(nulls.Raw) != "null" { 1948 t.Errorf("Unmarshal of RawMessage null did not record null: %v", string(nulls.Raw)) 1949 } 1950 if nulls.Time.String() != before { 1951 t.Errorf("Unmarshal of time.Time null set time to %v", nulls.Time.String()) 1952 } 1953 if nulls.BigInt.String() != "123" { 1954 t.Errorf("Unmarshal of big.Int null set int to %v", nulls.BigInt.String()) 1955 } 1956} 1957 1958type MustNotUnmarshalJSON struct{} 1959 1960func (x MustNotUnmarshalJSON) UnmarshalJSON(data []byte) error { 1961 return errors.New("MustNotUnmarshalJSON was used") 1962} 1963 1964type MustNotUnmarshalText struct{} 1965 1966func (x MustNotUnmarshalText) UnmarshalText(text []byte) error { 1967 return errors.New("MustNotUnmarshalText was used") 1968} 1969 1970func TestStringKind(t *testing.T) { 1971 type stringKind string 1972 want := map[stringKind]int{"foo": 42} 1973 data, err := Marshal(want) 1974 if err != nil { 1975 t.Fatalf("Marshal error: %v", err) 1976 } 1977 var got map[stringKind]int 1978 err = Unmarshal(data, &got) 1979 if err != nil { 1980 t.Fatalf("Unmarshal error: %v", err) 1981 } 1982 if !reflect.DeepEqual(got, want) { 1983 t.Fatalf("Marshal/Unmarshal mismatch:\n\tgot: %v\n\twant: %v", got, want) 1984 } 1985} 1986 1987// Custom types with []byte as underlying type could not be marshaled 1988// and then unmarshaled. 1989// Issue 8962. 1990func TestByteKind(t *testing.T) { 1991 type byteKind []byte 1992 want := byteKind("hello") 1993 data, err := Marshal(want) 1994 if err != nil { 1995 t.Fatalf("Marshal error: %v", err) 1996 } 1997 var got byteKind 1998 err = Unmarshal(data, &got) 1999 if err != nil { 2000 t.Fatalf("Unmarshal error: %v", err) 2001 } 2002 if !slices.Equal(got, want) { 2003 t.Fatalf("Marshal/Unmarshal mismatch:\n\tgot: %v\n\twant: %v", got, want) 2004 } 2005} 2006 2007// The fix for issue 8962 introduced a regression. 2008// Issue 12921. 2009func TestSliceOfCustomByte(t *testing.T) { 2010 type Uint8 uint8 2011 want := []Uint8("hello") 2012 data, err := Marshal(want) 2013 if err != nil { 2014 t.Fatalf("Marshal error: %v", err) 2015 } 2016 var got []Uint8 2017 err = Unmarshal(data, &got) 2018 if err != nil { 2019 t.Fatalf("Unmarshal error: %v", err) 2020 } 2021 if !slices.Equal(got, want) { 2022 t.Fatalf("Marshal/Unmarshal mismatch:\n\tgot: %v\n\twant: %v", got, want) 2023 } 2024} 2025 2026func TestUnmarshalTypeError(t *testing.T) { 2027 tests := []struct { 2028 CaseName 2029 dest any 2030 in string 2031 }{ 2032 {Name(""), new(string), `{"user": "name"}`}, // issue 4628. 2033 {Name(""), new(error), `{}`}, // issue 4222 2034 {Name(""), new(error), `[]`}, 2035 {Name(""), new(error), `""`}, 2036 {Name(""), new(error), `123`}, 2037 {Name(""), new(error), `true`}, 2038 } 2039 for _, tt := range tests { 2040 t.Run(tt.Name, func(t *testing.T) { 2041 err := Unmarshal([]byte(tt.in), tt.dest) 2042 if _, ok := err.(*UnmarshalTypeError); !ok { 2043 t.Errorf("%s: Unmarshal(%#q, %T):\n\tgot: %T\n\twant: %T", 2044 tt.Where, tt.in, tt.dest, err, new(UnmarshalTypeError)) 2045 } 2046 }) 2047 } 2048} 2049 2050func TestUnmarshalSyntax(t *testing.T) { 2051 var x any 2052 tests := []struct { 2053 CaseName 2054 in string 2055 }{ 2056 {Name(""), "tru"}, 2057 {Name(""), "fals"}, 2058 {Name(""), "nul"}, 2059 {Name(""), "123e"}, 2060 {Name(""), `"hello`}, 2061 {Name(""), `[1,2,3`}, 2062 {Name(""), `{"key":1`}, 2063 {Name(""), `{"key":1,`}, 2064 } 2065 for _, tt := range tests { 2066 t.Run(tt.Name, func(t *testing.T) { 2067 err := Unmarshal([]byte(tt.in), &x) 2068 if _, ok := err.(*SyntaxError); !ok { 2069 t.Errorf("%s: Unmarshal(%#q, any):\n\tgot: %T\n\twant: %T", 2070 tt.Where, tt.in, err, new(SyntaxError)) 2071 } 2072 }) 2073 } 2074} 2075 2076// Test handling of unexported fields that should be ignored. 2077// Issue 4660 2078type unexportedFields struct { 2079 Name string 2080 m map[string]any `json:"-"` 2081 m2 map[string]any `json:"abcd"` 2082 2083 s []int `json:"-"` 2084} 2085 2086func TestUnmarshalUnexported(t *testing.T) { 2087 input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}, "s": [2, 3]}` 2088 want := &unexportedFields{Name: "Bob"} 2089 2090 out := &unexportedFields{} 2091 err := Unmarshal([]byte(input), out) 2092 if err != nil { 2093 t.Errorf("Unmarshal error: %v", err) 2094 } 2095 if !reflect.DeepEqual(out, want) { 2096 t.Errorf("Unmarshal:\n\tgot: %+v\n\twant: %+v", out, want) 2097 } 2098} 2099 2100// Time3339 is a time.Time which encodes to and from JSON 2101// as an RFC 3339 time in UTC. 2102type Time3339 time.Time 2103 2104func (t *Time3339) UnmarshalJSON(b []byte) error { 2105 if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { 2106 return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b) 2107 } 2108 tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1])) 2109 if err != nil { 2110 return err 2111 } 2112 *t = Time3339(tm) 2113 return nil 2114} 2115 2116func TestUnmarshalJSONLiteralError(t *testing.T) { 2117 var t3 Time3339 2118 switch err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3); { 2119 case err == nil: 2120 t.Fatalf("Unmarshal error: got nil, want non-nil") 2121 case !strings.Contains(err.Error(), "range"): 2122 t.Errorf("Unmarshal error:\n\tgot: %v\n\twant: out of range", err) 2123 } 2124} 2125 2126// Test that extra object elements in an array do not result in a 2127// "data changing underfoot" error. 2128// Issue 3717 2129func TestSkipArrayObjects(t *testing.T) { 2130 json := `[{}]` 2131 var dest [0]any 2132 2133 err := Unmarshal([]byte(json), &dest) 2134 if err != nil { 2135 t.Errorf("Unmarshal error: %v", err) 2136 } 2137} 2138 2139// Test semantics of pre-filled data, such as struct fields, map elements, 2140// slices, and arrays. 2141// Issues 4900 and 8837, among others. 2142func TestPrefilled(t *testing.T) { 2143 // Values here change, cannot reuse table across runs. 2144 tests := []struct { 2145 CaseName 2146 in string 2147 ptr any 2148 out any 2149 }{{ 2150 CaseName: Name(""), 2151 in: `{"X": 1, "Y": 2}`, 2152 ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5}, 2153 out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5}, 2154 }, { 2155 CaseName: Name(""), 2156 in: `{"X": 1, "Y": 2}`, 2157 ptr: &map[string]any{"X": float32(3), "Y": int16(4), "Z": 1.5}, 2158 out: &map[string]any{"X": float64(1), "Y": float64(2), "Z": 1.5}, 2159 }, { 2160 CaseName: Name(""), 2161 in: `[2]`, 2162 ptr: &[]int{1}, 2163 out: &[]int{2}, 2164 }, { 2165 CaseName: Name(""), 2166 in: `[2, 3]`, 2167 ptr: &[]int{1}, 2168 out: &[]int{2, 3}, 2169 }, { 2170 CaseName: Name(""), 2171 in: `[2, 3]`, 2172 ptr: &[...]int{1}, 2173 out: &[...]int{2}, 2174 }, { 2175 CaseName: Name(""), 2176 in: `[3]`, 2177 ptr: &[...]int{1, 2}, 2178 out: &[...]int{3, 0}, 2179 }} 2180 for _, tt := range tests { 2181 t.Run(tt.Name, func(t *testing.T) { 2182 ptrstr := fmt.Sprintf("%v", tt.ptr) 2183 err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here 2184 if err != nil { 2185 t.Errorf("%s: Unmarshal error: %v", tt.Where, err) 2186 } 2187 if !reflect.DeepEqual(tt.ptr, tt.out) { 2188 t.Errorf("%s: Unmarshal(%#q, %T):\n\tgot: %v\n\twant: %v", tt.Where, tt.in, ptrstr, tt.ptr, tt.out) 2189 } 2190 }) 2191 } 2192} 2193 2194func TestInvalidUnmarshal(t *testing.T) { 2195 buf := []byte(`{"a":"1"}`) 2196 tests := []struct { 2197 CaseName 2198 v any 2199 want string 2200 }{ 2201 {Name(""), nil, "json: Unmarshal(nil)"}, 2202 {Name(""), struct{}{}, "json: Unmarshal(non-pointer struct {})"}, 2203 {Name(""), (*int)(nil), "json: Unmarshal(nil *int)"}, 2204 } 2205 for _, tt := range tests { 2206 t.Run(tt.Name, func(t *testing.T) { 2207 err := Unmarshal(buf, tt.v) 2208 if err == nil { 2209 t.Fatalf("%s: Unmarshal error: got nil, want non-nil", tt.Where) 2210 } 2211 if got := err.Error(); got != tt.want { 2212 t.Errorf("%s: Unmarshal error:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want) 2213 } 2214 }) 2215 } 2216} 2217 2218func TestInvalidUnmarshalText(t *testing.T) { 2219 buf := []byte(`123`) 2220 tests := []struct { 2221 CaseName 2222 v any 2223 want string 2224 }{ 2225 {Name(""), nil, "json: Unmarshal(nil)"}, 2226 {Name(""), struct{}{}, "json: Unmarshal(non-pointer struct {})"}, 2227 {Name(""), (*int)(nil), "json: Unmarshal(nil *int)"}, 2228 {Name(""), new(net.IP), "json: cannot unmarshal number into Go value of type *net.IP"}, 2229 } 2230 for _, tt := range tests { 2231 t.Run(tt.Name, func(t *testing.T) { 2232 err := Unmarshal(buf, tt.v) 2233 if err == nil { 2234 t.Fatalf("%s: Unmarshal error: got nil, want non-nil", tt.Where) 2235 } 2236 if got := err.Error(); got != tt.want { 2237 t.Errorf("%s: Unmarshal error:\n\tgot: %s\n\twant: %s", tt.Where, got, tt.want) 2238 } 2239 }) 2240 } 2241} 2242 2243// Test that string option is ignored for invalid types. 2244// Issue 9812. 2245func TestInvalidStringOption(t *testing.T) { 2246 num := 0 2247 item := struct { 2248 T time.Time `json:",string"` 2249 M map[string]string `json:",string"` 2250 S []string `json:",string"` 2251 A [1]string `json:",string"` 2252 I any `json:",string"` 2253 P *int `json:",string"` 2254 }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num} 2255 2256 data, err := Marshal(item) 2257 if err != nil { 2258 t.Fatalf("Marshal error: %v", err) 2259 } 2260 2261 err = Unmarshal(data, &item) 2262 if err != nil { 2263 t.Fatalf("Unmarshal error: %v", err) 2264 } 2265} 2266 2267// Test unmarshal behavior with regards to embedded unexported structs. 2268// 2269// (Issue 21357) If the embedded struct is a pointer and is unallocated, 2270// this returns an error because unmarshal cannot set the field. 2271// 2272// (Issue 24152) If the embedded struct is given an explicit name, 2273// ensure that the normal unmarshal logic does not panic in reflect. 2274// 2275// (Issue 28145) If the embedded struct is given an explicit name and has 2276// exported methods, don't cause a panic trying to get its value. 2277func TestUnmarshalEmbeddedUnexported(t *testing.T) { 2278 type ( 2279 embed1 struct{ Q int } 2280 embed2 struct{ Q int } 2281 embed3 struct { 2282 Q int64 `json:",string"` 2283 } 2284 S1 struct { 2285 *embed1 2286 R int 2287 } 2288 S2 struct { 2289 *embed1 2290 Q int 2291 } 2292 S3 struct { 2293 embed1 2294 R int 2295 } 2296 S4 struct { 2297 *embed1 2298 embed2 2299 } 2300 S5 struct { 2301 *embed3 2302 R int 2303 } 2304 S6 struct { 2305 embed1 `json:"embed1"` 2306 } 2307 S7 struct { 2308 embed1 `json:"embed1"` 2309 embed2 2310 } 2311 S8 struct { 2312 embed1 `json:"embed1"` 2313 embed2 `json:"embed2"` 2314 Q int 2315 } 2316 S9 struct { 2317 unexportedWithMethods `json:"embed"` 2318 } 2319 ) 2320 2321 tests := []struct { 2322 CaseName 2323 in string 2324 ptr any 2325 out any 2326 err error 2327 }{{ 2328 // Error since we cannot set S1.embed1, but still able to set S1.R. 2329 CaseName: Name(""), 2330 in: `{"R":2,"Q":1}`, 2331 ptr: new(S1), 2332 out: &S1{R: 2}, 2333 err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json.embed1"), 2334 }, { 2335 // The top level Q field takes precedence. 2336 CaseName: Name(""), 2337 in: `{"Q":1}`, 2338 ptr: new(S2), 2339 out: &S2{Q: 1}, 2340 }, { 2341 // No issue with non-pointer variant. 2342 CaseName: Name(""), 2343 in: `{"R":2,"Q":1}`, 2344 ptr: new(S3), 2345 out: &S3{embed1: embed1{Q: 1}, R: 2}, 2346 }, { 2347 // No error since both embedded structs have field R, which annihilate each other. 2348 // Thus, no attempt is made at setting S4.embed1. 2349 CaseName: Name(""), 2350 in: `{"R":2}`, 2351 ptr: new(S4), 2352 out: new(S4), 2353 }, { 2354 // Error since we cannot set S5.embed1, but still able to set S5.R. 2355 CaseName: Name(""), 2356 in: `{"R":2,"Q":1}`, 2357 ptr: new(S5), 2358 out: &S5{R: 2}, 2359 err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json.embed3"), 2360 }, { 2361 // Issue 24152, ensure decodeState.indirect does not panic. 2362 CaseName: Name(""), 2363 in: `{"embed1": {"Q": 1}}`, 2364 ptr: new(S6), 2365 out: &S6{embed1{1}}, 2366 }, { 2367 // Issue 24153, check that we can still set forwarded fields even in 2368 // the presence of a name conflict. 2369 // 2370 // This relies on obscure behavior of reflect where it is possible 2371 // to set a forwarded exported field on an unexported embedded struct 2372 // even though there is a name conflict, even when it would have been 2373 // impossible to do so according to Go visibility rules. 2374 // Go forbids this because it is ambiguous whether S7.Q refers to 2375 // S7.embed1.Q or S7.embed2.Q. Since embed1 and embed2 are unexported, 2376 // it should be impossible for an external package to set either Q. 2377 // 2378 // It is probably okay for a future reflect change to break this. 2379 CaseName: Name(""), 2380 in: `{"embed1": {"Q": 1}, "Q": 2}`, 2381 ptr: new(S7), 2382 out: &S7{embed1{1}, embed2{2}}, 2383 }, { 2384 // Issue 24153, similar to the S7 case. 2385 CaseName: Name(""), 2386 in: `{"embed1": {"Q": 1}, "embed2": {"Q": 2}, "Q": 3}`, 2387 ptr: new(S8), 2388 out: &S8{embed1{1}, embed2{2}, 3}, 2389 }, { 2390 // Issue 228145, similar to the cases above. 2391 CaseName: Name(""), 2392 in: `{"embed": {}}`, 2393 ptr: new(S9), 2394 out: &S9{}, 2395 }} 2396 for _, tt := range tests { 2397 t.Run(tt.Name, func(t *testing.T) { 2398 err := Unmarshal([]byte(tt.in), tt.ptr) 2399 if !equalError(err, tt.err) { 2400 t.Errorf("%s: Unmarshal error:\n\tgot: %v\n\twant: %v", tt.Where, err, tt.err) 2401 } 2402 if !reflect.DeepEqual(tt.ptr, tt.out) { 2403 t.Errorf("%s: Unmarshal:\n\tgot: %#+v\n\twant: %#+v", tt.Where, tt.ptr, tt.out) 2404 } 2405 }) 2406 } 2407} 2408 2409func TestUnmarshalErrorAfterMultipleJSON(t *testing.T) { 2410 tests := []struct { 2411 CaseName 2412 in string 2413 err error 2414 }{{ 2415 CaseName: Name(""), 2416 in: `1 false null :`, 2417 err: &SyntaxError{"invalid character ':' looking for beginning of value", 14}, 2418 }, { 2419 CaseName: Name(""), 2420 in: `1 [] [,]`, 2421 err: &SyntaxError{"invalid character ',' looking for beginning of value", 7}, 2422 }, { 2423 CaseName: Name(""), 2424 in: `1 [] [true:]`, 2425 err: &SyntaxError{"invalid character ':' after array element", 11}, 2426 }, { 2427 CaseName: Name(""), 2428 in: `1 {} {"x"=}`, 2429 err: &SyntaxError{"invalid character '=' after object key", 14}, 2430 }, { 2431 CaseName: Name(""), 2432 in: `falsetruenul#`, 2433 err: &SyntaxError{"invalid character '#' in literal null (expecting 'l')", 13}, 2434 }} 2435 for _, tt := range tests { 2436 t.Run(tt.Name, func(t *testing.T) { 2437 dec := NewDecoder(strings.NewReader(tt.in)) 2438 var err error 2439 for err == nil { 2440 var v any 2441 err = dec.Decode(&v) 2442 } 2443 if !reflect.DeepEqual(err, tt.err) { 2444 t.Errorf("%s: Decode error:\n\tgot: %v\n\twant: %v", tt.Where, err, tt.err) 2445 } 2446 }) 2447 } 2448} 2449 2450type unmarshalPanic struct{} 2451 2452func (unmarshalPanic) UnmarshalJSON([]byte) error { panic(0xdead) } 2453 2454func TestUnmarshalPanic(t *testing.T) { 2455 defer func() { 2456 if got := recover(); !reflect.DeepEqual(got, 0xdead) { 2457 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) 2458 } 2459 }() 2460 Unmarshal([]byte("{}"), &unmarshalPanic{}) 2461 t.Fatalf("Unmarshal should have panicked") 2462} 2463 2464// The decoder used to hang if decoding into an interface pointing to its own address. 2465// See golang.org/issues/31740. 2466func TestUnmarshalRecursivePointer(t *testing.T) { 2467 var v any 2468 v = &v 2469 data := []byte(`{"a": "b"}`) 2470 2471 if err := Unmarshal(data, v); err != nil { 2472 t.Fatalf("Unmarshal error: %v", err) 2473 } 2474} 2475 2476type textUnmarshalerString string 2477 2478func (m *textUnmarshalerString) UnmarshalText(text []byte) error { 2479 *m = textUnmarshalerString(strings.ToLower(string(text))) 2480 return nil 2481} 2482 2483// Test unmarshal to a map, where the map key is a user defined type. 2484// See golang.org/issues/34437. 2485func TestUnmarshalMapWithTextUnmarshalerStringKey(t *testing.T) { 2486 var p map[textUnmarshalerString]string 2487 if err := Unmarshal([]byte(`{"FOO": "1"}`), &p); err != nil { 2488 t.Fatalf("Unmarshal error: %v", err) 2489 } 2490 2491 if _, ok := p["foo"]; !ok { 2492 t.Errorf(`key "foo" missing in map: %v`, p) 2493 } 2494} 2495 2496func TestUnmarshalRescanLiteralMangledUnquote(t *testing.T) { 2497 // See golang.org/issues/38105. 2498 var p map[textUnmarshalerString]string 2499 if err := Unmarshal([]byte(`{"开源":"12345开源"}`), &p); err != nil { 2500 t.Fatalf("Unmarshal error: %v", err) 2501 } 2502 if _, ok := p["开源"]; !ok { 2503 t.Errorf(`key "开源" missing in map: %v`, p) 2504 } 2505 2506 // See golang.org/issues/38126. 2507 type T struct { 2508 F1 string `json:"F1,string"` 2509 } 2510 wantT := T{"aaa\tbbb"} 2511 2512 b, err := Marshal(wantT) 2513 if err != nil { 2514 t.Fatalf("Marshal error: %v", err) 2515 } 2516 var gotT T 2517 if err := Unmarshal(b, &gotT); err != nil { 2518 t.Fatalf("Unmarshal error: %v", err) 2519 } 2520 if gotT != wantT { 2521 t.Errorf("Marshal/Unmarshal roundtrip:\n\tgot: %q\n\twant: %q", gotT, wantT) 2522 } 2523 2524 // See golang.org/issues/39555. 2525 input := map[textUnmarshalerString]string{"FOO": "", `"`: ""} 2526 2527 encoded, err := Marshal(input) 2528 if err != nil { 2529 t.Fatalf("Marshal error: %v", err) 2530 } 2531 var got map[textUnmarshalerString]string 2532 if err := Unmarshal(encoded, &got); err != nil { 2533 t.Fatalf("Unmarshal error: %v", err) 2534 } 2535 want := map[textUnmarshalerString]string{"foo": "", `"`: ""} 2536 if !reflect.DeepEqual(got, want) { 2537 t.Errorf("Marshal/Unmarshal roundtrip:\n\tgot: %q\n\twant: %q", gotT, wantT) 2538 } 2539} 2540 2541func TestUnmarshalMaxDepth(t *testing.T) { 2542 tests := []struct { 2543 CaseName 2544 data string 2545 errMaxDepth bool 2546 }{{ 2547 CaseName: Name("ArrayUnderMaxNestingDepth"), 2548 data: `{"a":` + strings.Repeat(`[`, 10000-1) + strings.Repeat(`]`, 10000-1) + `}`, 2549 errMaxDepth: false, 2550 }, { 2551 CaseName: Name("ArrayOverMaxNestingDepth"), 2552 data: `{"a":` + strings.Repeat(`[`, 10000) + strings.Repeat(`]`, 10000) + `}`, 2553 errMaxDepth: true, 2554 }, { 2555 CaseName: Name("ArrayOverStackDepth"), 2556 data: `{"a":` + strings.Repeat(`[`, 3000000) + strings.Repeat(`]`, 3000000) + `}`, 2557 errMaxDepth: true, 2558 }, { 2559 CaseName: Name("ObjectUnderMaxNestingDepth"), 2560 data: `{"a":` + strings.Repeat(`{"a":`, 10000-1) + `0` + strings.Repeat(`}`, 10000-1) + `}`, 2561 errMaxDepth: false, 2562 }, { 2563 CaseName: Name("ObjectOverMaxNestingDepth"), 2564 data: `{"a":` + strings.Repeat(`{"a":`, 10000) + `0` + strings.Repeat(`}`, 10000) + `}`, 2565 errMaxDepth: true, 2566 }, { 2567 CaseName: Name("ObjectOverStackDepth"), 2568 data: `{"a":` + strings.Repeat(`{"a":`, 3000000) + `0` + strings.Repeat(`}`, 3000000) + `}`, 2569 errMaxDepth: true, 2570 }} 2571 2572 targets := []struct { 2573 CaseName 2574 newValue func() any 2575 }{{ 2576 CaseName: Name("unstructured"), 2577 newValue: func() any { 2578 var v any 2579 return &v 2580 }, 2581 }, { 2582 CaseName: Name("typed named field"), 2583 newValue: func() any { 2584 v := struct { 2585 A any `json:"a"` 2586 }{} 2587 return &v 2588 }, 2589 }, { 2590 CaseName: Name("typed missing field"), 2591 newValue: func() any { 2592 v := struct { 2593 B any `json:"b"` 2594 }{} 2595 return &v 2596 }, 2597 }, { 2598 CaseName: Name("custom unmarshaler"), 2599 newValue: func() any { 2600 v := unmarshaler{} 2601 return &v 2602 }, 2603 }} 2604 2605 for _, tt := range tests { 2606 for _, target := range targets { 2607 t.Run(target.Name+"-"+tt.Name, func(t *testing.T) { 2608 err := Unmarshal([]byte(tt.data), target.newValue()) 2609 if !tt.errMaxDepth { 2610 if err != nil { 2611 t.Errorf("%s: %s: Unmarshal error: %v", tt.Where, target.Where, err) 2612 } 2613 } else { 2614 if err == nil || !strings.Contains(err.Error(), "exceeded max depth") { 2615 t.Errorf("%s: %s: Unmarshal error:\n\tgot: %v\n\twant: exceeded max depth", tt.Where, target.Where, err) 2616 } 2617 } 2618 }) 2619 } 2620 } 2621} 2622