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