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