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