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