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