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