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