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