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