1
2
3
4
5
6
7 package json
8
9 import (
10 "bytes"
11 "encoding"
12 "encoding/base32"
13 "encoding/base64"
14 "encoding/hex"
15 "errors"
16 "fmt"
17 "io"
18 "math"
19 "net"
20 "net/netip"
21 "reflect"
22 "strconv"
23 "strings"
24 "testing"
25 "time"
26
27 "encoding/json/internal"
28 "encoding/json/internal/jsonflags"
29 "encoding/json/internal/jsonopts"
30 "encoding/json/internal/jsontest"
31 "encoding/json/internal/jsonwire"
32 "encoding/json/jsontext"
33 )
34
35 func newNonStringNameError(offset int64, pointer jsontext.Pointer) error {
36 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsontext.ErrNonStringName}
37 }
38
39 func newInvalidCharacterError(prefix, where string, offset int64, pointer jsontext.Pointer) error {
40 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.NewInvalidCharacterError(prefix, where)}
41 }
42
43 func newInvalidUTF8Error(offset int64, pointer jsontext.Pointer) error {
44 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.ErrInvalidUTF8}
45 }
46
47 func newParseTimeError(layout, value, layoutElem, valueElem, message string) error {
48 return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message}
49 }
50
51 func EM(err error) *SemanticError {
52 return &SemanticError{action: "marshal", Err: err}
53 }
54
55 func EU(err error) *SemanticError {
56 return &SemanticError{action: "unmarshal", Err: err}
57 }
58
59 func (e *SemanticError) withVal(val string) *SemanticError {
60 e.JSONValue = jsontext.Value(val)
61 return e
62 }
63
64 func (e *SemanticError) withPos(prefix string, pointer jsontext.Pointer) *SemanticError {
65 e.ByteOffset = int64(len(prefix))
66 e.JSONPointer = pointer
67 return e
68 }
69
70 func (e *SemanticError) withType(k jsontext.Kind, t reflect.Type) *SemanticError {
71 e.JSONKind = k
72 e.GoType = t
73 return e
74 }
75
76 var (
77 errInvalidFormatFlag = errors.New(`invalid format flag "invalid"`)
78 errSomeError = errors.New("some error")
79 errMustNotCall = errors.New("must not call")
80 )
81
82 func T[T any]() reflect.Type { return reflect.TypeFor[T]() }
83
84 type (
85 jsonObject = map[string]any
86 jsonArray = []any
87
88 namedAny any
89 namedBool bool
90 namedString string
91 NamedString string
92 namedBytes []byte
93 namedInt64 int64
94 namedUint64 uint64
95 namedFloat64 float64
96 namedByte byte
97 netipAddr = netip.Addr
98
99 recursiveMap map[string]recursiveMap
100 recursiveSlice []recursiveSlice
101 recursivePointer struct{ P *recursivePointer }
102
103 structEmpty struct{}
104 structConflicting struct {
105 A string `json:"conflict"`
106 B string `json:"conflict"`
107 }
108 structNoneExported struct {
109 unexported string
110 }
111 structUnexportedIgnored struct {
112 ignored string `json:"-"`
113 }
114 structMalformedTag struct {
115 Malformed string `json:"\""`
116 }
117 structUnexportedTag struct {
118 unexported string `json:"name"`
119 }
120 structExportedEmbedded struct {
121 NamedString
122 }
123 structExportedEmbeddedTag struct {
124 NamedString `json:"name"`
125 }
126 structUnexportedEmbedded struct {
127 namedString
128 }
129 structUnexportedEmbeddedTag struct {
130 namedString `json:"name"`
131 }
132 structUnexportedEmbeddedMethodTag struct {
133
134
135 netipAddr `json:"name"`
136
137
138
139
140 }
141 structUnexportedEmbeddedStruct struct {
142 structOmitZeroAll
143 FizzBuzz int
144 structNestedAddr
145 }
146 structUnexportedEmbeddedStructPointer struct {
147 *structOmitZeroAll
148 FizzBuzz int
149 *structNestedAddr
150 }
151 structNestedAddr struct {
152 Addr netip.Addr
153 }
154 structIgnoredUnexportedEmbedded struct {
155 namedString `json:"-"`
156 }
157 structWeirdNames struct {
158 Empty string `json:"''"`
159 Comma string `json:"','"`
160 Quote string `json:"'\"'"`
161 }
162 structNoCase struct {
163 Aaa string `json:",case:strict"`
164 AA_A string
165 AaA string `json:",case:ignore"`
166 AAa string `json:",case:ignore"`
167 AAA string
168 }
169 structScalars struct {
170 unexported bool
171 Ignored bool `json:"-"`
172
173 Bool bool
174 String string
175 Bytes []byte
176 Int int64
177 Uint uint64
178 Float float64
179 }
180 structSlices struct {
181 unexported bool
182 Ignored bool `json:"-"`
183
184 SliceBool []bool
185 SliceString []string
186 SliceBytes [][]byte
187 SliceInt []int64
188 SliceUint []uint64
189 SliceFloat []float64
190 }
191 structMaps struct {
192 unexported bool
193 Ignored bool `json:"-"`
194
195 MapBool map[string]bool
196 MapString map[string]string
197 MapBytes map[string][]byte
198 MapInt map[string]int64
199 MapUint map[string]uint64
200 MapFloat map[string]float64
201 }
202 structAll struct {
203 Bool bool
204 String string
205 Bytes []byte
206 Int int64
207 Uint uint64
208 Float float64
209 Map map[string]string
210 StructScalars structScalars
211 StructMaps structMaps
212 StructSlices structSlices
213 Slice []string
214 Array [1]string
215 Pointer *structAll
216 Interface any
217 }
218 structStringifiedAll struct {
219 Bool bool `json:",string"`
220 String string `json:",string"`
221 Bytes []byte `json:",string"`
222 Int int64 `json:",string"`
223 Uint uint64 `json:",string"`
224 Float float64 `json:",string"`
225 Map map[string]string `json:",string"`
226 StructScalars structScalars `json:",string"`
227 StructMaps structMaps `json:",string"`
228 StructSlices structSlices `json:",string"`
229 Slice []string `json:",string"`
230 Array [1]string `json:",string"`
231 Pointer *structStringifiedAll `json:",string"`
232 Interface any `json:",string"`
233 }
234 structOmitZeroAll struct {
235 Bool bool `json:",omitzero"`
236 String string `json:",omitzero"`
237 Bytes []byte `json:",omitzero"`
238 Int int64 `json:",omitzero"`
239 Uint uint64 `json:",omitzero"`
240 Float float64 `json:",omitzero"`
241 Map map[string]string `json:",omitzero"`
242 StructScalars structScalars `json:",omitzero"`
243 StructMaps structMaps `json:",omitzero"`
244 StructSlices structSlices `json:",omitzero"`
245 Slice []string `json:",omitzero"`
246 Array [1]string `json:",omitzero"`
247 Pointer *structOmitZeroAll `json:",omitzero"`
248 Interface any `json:",omitzero"`
249 }
250 structOmitZeroMethodAll struct {
251 ValueAlwaysZero valueAlwaysZero `json:",omitzero"`
252 ValueNeverZero valueNeverZero `json:",omitzero"`
253 PointerAlwaysZero pointerAlwaysZero `json:",omitzero"`
254 PointerNeverZero pointerNeverZero `json:",omitzero"`
255 PointerValueAlwaysZero *valueAlwaysZero `json:",omitzero"`
256 PointerValueNeverZero *valueNeverZero `json:",omitzero"`
257 PointerPointerAlwaysZero *pointerAlwaysZero `json:",omitzero"`
258 PointerPointerNeverZero *pointerNeverZero `json:",omitzero"`
259 PointerPointerValueAlwaysZero **valueAlwaysZero `json:",omitzero"`
260 PointerPointerValueNeverZero **valueNeverZero `json:",omitzero"`
261 PointerPointerPointerAlwaysZero **pointerAlwaysZero `json:",omitzero"`
262 PointerPointerPointerNeverZero **pointerNeverZero `json:",omitzero"`
263 }
264 structOmitZeroMethodInterfaceAll struct {
265 ValueAlwaysZero isZeroer `json:",omitzero"`
266 ValueNeverZero isZeroer `json:",omitzero"`
267 PointerValueAlwaysZero isZeroer `json:",omitzero"`
268 PointerValueNeverZero isZeroer `json:",omitzero"`
269 PointerPointerAlwaysZero isZeroer `json:",omitzero"`
270 PointerPointerNeverZero isZeroer `json:",omitzero"`
271 }
272 structOmitEmptyAll struct {
273 Bool bool `json:",omitempty"`
274 PointerBool *bool `json:",omitempty"`
275 String string `json:",omitempty"`
276 StringEmpty stringMarshalEmpty `json:",omitempty"`
277 StringNonEmpty stringMarshalNonEmpty `json:",omitempty"`
278 PointerString *string `json:",omitempty"`
279 PointerStringEmpty *stringMarshalEmpty `json:",omitempty"`
280 PointerStringNonEmpty *stringMarshalNonEmpty `json:",omitempty"`
281 Bytes []byte `json:",omitempty"`
282 BytesEmpty bytesMarshalEmpty `json:",omitempty"`
283 BytesNonEmpty bytesMarshalNonEmpty `json:",omitempty"`
284 PointerBytes *[]byte `json:",omitempty"`
285 PointerBytesEmpty *bytesMarshalEmpty `json:",omitempty"`
286 PointerBytesNonEmpty *bytesMarshalNonEmpty `json:",omitempty"`
287 Float float64 `json:",omitempty"`
288 PointerFloat *float64 `json:",omitempty"`
289 Map map[string]string `json:",omitempty"`
290 MapEmpty mapMarshalEmpty `json:",omitempty"`
291 MapNonEmpty mapMarshalNonEmpty `json:",omitempty"`
292 PointerMap *map[string]string `json:",omitempty"`
293 PointerMapEmpty *mapMarshalEmpty `json:",omitempty"`
294 PointerMapNonEmpty *mapMarshalNonEmpty `json:",omitempty"`
295 Slice []string `json:",omitempty"`
296 SliceEmpty sliceMarshalEmpty `json:",omitempty"`
297 SliceNonEmpty sliceMarshalNonEmpty `json:",omitempty"`
298 PointerSlice *[]string `json:",omitempty"`
299 PointerSliceEmpty *sliceMarshalEmpty `json:",omitempty"`
300 PointerSliceNonEmpty *sliceMarshalNonEmpty `json:",omitempty"`
301 Pointer *structOmitZeroEmptyAll `json:",omitempty"`
302 Interface any `json:",omitempty"`
303 }
304 structOmitZeroEmptyAll struct {
305 Bool bool `json:",omitzero,omitempty"`
306 String string `json:",omitzero,omitempty"`
307 Bytes []byte `json:",omitzero,omitempty"`
308 Int int64 `json:",omitzero,omitempty"`
309 Uint uint64 `json:",omitzero,omitempty"`
310 Float float64 `json:",omitzero,omitempty"`
311 Map map[string]string `json:",omitzero,omitempty"`
312 Slice []string `json:",omitzero,omitempty"`
313 Array [1]string `json:",omitzero,omitempty"`
314 Pointer *structOmitZeroEmptyAll `json:",omitzero,omitempty"`
315 Interface any `json:",omitzero,omitempty"`
316 }
317 structFormatBytes struct {
318 Base16 []byte `json:",format:base16"`
319 Base32 []byte `json:",format:base32"`
320 Base32Hex []byte `json:",format:base32hex"`
321 Base64 []byte `json:",format:base64"`
322 Base64URL []byte `json:",format:base64url"`
323 Array []byte `json:",format:array"`
324 }
325 structFormatArrayBytes struct {
326 Base16 [4]byte `json:",format:base16"`
327 Base32 [4]byte `json:",format:base32"`
328 Base32Hex [4]byte `json:",format:base32hex"`
329 Base64 [4]byte `json:",format:base64"`
330 Base64URL [4]byte `json:",format:base64url"`
331 Array [4]byte `json:",format:array"`
332 Default [4]byte
333 }
334 structFormatFloats struct {
335 NonFinite float64 `json:",format:nonfinite"`
336 PointerNonFinite *float64 `json:",format:nonfinite"`
337 }
338 structFormatMaps struct {
339 EmitNull map[string]string `json:",format:emitnull"`
340 PointerEmitNull *map[string]string `json:",format:emitnull"`
341 EmitEmpty map[string]string `json:",format:emitempty"`
342 PointerEmitEmpty *map[string]string `json:",format:emitempty"`
343 EmitDefault map[string]string
344 PointerEmitDefault *map[string]string
345 }
346 structFormatSlices struct {
347 EmitNull []string `json:",format:emitnull"`
348 PointerEmitNull *[]string `json:",format:emitnull"`
349 EmitEmpty []string `json:",format:emitempty"`
350 PointerEmitEmpty *[]string `json:",format:emitempty"`
351 EmitDefault []string
352 PointerEmitDefault *[]string
353 }
354 structFormatInvalid struct {
355 Bool bool `json:",omitzero,format:invalid"`
356 String string `json:",omitzero,format:invalid"`
357 Bytes []byte `json:",omitzero,format:invalid"`
358 Int int64 `json:",omitzero,format:invalid"`
359 Uint uint64 `json:",omitzero,format:invalid"`
360 Float float64 `json:",omitzero,format:invalid"`
361 Map map[string]string `json:",omitzero,format:invalid"`
362 Struct structAll `json:",omitzero,format:invalid"`
363 Slice []string `json:",omitzero,format:invalid"`
364 Array [1]string `json:",omitzero,format:invalid"`
365 Interface any `json:",omitzero,format:invalid"`
366 }
367 structDurationFormat struct {
368 D1 time.Duration `json:",format:units"`
369 D2 time.Duration `json:",format:units"`
370 D3 time.Duration `json:",format:sec"`
371 D4 time.Duration `json:",string,format:sec"`
372 D5 time.Duration `json:",format:milli"`
373 D6 time.Duration `json:",string,format:milli"`
374 D7 time.Duration `json:",format:micro"`
375 D8 time.Duration `json:",string,format:micro"`
376 D9 time.Duration `json:",format:nano"`
377 D10 time.Duration `json:",string,format:nano"`
378 D11 time.Duration `json:",format:iso8601"`
379 }
380 structTimeFormat struct {
381 T1 time.Time
382 T2 time.Time `json:",format:ANSIC"`
383 T3 time.Time `json:",format:UnixDate"`
384 T4 time.Time `json:",format:RubyDate"`
385 T5 time.Time `json:",format:RFC822"`
386 T6 time.Time `json:",format:RFC822Z"`
387 T7 time.Time `json:",format:RFC850"`
388 T8 time.Time `json:",format:RFC1123"`
389 T9 time.Time `json:",format:RFC1123Z"`
390 T10 time.Time `json:",format:RFC3339"`
391 T11 time.Time `json:",format:RFC3339Nano"`
392 T12 time.Time `json:",format:Kitchen"`
393 T13 time.Time `json:",format:Stamp"`
394 T14 time.Time `json:",format:StampMilli"`
395 T15 time.Time `json:",format:StampMicro"`
396 T16 time.Time `json:",format:StampNano"`
397 T17 time.Time `json:",format:DateTime"`
398 T18 time.Time `json:",format:DateOnly"`
399 T19 time.Time `json:",format:TimeOnly"`
400 T20 time.Time `json:",format:'2006-01-02'"`
401 T21 time.Time `json:",format:'\"weird\"2006'"`
402 T22 time.Time `json:",format:unix"`
403 T23 time.Time `json:",string,format:unix"`
404 T24 time.Time `json:",format:unixmilli"`
405 T25 time.Time `json:",string,format:unixmilli"`
406 T26 time.Time `json:",format:unixmicro"`
407 T27 time.Time `json:",string,format:unixmicro"`
408 T28 time.Time `json:",format:unixnano"`
409 T29 time.Time `json:",string,format:unixnano"`
410 }
411 structInlined struct {
412 X structInlinedL1 `json:",inline"`
413 *StructEmbed2
414 }
415 structInlinedL1 struct {
416 X *structInlinedL2 `json:",inline"`
417 StructEmbed1 `json:",inline"`
418 }
419 structInlinedL2 struct{ A, B, C string }
420 StructEmbed1 struct{ C, D, E string }
421 StructEmbed2 struct{ E, F, G string }
422 structInlineTextValue struct {
423 A int `json:",omitzero"`
424 X jsontext.Value `json:",inline"`
425 B int `json:",omitzero"`
426 }
427 structInlinePointerTextValue struct {
428 A int `json:",omitzero"`
429 X *jsontext.Value `json:",inline"`
430 B int `json:",omitzero"`
431 }
432 structInlinePointerInlineTextValue struct {
433 X *struct {
434 A int
435 X jsontext.Value `json:",inline"`
436 } `json:",inline"`
437 }
438 structInlineInlinePointerTextValue struct {
439 X struct {
440 X *jsontext.Value `json:",inline"`
441 } `json:",inline"`
442 }
443 structInlineMapStringAny struct {
444 A int `json:",omitzero"`
445 X jsonObject `json:",inline"`
446 B int `json:",omitzero"`
447 }
448 structInlinePointerMapStringAny struct {
449 A int `json:",omitzero"`
450 X *jsonObject `json:",inline"`
451 B int `json:",omitzero"`
452 }
453 structInlinePointerInlineMapStringAny struct {
454 X *struct {
455 A int
456 X jsonObject `json:",inline"`
457 } `json:",inline"`
458 }
459 structInlineInlinePointerMapStringAny struct {
460 X struct {
461 X *jsonObject `json:",inline"`
462 } `json:",inline"`
463 }
464 structInlineMapStringInt struct {
465 X map[string]int `json:",inline"`
466 }
467 structInlineMapNamedStringInt struct {
468 X map[namedString]int `json:",inline"`
469 }
470 structInlineMapNamedStringAny struct {
471 A int `json:",omitzero"`
472 X map[namedString]any `json:",inline"`
473 B int `json:",omitzero"`
474 }
475 structNoCaseInlineTextValue struct {
476 AAA string `json:",omitempty,case:strict"`
477 AA_b string `json:",omitempty"`
478 AaA string `json:",omitempty,case:ignore"`
479 AAa string `json:",omitempty,case:ignore"`
480 Aaa string `json:",omitempty"`
481 X jsontext.Value `json:",inline"`
482 }
483 structNoCaseInlineMapStringAny struct {
484 AAA string `json:",omitempty"`
485 AaA string `json:",omitempty,case:ignore"`
486 AAa string `json:",omitempty,case:ignore"`
487 Aaa string `json:",omitempty"`
488 X jsonObject `json:",inline"`
489 }
490
491 allMethods struct {
492 method string
493 value []byte
494 }
495 allMethodsExceptJSONv2 struct {
496 allMethods
497 MarshalJSONTo struct{}
498 UnmarshalJSONFrom struct{}
499 }
500 allMethodsExceptJSONv1 struct {
501 allMethods
502 MarshalJSON struct{}
503 UnmarshalJSON struct{}
504 }
505 allMethodsExceptText struct {
506 allMethods
507 MarshalText struct{}
508 UnmarshalText struct{}
509 }
510 onlyMethodJSONv2 struct {
511 allMethods
512 MarshalJSON struct{}
513 UnmarshalJSON struct{}
514 MarshalText struct{}
515 UnmarshalText struct{}
516 }
517 onlyMethodJSONv1 struct {
518 allMethods
519 MarshalJSONTo struct{}
520 UnmarshalJSONFrom struct{}
521 MarshalText struct{}
522 UnmarshalText struct{}
523 }
524 onlyMethodText struct {
525 allMethods
526 MarshalJSONTo struct{}
527 UnmarshalJSONFrom struct{}
528 MarshalJSON struct{}
529 UnmarshalJSON struct{}
530 }
531
532 unsupportedMethodJSONv2 map[string]int
533
534 structMethodJSONv2 struct{ value string }
535 structMethodJSONv1 struct{ value string }
536 structMethodText struct{ value string }
537
538 marshalJSONv2Func func(*jsontext.Encoder) error
539 marshalJSONv1Func func() ([]byte, error)
540 appendTextFunc func([]byte) ([]byte, error)
541 marshalTextFunc func() ([]byte, error)
542 unmarshalJSONv2Func func(*jsontext.Decoder) error
543 unmarshalJSONv1Func func([]byte) error
544 unmarshalTextFunc func([]byte) error
545
546 nocaseString string
547
548 stringMarshalEmpty string
549 stringMarshalNonEmpty string
550 bytesMarshalEmpty []byte
551 bytesMarshalNonEmpty []byte
552 mapMarshalEmpty map[string]string
553 mapMarshalNonEmpty map[string]string
554 sliceMarshalEmpty []string
555 sliceMarshalNonEmpty []string
556
557 valueAlwaysZero string
558 valueNeverZero string
559 pointerAlwaysZero string
560 pointerNeverZero string
561
562 valueStringer struct{}
563 pointerStringer struct{}
564
565 cyclicA struct {
566 B1 cyclicB `json:",inline"`
567 B2 cyclicB `json:",inline"`
568 }
569 cyclicB struct {
570 F int
571 A *cyclicA `json:",inline"`
572 }
573 )
574
575 func (structUnexportedEmbeddedMethodTag) MarshalText() {}
576 func (structUnexportedEmbeddedMethodTag) AppendText() {}
577
578 func (p *allMethods) MarshalJSONTo(enc *jsontext.Encoder) error {
579 if got, want := "MarshalJSONTo", p.method; got != want {
580 return fmt.Errorf("called wrong method: got %v, want %v", got, want)
581 }
582 return enc.WriteValue(p.value)
583 }
584 func (p *allMethods) MarshalJSON() ([]byte, error) {
585 if got, want := "MarshalJSON", p.method; got != want {
586 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
587 }
588 return p.value, nil
589 }
590 func (p *allMethods) MarshalText() ([]byte, error) {
591 if got, want := "MarshalText", p.method; got != want {
592 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
593 }
594 return p.value, nil
595 }
596
597 func (p *allMethods) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
598 p.method = "UnmarshalJSONFrom"
599 val, err := dec.ReadValue()
600 p.value = val
601 return err
602 }
603 func (p *allMethods) UnmarshalJSON(val []byte) error {
604 p.method = "UnmarshalJSON"
605 p.value = val
606 return nil
607 }
608 func (p *allMethods) UnmarshalText(val []byte) error {
609 p.method = "UnmarshalText"
610 p.value = val
611 return nil
612 }
613
614 func (s *unsupportedMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
615 (*s)["called"] += 1
616 return errors.ErrUnsupported
617 }
618 func (s *unsupportedMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
619 (*s)["called"] += 1
620 return errors.ErrUnsupported
621 }
622
623 func (s structMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
624 return enc.WriteToken(jsontext.String(s.value))
625 }
626 func (s *structMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
627 tok, err := dec.ReadToken()
628 if err != nil {
629 return err
630 }
631 if k := tok.Kind(); k != '"' {
632 return EU(nil).withType(k, T[structMethodJSONv2]())
633 }
634 s.value = tok.String()
635 return nil
636 }
637
638 func (s structMethodJSONv1) MarshalJSON() ([]byte, error) {
639 return jsontext.AppendQuote(nil, s.value)
640 }
641 func (s *structMethodJSONv1) UnmarshalJSON(b []byte) error {
642 if k := jsontext.Value(b).Kind(); k != '"' {
643 return EU(nil).withType(k, T[structMethodJSONv1]())
644 }
645 b, _ = jsontext.AppendUnquote(nil, b)
646 s.value = string(b)
647 return nil
648 }
649
650 func (s structMethodText) MarshalText() ([]byte, error) {
651 return []byte(s.value), nil
652 }
653 func (s *structMethodText) UnmarshalText(b []byte) error {
654 s.value = string(b)
655 return nil
656 }
657
658 func (f marshalJSONv2Func) MarshalJSONTo(enc *jsontext.Encoder) error {
659 return f(enc)
660 }
661 func (f marshalJSONv1Func) MarshalJSON() ([]byte, error) {
662 return f()
663 }
664 func (f appendTextFunc) AppendText(b []byte) ([]byte, error) {
665 return f(b)
666 }
667 func (f marshalTextFunc) MarshalText() ([]byte, error) {
668 return f()
669 }
670 func (f unmarshalJSONv2Func) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
671 return f(dec)
672 }
673 func (f unmarshalJSONv1Func) UnmarshalJSON(b []byte) error {
674 return f(b)
675 }
676 func (f unmarshalTextFunc) UnmarshalText(b []byte) error {
677 return f(b)
678 }
679
680 func (k nocaseString) MarshalText() ([]byte, error) {
681 return []byte(strings.ToLower(string(k))), nil
682 }
683 func (k *nocaseString) UnmarshalText(b []byte) error {
684 *k = nocaseString(strings.ToLower(string(b)))
685 return nil
686 }
687
688 func (stringMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`""`), nil }
689 func (stringMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`"value"`), nil }
690 func (bytesMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
691 func (bytesMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
692 func (mapMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`{}`), nil }
693 func (mapMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`{"key":"value"}`), nil }
694 func (sliceMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
695 func (sliceMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
696
697 func (valueAlwaysZero) IsZero() bool { return true }
698 func (valueNeverZero) IsZero() bool { return false }
699 func (*pointerAlwaysZero) IsZero() bool { return true }
700 func (*pointerNeverZero) IsZero() bool { return false }
701
702 func (valueStringer) String() string { return "" }
703 func (*pointerStringer) String() string { return "" }
704
705 func addr[T any](v T) *T {
706 return &v
707 }
708
709 func mustParseTime(layout, value string) time.Time {
710 t, err := time.Parse(layout, value)
711 if err != nil {
712 panic(err)
713 }
714 return t
715 }
716
717 var invalidFormatOption = &jsonopts.Struct{
718 ArshalValues: jsonopts.ArshalValues{FormatDepth: 1000, Format: "invalid"},
719 }
720
721 func TestMarshal(t *testing.T) {
722 tests := []struct {
723 name jsontest.CaseName
724 opts []Options
725 in any
726 want string
727 wantErr error
728
729 canonicalize bool
730 useWriter bool
731 skip bool
732 }{{
733 name: jsontest.Name("Nil"),
734 in: nil,
735 want: `null`,
736 }, {
737 name: jsontest.Name("Bools"),
738 in: []bool{false, true},
739 want: `[false,true]`,
740 }, {
741 name: jsontest.Name("Bools/Named"),
742 in: []namedBool{false, true},
743 want: `[false,true]`,
744 }, {
745 name: jsontest.Name("Bools/NotStringified"),
746 opts: []Options{StringifyNumbers(true)},
747 in: []bool{false, true},
748 want: `[false,true]`,
749 }, {
750 name: jsontest.Name("Bools/StringifiedBool"),
751 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
752 in: []bool{false, true},
753 want: `["false","true"]`,
754 }, {
755 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
756 opts: []Options{invalidFormatOption},
757 in: true,
758 want: `true`,
759 }, {
760 name: jsontest.Name("Strings"),
761 in: []string{"", "hello", "世界"},
762 want: `["","hello","世界"]`,
763 }, {
764 name: jsontest.Name("Strings/Named"),
765 in: []namedString{"", "hello", "世界"},
766 want: `["","hello","世界"]`,
767 }, {
768 name: jsontest.Name("Strings/StringifiedBool"),
769 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
770 in: []string{"", "hello", "世界"},
771 want: `["\"\"","\"hello\"","\"世界\""]`,
772 }, {
773 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
774 opts: []Options{invalidFormatOption},
775 in: "string",
776 want: `"string"`,
777 }, {
778 name: jsontest.Name("Bytes"),
779 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
780 want: `["","","AQ==","AQI=","AQID"]`,
781 }, {
782 name: jsontest.Name("Bytes/FormatNilSliceAsNull"),
783 opts: []Options{FormatNilSliceAsNull(true)},
784 in: [][]byte{nil, {}},
785 want: `[null,""]`,
786 }, {
787 name: jsontest.Name("Bytes/Large"),
788 in: []byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on."),
789 want: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
790 }, {
791 name: jsontest.Name("Bytes/Named"),
792 in: []namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}},
793 want: `["","","AQ==","AQI=","AQID"]`,
794 }, {
795 name: jsontest.Name("Bytes/NotStringified"),
796 opts: []Options{StringifyNumbers(true)},
797 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
798 want: `["","","AQ==","AQI=","AQID"]`,
799 }, {
800
801
802 name: jsontest.Name("Bytes/Invariant"),
803 in: [][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
804 want: `[[],[],[1],[1,2],[1,2,3]]`,
805 }, {
806
807
808 name: jsontest.Name("Bytes/ByteArray"),
809 in: [5]byte{'h', 'e', 'l', 'l', 'o'},
810 want: `"aGVsbG8="`,
811 }, {
812
813
814 name: jsontest.Name("Bytes/NamedByteArray"),
815 in: [5]namedByte{'h', 'e', 'l', 'l', 'o'},
816 want: `[104,101,108,108,111]`,
817 }, {
818 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
819 opts: []Options{invalidFormatOption},
820 in: []byte("hello"),
821 want: `"aGVsbG8="`,
822 }, {
823 name: jsontest.Name("Ints"),
824 in: []any{
825 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
826 },
827 want: `[0,-128,-32768,-2147483648,-9223372036854775808,-6464]`,
828 }, {
829 name: jsontest.Name("Ints/Stringified"),
830 opts: []Options{StringifyNumbers(true)},
831 in: []any{
832 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
833 },
834 want: `["0","-128","-32768","-2147483648","-9223372036854775808","-6464"]`,
835 }, {
836 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
837 opts: []Options{invalidFormatOption},
838 in: int(0),
839 want: `0`,
840 }, {
841 name: jsontest.Name("Uints"),
842 in: []any{
843 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464), uintptr(1234),
844 },
845 want: `[0,255,65535,4294967295,18446744073709551615,6464,1234]`,
846 }, {
847 name: jsontest.Name("Uints/Stringified"),
848 opts: []Options{StringifyNumbers(true)},
849 in: []any{
850 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464),
851 },
852 want: `["0","255","65535","4294967295","18446744073709551615","6464"]`,
853 }, {
854 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
855 opts: []Options{invalidFormatOption},
856 in: uint(0),
857 want: `0`,
858 }, {
859 name: jsontest.Name("Floats"),
860 in: []any{
861 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
862 },
863 want: `[3.4028235e+38,1.7976931348623157e+308,64.64]`,
864 }, {
865 name: jsontest.Name("Floats/Stringified"),
866 opts: []Options{StringifyNumbers(true)},
867 in: []any{
868 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
869 },
870 want: `["3.4028235e+38","1.7976931348623157e+308","64.64"]`,
871 }, {
872 name: jsontest.Name("Floats/Invalid/NaN"),
873 opts: []Options{StringifyNumbers(true)},
874 in: math.NaN(),
875 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, float64Type),
876 }, {
877 name: jsontest.Name("Floats/Invalid/PositiveInfinity"),
878 in: math.Inf(+1),
879 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(+1))).withType(0, float64Type),
880 }, {
881 name: jsontest.Name("Floats/Invalid/NegativeInfinity"),
882 in: math.Inf(-1),
883 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(-1))).withType(0, float64Type),
884 }, {
885 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
886 opts: []Options{invalidFormatOption},
887 in: float64(0),
888 want: `0`,
889 }, {
890 name: jsontest.Name("Maps/InvalidKey/Bool"),
891 in: map[bool]string{false: "value"},
892 want: `{`,
893 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, boolType),
894 }, {
895 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
896 in: map[namedBool]string{false: "value"},
897 want: `{`,
898 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[namedBool]()),
899 }, {
900 name: jsontest.Name("Maps/InvalidKey/Array"),
901 in: map[[1]string]string{{"key"}: "value"},
902 want: `{`,
903 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[[1]string]()),
904 }, {
905 name: jsontest.Name("Maps/InvalidKey/Channel"),
906 in: map[chan string]string{make(chan string): "value"},
907 want: `{`,
908 wantErr: EM(nil).withPos(`{`, "").withType(0, T[chan string]()),
909 }, {
910 name: jsontest.Name("Maps/ValidKey/Int"),
911 in: map[int64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
912 canonicalize: true,
913 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
914 }, {
915 name: jsontest.Name("Maps/ValidKey/PointerInt"),
916 in: map[*int64]string{addr(int64(math.MinInt64)): "MinInt64", addr(int64(0)): "Zero", addr(int64(math.MaxInt64)): "MaxInt64"},
917 canonicalize: true,
918 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
919 }, {
920 name: jsontest.Name("Maps/DuplicateName/PointerInt"),
921 in: map[*int64]string{addr(int64(0)): "0", addr(int64(0)): "0"},
922 canonicalize: true,
923 want: `{"0":"0"`,
924 wantErr: newDuplicateNameError("", []byte(`"0"`), len64(`{"0":"0",`)),
925 }, {
926 name: jsontest.Name("Maps/ValidKey/NamedInt"),
927 in: map[namedInt64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
928 canonicalize: true,
929 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
930 }, {
931 name: jsontest.Name("Maps/ValidKey/Uint"),
932 in: map[uint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
933 canonicalize: true,
934 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
935 }, {
936 name: jsontest.Name("Maps/ValidKey/NamedUint"),
937 in: map[namedUint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
938 canonicalize: true,
939 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
940 }, {
941 name: jsontest.Name("Maps/ValidKey/Float"),
942 in: map[float64]string{3.14159: "value"},
943 want: `{"3.14159":"value"}`,
944 }, {
945 name: jsontest.Name("Maps/InvalidKey/Float/NaN"),
946 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
947 want: `{`,
948 wantErr: EM(errors.New("unsupported value: NaN")).withPos(`{`, "").withType(0, float64Type),
949 }, {
950 name: jsontest.Name("Maps/ValidKey/Interface"),
951 in: map[any]any{
952 "key": "key",
953 namedInt64(-64): int32(-32),
954 namedUint64(+64): uint32(+32),
955 namedFloat64(64.64): float32(32.32),
956 },
957 canonicalize: true,
958 want: `{"-64":-32,"64":32,"64.64":32.32,"key":"key"}`,
959 }, {
960 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8+AllowDuplicateNames"),
961 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
962 in: map[string]string{"\x80": "", "\x81": ""},
963 want: `{"�":"","�":""}`,
964 }, {
965 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8"),
966 opts: []Options{jsontext.AllowInvalidUTF8(true)},
967 in: map[string]string{"\x80": "", "\x81": ""},
968 want: `{"�":""`,
969 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":"",`)),
970 }, {
971 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
972 opts: []Options{jsontext.AllowDuplicateNames(true)},
973 in: map[nocaseString]string{"hello": "", "HELLO": ""},
974 want: `{"hello":"","hello":""}`,
975 }, {
976 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
977 in: map[nocaseString]string{"hello": "", "HELLO": ""},
978 want: `{"hello":""`,
979 wantErr: EM(newDuplicateNameError("", []byte(`"hello"`), len64(`{"hello":"",`))).withPos(`{"hello":"",`, "").withType(0, T[nocaseString]()),
980 }, {
981 name: jsontest.Name("Maps/DuplicateName/NaNs/Deterministic+AllowDuplicateNames"),
982 opts: []Options{
983 WithMarshalers(
984 MarshalFunc(func(v float64) ([]byte, error) { return []byte(`"NaN"`), nil }),
985 ),
986 Deterministic(true),
987 jsontext.AllowDuplicateNames(true),
988 },
989 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
990 want: `{"NaN":"NaN","NaN":"NaN"}`,
991 }, {
992 name: jsontest.Name("Maps/InvalidValue/Channel"),
993 in: map[string]chan string{
994 "key": nil,
995 },
996 want: `{"key"`,
997 wantErr: EM(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
998 }, {
999 name: jsontest.Name("Maps/String/Deterministic"),
1000 opts: []Options{Deterministic(true)},
1001 in: map[string]int{"a": 0, "b": 1, "c": 2},
1002 want: `{"a":0,"b":1,"c":2}`,
1003 }, {
1004 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
1005 opts: []Options{
1006 Deterministic(true),
1007 jsontext.AllowInvalidUTF8(true),
1008 jsontext.AllowDuplicateNames(false),
1009 },
1010 in: map[string]int{"\xff": 0, "\xfe": 1},
1011 want: `{"�":1`,
1012 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1,`)),
1013 }, {
1014 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
1015 opts: []Options{
1016 Deterministic(true),
1017 jsontext.AllowInvalidUTF8(true),
1018 jsontext.AllowDuplicateNames(true),
1019 },
1020 in: map[string]int{"\xff": 0, "\xfe": 1},
1021 want: `{"�":1,"�":0}`,
1022 }, {
1023 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs"),
1024 opts: []Options{
1025 Deterministic(true),
1026 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1027 if p := enc.StackPointer(); p != "/X" {
1028 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1029 }
1030 switch v {
1031 case "a":
1032 return enc.WriteToken(jsontext.String("b"))
1033 case "b":
1034 return enc.WriteToken(jsontext.String("a"))
1035 default:
1036 return fmt.Errorf("invalid value: %q", v)
1037 }
1038 })),
1039 },
1040 in: map[namedString]map[string]int{"X": {"a": -1, "b": 1}},
1041 want: `{"X":{"a":1,"b":-1}}`,
1042 }, {
1043 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+RejectDuplicateNames"),
1044 opts: []Options{
1045 Deterministic(true),
1046 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1047 if p := enc.StackPointer(); p != "/X" {
1048 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1049 }
1050 switch v {
1051 case "a", "b":
1052 return enc.WriteToken(jsontext.String("x"))
1053 default:
1054 return fmt.Errorf("invalid value: %q", v)
1055 }
1056 })),
1057 jsontext.AllowDuplicateNames(false),
1058 },
1059 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1060 want: `{"X":{"x":1`,
1061 wantErr: newDuplicateNameError("/X/x", nil, len64(`{"X":{"x":1,`)),
1062 }, {
1063 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+AllowDuplicateNames"),
1064 opts: []Options{
1065 Deterministic(true),
1066 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1067 if p := enc.StackPointer(); p != "/X" {
1068 return fmt.Errorf("invalid stack pointer: got %s, want /0", p)
1069 }
1070 switch v {
1071 case "a", "b":
1072 return enc.WriteToken(jsontext.String("x"))
1073 default:
1074 return fmt.Errorf("invalid value: %q", v)
1075 }
1076 })),
1077 jsontext.AllowDuplicateNames(true),
1078 },
1079 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1080
1081
1082 want: `{"X":{"x":1,"x":1}}`,
1083 }, {
1084 name: jsontest.Name("Maps/RecursiveMap"),
1085 in: recursiveMap{
1086 "fizz": {
1087 "foo": {},
1088 "bar": nil,
1089 },
1090 "buzz": nil,
1091 },
1092 canonicalize: true,
1093 want: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
1094 }, {
1095 name: jsontest.Name("Maps/CyclicMap"),
1096 in: func() recursiveMap {
1097 m := recursiveMap{"k": nil}
1098 m["k"] = m
1099 return m
1100 }(),
1101 want: strings.Repeat(`{"k":`, startDetectingCyclesAfter) + `{"k"`,
1102 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"k":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/k", startDetectingCyclesAfter+1))).withType(0, T[recursiveMap]()),
1103 }, {
1104 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
1105 opts: []Options{invalidFormatOption},
1106 in: map[string]string{},
1107 want: `{}`,
1108 }, {
1109 name: jsontest.Name("Structs/Empty"),
1110 in: structEmpty{},
1111 want: `{}`,
1112 }, {
1113 name: jsontest.Name("Structs/UnexportedIgnored"),
1114 in: structUnexportedIgnored{ignored: "ignored"},
1115 want: `{}`,
1116 }, {
1117 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
1118 in: structIgnoredUnexportedEmbedded{namedString: "ignored"},
1119 want: `{}`,
1120 }, {
1121 name: jsontest.Name("Structs/WeirdNames"),
1122 in: structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"},
1123 want: `{"":"empty",",":"comma","\"":"quote"}`,
1124 skip: !internal.ExpJSONFormat,
1125 }, {
1126 name: jsontest.Name("Structs/EscapedNames"),
1127 opts: []Options{jsontext.EscapeForHTML(true), jsontext.EscapeForJS(true)},
1128 in: struct {
1129 S string "json:\"'abc<>&\u2028\u2029xyz'\""
1130 M any
1131 I structInlineTextValue
1132 }{
1133 S: "abc<>&\u2028\u2029xyz",
1134 M: map[string]string{"abc<>&\u2028\u2029xyz": "abc<>&\u2028\u2029xyz"},
1135 I: structInlineTextValue{X: jsontext.Value(`{"abc<>&` + "\u2028\u2029" + `xyz":"abc<>&` + "\u2028\u2029" + `xyz"}`)},
1136 },
1137 want: `{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz","M":{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz"},"I":{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz"}}`,
1138 skip: !internal.ExpJSONFormat,
1139 }, {
1140 name: jsontest.Name("Structs/NoCase"),
1141 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1142 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1143 }, {
1144 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames"),
1145 opts: []Options{MatchCaseInsensitiveNames(true)},
1146 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1147 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1148 }, {
1149 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
1150 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
1151 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1152 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1153 }, {
1154 name: jsontest.Name("Structs/Normal"),
1155 opts: []Options{jsontext.Multiline(true)},
1156 in: structAll{
1157 Bool: true,
1158 String: "hello",
1159 Bytes: []byte{1, 2, 3},
1160 Int: -64,
1161 Uint: +64,
1162 Float: 3.14159,
1163 Map: map[string]string{"key": "value"},
1164 StructScalars: structScalars{
1165 Bool: true,
1166 String: "hello",
1167 Bytes: []byte{1, 2, 3},
1168 Int: -64,
1169 Uint: +64,
1170 Float: 3.14159,
1171 },
1172 StructMaps: structMaps{
1173 MapBool: map[string]bool{"": true},
1174 MapString: map[string]string{"": "hello"},
1175 MapBytes: map[string][]byte{"": {1, 2, 3}},
1176 MapInt: map[string]int64{"": -64},
1177 MapUint: map[string]uint64{"": +64},
1178 MapFloat: map[string]float64{"": 3.14159},
1179 },
1180 StructSlices: structSlices{
1181 SliceBool: []bool{true},
1182 SliceString: []string{"hello"},
1183 SliceBytes: [][]byte{{1, 2, 3}},
1184 SliceInt: []int64{-64},
1185 SliceUint: []uint64{+64},
1186 SliceFloat: []float64{3.14159},
1187 },
1188 Slice: []string{"fizz", "buzz"},
1189 Array: [1]string{"goodbye"},
1190 Pointer: new(structAll),
1191 Interface: (*structAll)(nil),
1192 },
1193 want: `{
1194 "Bool": true,
1195 "String": "hello",
1196 "Bytes": "AQID",
1197 "Int": -64,
1198 "Uint": 64,
1199 "Float": 3.14159,
1200 "Map": {
1201 "key": "value"
1202 },
1203 "StructScalars": {
1204 "Bool": true,
1205 "String": "hello",
1206 "Bytes": "AQID",
1207 "Int": -64,
1208 "Uint": 64,
1209 "Float": 3.14159
1210 },
1211 "StructMaps": {
1212 "MapBool": {
1213 "": true
1214 },
1215 "MapString": {
1216 "": "hello"
1217 },
1218 "MapBytes": {
1219 "": "AQID"
1220 },
1221 "MapInt": {
1222 "": -64
1223 },
1224 "MapUint": {
1225 "": 64
1226 },
1227 "MapFloat": {
1228 "": 3.14159
1229 }
1230 },
1231 "StructSlices": {
1232 "SliceBool": [
1233 true
1234 ],
1235 "SliceString": [
1236 "hello"
1237 ],
1238 "SliceBytes": [
1239 "AQID"
1240 ],
1241 "SliceInt": [
1242 -64
1243 ],
1244 "SliceUint": [
1245 64
1246 ],
1247 "SliceFloat": [
1248 3.14159
1249 ]
1250 },
1251 "Slice": [
1252 "fizz",
1253 "buzz"
1254 ],
1255 "Array": [
1256 "goodbye"
1257 ],
1258 "Pointer": {
1259 "Bool": false,
1260 "String": "",
1261 "Bytes": "",
1262 "Int": 0,
1263 "Uint": 0,
1264 "Float": 0,
1265 "Map": {},
1266 "StructScalars": {
1267 "Bool": false,
1268 "String": "",
1269 "Bytes": "",
1270 "Int": 0,
1271 "Uint": 0,
1272 "Float": 0
1273 },
1274 "StructMaps": {
1275 "MapBool": {},
1276 "MapString": {},
1277 "MapBytes": {},
1278 "MapInt": {},
1279 "MapUint": {},
1280 "MapFloat": {}
1281 },
1282 "StructSlices": {
1283 "SliceBool": [],
1284 "SliceString": [],
1285 "SliceBytes": [],
1286 "SliceInt": [],
1287 "SliceUint": [],
1288 "SliceFloat": []
1289 },
1290 "Slice": [],
1291 "Array": [
1292 ""
1293 ],
1294 "Pointer": null,
1295 "Interface": null
1296 },
1297 "Interface": null
1298 }`,
1299 }, {
1300 name: jsontest.Name("Structs/SpaceAfterColonAndComma"),
1301 opts: []Options{jsontext.SpaceAfterColon(true), jsontext.SpaceAfterComma(true)},
1302 in: structOmitZeroAll{Int: 1, Uint: 1},
1303 want: `{"Int": 1, "Uint": 1}`,
1304 }, {
1305 name: jsontest.Name("Structs/SpaceAfterColon"),
1306 opts: []Options{jsontext.SpaceAfterColon(true)},
1307 in: structOmitZeroAll{Int: 1, Uint: 1},
1308 want: `{"Int": 1,"Uint": 1}`,
1309 }, {
1310 name: jsontest.Name("Structs/SpaceAfterComma"),
1311 opts: []Options{jsontext.SpaceAfterComma(true)},
1312 in: structOmitZeroAll{Int: 1, Uint: 1, Slice: []string{"a", "b"}},
1313 want: `{"Int":1, "Uint":1, "Slice":["a", "b"]}`,
1314 }, {
1315 name: jsontest.Name("Structs/Stringified"),
1316 opts: []Options{jsontext.Multiline(true)},
1317 in: structStringifiedAll{
1318 Bool: true,
1319 String: "hello",
1320 Bytes: []byte{1, 2, 3},
1321 Int: -64,
1322 Uint: +64,
1323 Float: 3.14159,
1324 Map: map[string]string{"key": "value"},
1325 StructScalars: structScalars{
1326 Bool: true,
1327 String: "hello",
1328 Bytes: []byte{1, 2, 3},
1329 Int: -64,
1330 Uint: +64,
1331 Float: 3.14159,
1332 },
1333 StructMaps: structMaps{
1334 MapBool: map[string]bool{"": true},
1335 MapString: map[string]string{"": "hello"},
1336 MapBytes: map[string][]byte{"": {1, 2, 3}},
1337 MapInt: map[string]int64{"": -64},
1338 MapUint: map[string]uint64{"": +64},
1339 MapFloat: map[string]float64{"": 3.14159},
1340 },
1341 StructSlices: structSlices{
1342 SliceBool: []bool{true},
1343 SliceString: []string{"hello"},
1344 SliceBytes: [][]byte{{1, 2, 3}},
1345 SliceInt: []int64{-64},
1346 SliceUint: []uint64{+64},
1347 SliceFloat: []float64{3.14159},
1348 },
1349 Slice: []string{"fizz", "buzz"},
1350 Array: [1]string{"goodbye"},
1351 Pointer: new(structStringifiedAll),
1352 Interface: (*structStringifiedAll)(nil),
1353 },
1354 want: `{
1355 "Bool": true,
1356 "String": "hello",
1357 "Bytes": "AQID",
1358 "Int": "-64",
1359 "Uint": "64",
1360 "Float": "3.14159",
1361 "Map": {
1362 "key": "value"
1363 },
1364 "StructScalars": {
1365 "Bool": true,
1366 "String": "hello",
1367 "Bytes": "AQID",
1368 "Int": "-64",
1369 "Uint": "64",
1370 "Float": "3.14159"
1371 },
1372 "StructMaps": {
1373 "MapBool": {
1374 "": true
1375 },
1376 "MapString": {
1377 "": "hello"
1378 },
1379 "MapBytes": {
1380 "": "AQID"
1381 },
1382 "MapInt": {
1383 "": "-64"
1384 },
1385 "MapUint": {
1386 "": "64"
1387 },
1388 "MapFloat": {
1389 "": "3.14159"
1390 }
1391 },
1392 "StructSlices": {
1393 "SliceBool": [
1394 true
1395 ],
1396 "SliceString": [
1397 "hello"
1398 ],
1399 "SliceBytes": [
1400 "AQID"
1401 ],
1402 "SliceInt": [
1403 "-64"
1404 ],
1405 "SliceUint": [
1406 "64"
1407 ],
1408 "SliceFloat": [
1409 "3.14159"
1410 ]
1411 },
1412 "Slice": [
1413 "fizz",
1414 "buzz"
1415 ],
1416 "Array": [
1417 "goodbye"
1418 ],
1419 "Pointer": {
1420 "Bool": false,
1421 "String": "",
1422 "Bytes": "",
1423 "Int": "0",
1424 "Uint": "0",
1425 "Float": "0",
1426 "Map": {},
1427 "StructScalars": {
1428 "Bool": false,
1429 "String": "",
1430 "Bytes": "",
1431 "Int": "0",
1432 "Uint": "0",
1433 "Float": "0"
1434 },
1435 "StructMaps": {
1436 "MapBool": {},
1437 "MapString": {},
1438 "MapBytes": {},
1439 "MapInt": {},
1440 "MapUint": {},
1441 "MapFloat": {}
1442 },
1443 "StructSlices": {
1444 "SliceBool": [],
1445 "SliceString": [],
1446 "SliceBytes": [],
1447 "SliceInt": [],
1448 "SliceUint": [],
1449 "SliceFloat": []
1450 },
1451 "Slice": [],
1452 "Array": [
1453 ""
1454 ],
1455 "Pointer": null,
1456 "Interface": null
1457 },
1458 "Interface": null
1459 }`,
1460 }, {
1461 name: jsontest.Name("Structs/LegacyStringified"),
1462 opts: []Options{jsontext.Multiline(true), jsonflags.StringifyWithLegacySemantics | 1},
1463 in: structStringifiedAll{
1464 Bool: true,
1465 String: "hello",
1466 Bytes: []byte{1, 2, 3},
1467 Int: -64,
1468 Uint: +64,
1469 Float: 3.14159,
1470 Map: map[string]string{"key": "value"},
1471 StructScalars: structScalars{
1472 Bool: true,
1473 String: "hello",
1474 Bytes: []byte{1, 2, 3},
1475 Int: -64,
1476 Uint: +64,
1477 Float: 3.14159,
1478 },
1479 StructMaps: structMaps{
1480 MapBool: map[string]bool{"": true},
1481 MapString: map[string]string{"": "hello"},
1482 MapBytes: map[string][]byte{"": {1, 2, 3}},
1483 MapInt: map[string]int64{"": -64},
1484 MapUint: map[string]uint64{"": +64},
1485 MapFloat: map[string]float64{"": 3.14159},
1486 },
1487 StructSlices: structSlices{
1488 SliceBool: []bool{true},
1489 SliceString: []string{"hello"},
1490 SliceBytes: [][]byte{{1, 2, 3}},
1491 SliceInt: []int64{-64},
1492 SliceUint: []uint64{+64},
1493 SliceFloat: []float64{3.14159},
1494 },
1495 Slice: []string{"fizz", "buzz"},
1496 Array: [1]string{"goodbye"},
1497 Pointer: new(structStringifiedAll),
1498 Interface: (*structStringifiedAll)(nil),
1499 },
1500 want: `{
1501 "Bool": "true",
1502 "String": "\"hello\"",
1503 "Bytes": "AQID",
1504 "Int": "-64",
1505 "Uint": "64",
1506 "Float": "3.14159",
1507 "Map": {
1508 "key": "value"
1509 },
1510 "StructScalars": {
1511 "Bool": true,
1512 "String": "hello",
1513 "Bytes": "AQID",
1514 "Int": -64,
1515 "Uint": 64,
1516 "Float": 3.14159
1517 },
1518 "StructMaps": {
1519 "MapBool": {
1520 "": true
1521 },
1522 "MapString": {
1523 "": "hello"
1524 },
1525 "MapBytes": {
1526 "": "AQID"
1527 },
1528 "MapInt": {
1529 "": -64
1530 },
1531 "MapUint": {
1532 "": 64
1533 },
1534 "MapFloat": {
1535 "": 3.14159
1536 }
1537 },
1538 "StructSlices": {
1539 "SliceBool": [
1540 true
1541 ],
1542 "SliceString": [
1543 "hello"
1544 ],
1545 "SliceBytes": [
1546 "AQID"
1547 ],
1548 "SliceInt": [
1549 -64
1550 ],
1551 "SliceUint": [
1552 64
1553 ],
1554 "SliceFloat": [
1555 3.14159
1556 ]
1557 },
1558 "Slice": [
1559 "fizz",
1560 "buzz"
1561 ],
1562 "Array": [
1563 "goodbye"
1564 ],
1565 "Pointer": {
1566 "Bool": "false",
1567 "String": "\"\"",
1568 "Bytes": "",
1569 "Int": "0",
1570 "Uint": "0",
1571 "Float": "0",
1572 "Map": {},
1573 "StructScalars": {
1574 "Bool": false,
1575 "String": "",
1576 "Bytes": "",
1577 "Int": 0,
1578 "Uint": 0,
1579 "Float": 0
1580 },
1581 "StructMaps": {
1582 "MapBool": {},
1583 "MapString": {},
1584 "MapBytes": {},
1585 "MapInt": {},
1586 "MapUint": {},
1587 "MapFloat": {}
1588 },
1589 "StructSlices": {
1590 "SliceBool": [],
1591 "SliceString": [],
1592 "SliceBytes": [],
1593 "SliceInt": [],
1594 "SliceUint": [],
1595 "SliceFloat": []
1596 },
1597 "Slice": [],
1598 "Array": [
1599 ""
1600 ],
1601 "Pointer": null,
1602 "Interface": null
1603 },
1604 "Interface": null
1605 }`,
1606 }, {
1607 name: jsontest.Name("Structs/OmitZero/Zero"),
1608 in: structOmitZeroAll{},
1609 want: `{}`,
1610 }, {
1611 name: jsontest.Name("Structs/OmitZeroOption/Zero"),
1612 opts: []Options{OmitZeroStructFields(true)},
1613 in: structAll{},
1614 want: `{}`,
1615 }, {
1616 name: jsontest.Name("Structs/OmitZero/NonZero"),
1617 opts: []Options{jsontext.Multiline(true)},
1618 in: structOmitZeroAll{
1619 Bool: true,
1620 String: " ",
1621 Bytes: []byte{},
1622 Int: 1,
1623 Uint: 1,
1624 Float: math.SmallestNonzeroFloat64,
1625 Map: map[string]string{},
1626 StructScalars: structScalars{unexported: true},
1627 StructSlices: structSlices{Ignored: true},
1628 StructMaps: structMaps{MapBool: map[string]bool{}},
1629 Slice: []string{},
1630 Array: [1]string{" "},
1631 Pointer: new(structOmitZeroAll),
1632 Interface: (*structOmitZeroAll)(nil),
1633 },
1634 want: `{
1635 "Bool": true,
1636 "String": " ",
1637 "Bytes": "",
1638 "Int": 1,
1639 "Uint": 1,
1640 "Float": 5e-324,
1641 "Map": {},
1642 "StructScalars": {
1643 "Bool": false,
1644 "String": "",
1645 "Bytes": "",
1646 "Int": 0,
1647 "Uint": 0,
1648 "Float": 0
1649 },
1650 "StructMaps": {
1651 "MapBool": {},
1652 "MapString": {},
1653 "MapBytes": {},
1654 "MapInt": {},
1655 "MapUint": {},
1656 "MapFloat": {}
1657 },
1658 "StructSlices": {
1659 "SliceBool": [],
1660 "SliceString": [],
1661 "SliceBytes": [],
1662 "SliceInt": [],
1663 "SliceUint": [],
1664 "SliceFloat": []
1665 },
1666 "Slice": [],
1667 "Array": [
1668 " "
1669 ],
1670 "Pointer": {},
1671 "Interface": null
1672 }`,
1673 }, {
1674 name: jsontest.Name("Structs/OmitZeroOption/NonZero"),
1675 opts: []Options{OmitZeroStructFields(true), jsontext.Multiline(true)},
1676 in: structAll{
1677 Bool: true,
1678 String: " ",
1679 Bytes: []byte{},
1680 Int: 1,
1681 Uint: 1,
1682 Float: math.SmallestNonzeroFloat64,
1683 Map: map[string]string{},
1684 StructScalars: structScalars{unexported: true},
1685 StructSlices: structSlices{Ignored: true},
1686 StructMaps: structMaps{MapBool: map[string]bool{}},
1687 Slice: []string{},
1688 Array: [1]string{" "},
1689 Pointer: new(structAll),
1690 Interface: (*structAll)(nil),
1691 },
1692 want: `{
1693 "Bool": true,
1694 "String": " ",
1695 "Bytes": "",
1696 "Int": 1,
1697 "Uint": 1,
1698 "Float": 5e-324,
1699 "Map": {},
1700 "StructScalars": {},
1701 "StructMaps": {
1702 "MapBool": {}
1703 },
1704 "StructSlices": {},
1705 "Slice": [],
1706 "Array": [
1707 " "
1708 ],
1709 "Pointer": {},
1710 "Interface": null
1711 }`,
1712 }, {
1713 name: jsontest.Name("Structs/OmitZeroMethod/Zero"),
1714 in: structOmitZeroMethodAll{},
1715 want: `{"ValueNeverZero":"","PointerNeverZero":""}`,
1716 }, {
1717 name: jsontest.Name("Structs/OmitZeroMethod/NonZero"),
1718 opts: []Options{jsontext.Multiline(true)},
1719 in: structOmitZeroMethodAll{
1720 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1721 ValueNeverZero: valueNeverZero("nonzero"),
1722 PointerAlwaysZero: pointerAlwaysZero("nonzero"),
1723 PointerNeverZero: pointerNeverZero("nonzero"),
1724 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1725 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1726 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1727 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1728 PointerPointerValueAlwaysZero: addr(addr(valueAlwaysZero("nonzero"))),
1729 PointerPointerValueNeverZero: addr(addr(valueNeverZero("nonzero"))),
1730 PointerPointerPointerAlwaysZero: addr(addr(pointerAlwaysZero("nonzero"))),
1731 PointerPointerPointerNeverZero: addr(addr(pointerNeverZero("nonzero"))),
1732 },
1733 want: `{
1734 "ValueNeverZero": "nonzero",
1735 "PointerNeverZero": "nonzero",
1736 "PointerValueNeverZero": "nonzero",
1737 "PointerPointerNeverZero": "nonzero",
1738 "PointerPointerValueAlwaysZero": "nonzero",
1739 "PointerPointerValueNeverZero": "nonzero",
1740 "PointerPointerPointerAlwaysZero": "nonzero",
1741 "PointerPointerPointerNeverZero": "nonzero"
1742 }`,
1743 }, {
1744 name: jsontest.Name("Structs/OmitZeroMethod/Interface/Zero"),
1745 opts: []Options{jsontext.Multiline(true)},
1746 in: structOmitZeroMethodInterfaceAll{},
1747 want: `{}`,
1748 }, {
1749 name: jsontest.Name("Structs/OmitZeroMethod/Interface/PartialZero"),
1750 opts: []Options{jsontext.Multiline(true)},
1751 in: structOmitZeroMethodInterfaceAll{
1752 ValueAlwaysZero: valueAlwaysZero(""),
1753 ValueNeverZero: valueNeverZero(""),
1754 PointerValueAlwaysZero: (*valueAlwaysZero)(nil),
1755 PointerValueNeverZero: (*valueNeverZero)(nil),
1756 PointerPointerAlwaysZero: (*pointerAlwaysZero)(nil),
1757 PointerPointerNeverZero: (*pointerNeverZero)(nil),
1758 },
1759 want: `{
1760 "ValueNeverZero": ""
1761 }`,
1762 }, {
1763 name: jsontest.Name("Structs/OmitZeroMethod/Interface/NonZero"),
1764 opts: []Options{jsontext.Multiline(true)},
1765 in: structOmitZeroMethodInterfaceAll{
1766 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1767 ValueNeverZero: valueNeverZero("nonzero"),
1768 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1769 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1770 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1771 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1772 },
1773 want: `{
1774 "ValueNeverZero": "nonzero",
1775 "PointerValueNeverZero": "nonzero",
1776 "PointerPointerNeverZero": "nonzero"
1777 }`,
1778 }, {
1779 name: jsontest.Name("Structs/OmitEmpty/Zero"),
1780 opts: []Options{jsontext.Multiline(true)},
1781 in: structOmitEmptyAll{},
1782 want: `{
1783 "Bool": false,
1784 "StringNonEmpty": "value",
1785 "BytesNonEmpty": [
1786 "value"
1787 ],
1788 "Float": 0,
1789 "MapNonEmpty": {
1790 "key": "value"
1791 },
1792 "SliceNonEmpty": [
1793 "value"
1794 ]
1795 }`,
1796 }, {
1797 name: jsontest.Name("Structs/OmitEmpty/EmptyNonZero"),
1798 opts: []Options{jsontext.Multiline(true)},
1799 in: structOmitEmptyAll{
1800 String: string(""),
1801 StringEmpty: stringMarshalEmpty(""),
1802 StringNonEmpty: stringMarshalNonEmpty(""),
1803 PointerString: addr(string("")),
1804 PointerStringEmpty: addr(stringMarshalEmpty("")),
1805 PointerStringNonEmpty: addr(stringMarshalNonEmpty("")),
1806 Bytes: []byte(""),
1807 BytesEmpty: bytesMarshalEmpty([]byte("")),
1808 BytesNonEmpty: bytesMarshalNonEmpty([]byte("")),
1809 PointerBytes: addr([]byte("")),
1810 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte(""))),
1811 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte(""))),
1812 Map: map[string]string{},
1813 MapEmpty: mapMarshalEmpty{},
1814 MapNonEmpty: mapMarshalNonEmpty{},
1815 PointerMap: addr(map[string]string{}),
1816 PointerMapEmpty: addr(mapMarshalEmpty{}),
1817 PointerMapNonEmpty: addr(mapMarshalNonEmpty{}),
1818 Slice: []string{},
1819 SliceEmpty: sliceMarshalEmpty{},
1820 SliceNonEmpty: sliceMarshalNonEmpty{},
1821 PointerSlice: addr([]string{}),
1822 PointerSliceEmpty: addr(sliceMarshalEmpty{}),
1823 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{}),
1824 Pointer: &structOmitZeroEmptyAll{},
1825 Interface: []string{},
1826 },
1827 want: `{
1828 "Bool": false,
1829 "StringNonEmpty": "value",
1830 "PointerStringNonEmpty": "value",
1831 "BytesNonEmpty": [
1832 "value"
1833 ],
1834 "PointerBytesNonEmpty": [
1835 "value"
1836 ],
1837 "Float": 0,
1838 "MapNonEmpty": {
1839 "key": "value"
1840 },
1841 "PointerMapNonEmpty": {
1842 "key": "value"
1843 },
1844 "SliceNonEmpty": [
1845 "value"
1846 ],
1847 "PointerSliceNonEmpty": [
1848 "value"
1849 ]
1850 }`,
1851 }, {
1852 name: jsontest.Name("Structs/OmitEmpty/NonEmpty"),
1853 opts: []Options{jsontext.Multiline(true)},
1854 in: structOmitEmptyAll{
1855 Bool: true,
1856 PointerBool: addr(true),
1857 String: string("value"),
1858 StringEmpty: stringMarshalEmpty("value"),
1859 StringNonEmpty: stringMarshalNonEmpty("value"),
1860 PointerString: addr(string("value")),
1861 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1862 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1863 Bytes: []byte("value"),
1864 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1865 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1866 PointerBytes: addr([]byte("value")),
1867 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1868 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1869 Float: math.Copysign(0, -1),
1870 PointerFloat: addr(math.Copysign(0, -1)),
1871 Map: map[string]string{"": ""},
1872 MapEmpty: mapMarshalEmpty{"key": "value"},
1873 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1874 PointerMap: addr(map[string]string{"": ""}),
1875 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1876 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1877 Slice: []string{""},
1878 SliceEmpty: sliceMarshalEmpty{"value"},
1879 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1880 PointerSlice: addr([]string{""}),
1881 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1882 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1883 Pointer: &structOmitZeroEmptyAll{Float: math.SmallestNonzeroFloat64},
1884 Interface: []string{""},
1885 },
1886 want: `{
1887 "Bool": true,
1888 "PointerBool": true,
1889 "String": "value",
1890 "StringNonEmpty": "value",
1891 "PointerString": "value",
1892 "PointerStringNonEmpty": "value",
1893 "Bytes": "dmFsdWU=",
1894 "BytesNonEmpty": [
1895 "value"
1896 ],
1897 "PointerBytes": "dmFsdWU=",
1898 "PointerBytesNonEmpty": [
1899 "value"
1900 ],
1901 "Float": -0,
1902 "PointerFloat": -0,
1903 "Map": {
1904 "": ""
1905 },
1906 "MapNonEmpty": {
1907 "key": "value"
1908 },
1909 "PointerMap": {
1910 "": ""
1911 },
1912 "PointerMapNonEmpty": {
1913 "key": "value"
1914 },
1915 "Slice": [
1916 ""
1917 ],
1918 "SliceNonEmpty": [
1919 "value"
1920 ],
1921 "PointerSlice": [
1922 ""
1923 ],
1924 "PointerSliceNonEmpty": [
1925 "value"
1926 ],
1927 "Pointer": {
1928 "Float": 5e-324
1929 },
1930 "Interface": [
1931 ""
1932 ]
1933 }`,
1934 }, {
1935 name: jsontest.Name("Structs/OmitEmpty/Legacy/Zero"),
1936 opts: []Options{jsonflags.OmitEmptyWithLegacySemantics | 1},
1937 in: structOmitEmptyAll{},
1938 want: `{}`,
1939 }, {
1940 name: jsontest.Name("Structs/OmitEmpty/Legacy/NonEmpty"),
1941 opts: []Options{jsontext.Multiline(true), jsonflags.OmitEmptyWithLegacySemantics | 1},
1942 in: structOmitEmptyAll{
1943 Bool: true,
1944 PointerBool: addr(true),
1945 String: string("value"),
1946 StringEmpty: stringMarshalEmpty("value"),
1947 StringNonEmpty: stringMarshalNonEmpty("value"),
1948 PointerString: addr(string("value")),
1949 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1950 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1951 Bytes: []byte("value"),
1952 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1953 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1954 PointerBytes: addr([]byte("value")),
1955 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1956 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1957 Float: math.Copysign(0, -1),
1958 PointerFloat: addr(math.Copysign(0, -1)),
1959 Map: map[string]string{"": ""},
1960 MapEmpty: mapMarshalEmpty{"key": "value"},
1961 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1962 PointerMap: addr(map[string]string{"": ""}),
1963 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1964 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1965 Slice: []string{""},
1966 SliceEmpty: sliceMarshalEmpty{"value"},
1967 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1968 PointerSlice: addr([]string{""}),
1969 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1970 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1971 Pointer: &structOmitZeroEmptyAll{Float: math.Copysign(0, -1)},
1972 Interface: []string{""},
1973 },
1974 want: `{
1975 "Bool": true,
1976 "PointerBool": true,
1977 "String": "value",
1978 "StringEmpty": "",
1979 "StringNonEmpty": "value",
1980 "PointerString": "value",
1981 "PointerStringEmpty": "",
1982 "PointerStringNonEmpty": "value",
1983 "Bytes": "dmFsdWU=",
1984 "BytesEmpty": [],
1985 "BytesNonEmpty": [
1986 "value"
1987 ],
1988 "PointerBytes": "dmFsdWU=",
1989 "PointerBytesEmpty": [],
1990 "PointerBytesNonEmpty": [
1991 "value"
1992 ],
1993 "PointerFloat": -0,
1994 "Map": {
1995 "": ""
1996 },
1997 "MapEmpty": {},
1998 "MapNonEmpty": {
1999 "key": "value"
2000 },
2001 "PointerMap": {
2002 "": ""
2003 },
2004 "PointerMapEmpty": {},
2005 "PointerMapNonEmpty": {
2006 "key": "value"
2007 },
2008 "Slice": [
2009 ""
2010 ],
2011 "SliceEmpty": [],
2012 "SliceNonEmpty": [
2013 "value"
2014 ],
2015 "PointerSlice": [
2016 ""
2017 ],
2018 "PointerSliceEmpty": [],
2019 "PointerSliceNonEmpty": [
2020 "value"
2021 ],
2022 "Pointer": {},
2023 "Interface": [
2024 ""
2025 ]
2026 }`,
2027 }, {
2028 name: jsontest.Name("Structs/OmitEmpty/NonEmptyString"),
2029 in: struct {
2030 X string `json:",omitempty"`
2031 }{`"`},
2032 want: `{"X":"\""}`,
2033 }, {
2034 name: jsontest.Name("Structs/OmitZeroEmpty/Zero"),
2035 in: structOmitZeroEmptyAll{},
2036 want: `{}`,
2037 }, {
2038 name: jsontest.Name("Structs/OmitZeroEmpty/Empty"),
2039 in: structOmitZeroEmptyAll{
2040 Bytes: []byte{},
2041 Map: map[string]string{},
2042 Slice: []string{},
2043 Pointer: &structOmitZeroEmptyAll{},
2044 Interface: []string{},
2045 },
2046 want: `{}`,
2047 }, {
2048 name: jsontest.Name("Structs/OmitEmpty/PathologicalDepth"),
2049 in: func() any {
2050 type X struct {
2051 X *X `json:",omitempty"`
2052 }
2053 var make func(int) *X
2054 make = func(n int) *X {
2055 if n == 0 {
2056 return nil
2057 }
2058 return &X{make(n - 1)}
2059 }
2060 return make(100)
2061 }(),
2062 want: `{}`,
2063 useWriter: true,
2064 }, {
2065 name: jsontest.Name("Structs/OmitEmpty/PathologicalBreadth"),
2066 in: func() any {
2067 var fields []reflect.StructField
2068 for i := range 100 {
2069 fields = append(fields, reflect.StructField{
2070 Name: fmt.Sprintf("X%d", i),
2071 Type: T[stringMarshalEmpty](),
2072 Tag: `json:",omitempty"`,
2073 })
2074 }
2075 return reflect.New(reflect.StructOf(fields)).Interface()
2076 }(),
2077 want: `{}`,
2078 useWriter: true,
2079 }, {
2080 name: jsontest.Name("Structs/OmitEmpty/PathologicalTree"),
2081 in: func() any {
2082 type X struct {
2083 XL, XR *X `json:",omitempty"`
2084 }
2085 var make func(int) *X
2086 make = func(n int) *X {
2087 if n == 0 {
2088 return nil
2089 }
2090 return &X{make(n - 1), make(n - 1)}
2091 }
2092 return make(8)
2093 }(),
2094 want: `{}`,
2095 useWriter: true,
2096 }, {
2097 name: jsontest.Name("Structs/OmitZeroEmpty/NonEmpty"),
2098 in: structOmitZeroEmptyAll{
2099 Bytes: []byte("value"),
2100 Map: map[string]string{"": ""},
2101 Slice: []string{""},
2102 Pointer: &structOmitZeroEmptyAll{Bool: true},
2103 Interface: []string{""},
2104 },
2105 want: `{"Bytes":"dmFsdWU=","Map":{"":""},"Slice":[""],"Pointer":{"Bool":true},"Interface":[""]}`,
2106 }, {
2107 name: jsontest.Name("Structs/Format/Bytes"),
2108 opts: []Options{jsontext.Multiline(true)},
2109 in: structFormatBytes{
2110 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
2111 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2112 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2113 Base64: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"),
2114 Base64URL: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"),
2115 Array: []byte{1, 2, 3, 4},
2116 },
2117 want: `{
2118 "Base16": "0123456789abcdef",
2119 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
2120 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
2121 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
2122 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
2123 "Array": [
2124 1,
2125 2,
2126 3,
2127 4
2128 ]
2129 }`,
2130 skip: !internal.ExpJSONFormat,
2131 }, {
2132 name: jsontest.Name("Structs/Format/ArrayBytes"),
2133 opts: []Options{jsontext.Multiline(true)},
2134 in: structFormatArrayBytes{
2135 Base16: [4]byte{1, 2, 3, 4},
2136 Base32: [4]byte{1, 2, 3, 4},
2137 Base32Hex: [4]byte{1, 2, 3, 4},
2138 Base64: [4]byte{1, 2, 3, 4},
2139 Base64URL: [4]byte{1, 2, 3, 4},
2140 Array: [4]byte{1, 2, 3, 4},
2141 Default: [4]byte{1, 2, 3, 4},
2142 },
2143 want: `{
2144 "Base16": "01020304",
2145 "Base32": "AEBAGBA=",
2146 "Base32Hex": "0410610=",
2147 "Base64": "AQIDBA==",
2148 "Base64URL": "AQIDBA==",
2149 "Array": [
2150 1,
2151 2,
2152 3,
2153 4
2154 ],
2155 "Default": "AQIDBA=="
2156 }`,
2157 skip: !internal.ExpJSONFormat,
2158 }, {
2159 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
2160 opts: []Options{jsontext.Multiline(true), jsonflags.FormatByteArrayAsArray | jsonflags.FormatBytesWithLegacySemantics | 1},
2161 in: structFormatArrayBytes{
2162 Base16: [4]byte{1, 2, 3, 4},
2163 Base32: [4]byte{1, 2, 3, 4},
2164 Base32Hex: [4]byte{1, 2, 3, 4},
2165 Base64: [4]byte{1, 2, 3, 4},
2166 Base64URL: [4]byte{1, 2, 3, 4},
2167 Array: [4]byte{1, 2, 3, 4},
2168 Default: [4]byte{1, 2, 3, 4},
2169 },
2170 want: `{
2171 "Base16": "01020304",
2172 "Base32": "AEBAGBA=",
2173 "Base32Hex": "0410610=",
2174 "Base64": "AQIDBA==",
2175 "Base64URL": "AQIDBA==",
2176 "Array": [
2177 1,
2178 2,
2179 3,
2180 4
2181 ],
2182 "Default": [
2183 1,
2184 2,
2185 3,
2186 4
2187 ]
2188 }`,
2189 skip: !internal.ExpJSONFormat,
2190 }, {
2191 name: jsontest.Name("Structs/Format/Bytes/Array"),
2192 opts: []Options{
2193 WithMarshalers(MarshalFunc(func(in byte) ([]byte, error) {
2194 if in > 3 {
2195 return []byte("true"), nil
2196 } else {
2197 return []byte("false"), nil
2198 }
2199 })),
2200 },
2201 in: struct {
2202 Array []byte `json:",format:array"`
2203 }{
2204 Array: []byte{1, 6, 2, 5, 3, 4},
2205 },
2206 want: `{"Array":[false,true,false,true,false,true]}`,
2207 skip: !internal.ExpJSONFormat,
2208 }, {
2209 name: jsontest.Name("Structs/Format/Floats"),
2210 opts: []Options{jsontext.Multiline(true)},
2211 in: []structFormatFloats{
2212 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
2213 {NonFinite: math.NaN(), PointerNonFinite: addr(math.NaN())},
2214 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
2215 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
2216 },
2217 want: `[
2218 {
2219 "NonFinite": 3.141592653589793,
2220 "PointerNonFinite": 3.141592653589793
2221 },
2222 {
2223 "NonFinite": "NaN",
2224 "PointerNonFinite": "NaN"
2225 },
2226 {
2227 "NonFinite": "-Infinity",
2228 "PointerNonFinite": "-Infinity"
2229 },
2230 {
2231 "NonFinite": "Infinity",
2232 "PointerNonFinite": "Infinity"
2233 }
2234 ]`,
2235 skip: !internal.ExpJSONFormat,
2236 }, {
2237 name: jsontest.Name("Structs/Format/Maps"),
2238 opts: []Options{jsontext.Multiline(true)},
2239 in: []structFormatMaps{{
2240 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2241 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2242 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2243 }, {
2244 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2245 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2246 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2247 }, {
2248 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2249 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2250 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2251 }},
2252 want: `[
2253 {
2254 "EmitNull": null,
2255 "PointerEmitNull": null,
2256 "EmitEmpty": {},
2257 "PointerEmitEmpty": {},
2258 "EmitDefault": {},
2259 "PointerEmitDefault": {}
2260 },
2261 {
2262 "EmitNull": {},
2263 "PointerEmitNull": {},
2264 "EmitEmpty": {},
2265 "PointerEmitEmpty": {},
2266 "EmitDefault": {},
2267 "PointerEmitDefault": {}
2268 },
2269 {
2270 "EmitNull": {
2271 "k": "v"
2272 },
2273 "PointerEmitNull": {
2274 "k": "v"
2275 },
2276 "EmitEmpty": {
2277 "k": "v"
2278 },
2279 "PointerEmitEmpty": {
2280 "k": "v"
2281 },
2282 "EmitDefault": {
2283 "k": "v"
2284 },
2285 "PointerEmitDefault": {
2286 "k": "v"
2287 }
2288 }
2289 ]`,
2290 skip: !internal.ExpJSONFormat,
2291 }, {
2292 name: jsontest.Name("Structs/Format/Maps/FormatNilMapAsNull"),
2293 opts: []Options{
2294 FormatNilMapAsNull(true),
2295 jsontext.Multiline(true),
2296 },
2297 in: []structFormatMaps{{
2298 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2299 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2300 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2301 }, {
2302 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2303 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2304 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2305 }, {
2306 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2307 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2308 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2309 }},
2310 want: `[
2311 {
2312 "EmitNull": null,
2313 "PointerEmitNull": null,
2314 "EmitEmpty": {},
2315 "PointerEmitEmpty": {},
2316 "EmitDefault": null,
2317 "PointerEmitDefault": null
2318 },
2319 {
2320 "EmitNull": {},
2321 "PointerEmitNull": {},
2322 "EmitEmpty": {},
2323 "PointerEmitEmpty": {},
2324 "EmitDefault": {},
2325 "PointerEmitDefault": {}
2326 },
2327 {
2328 "EmitNull": {
2329 "k": "v"
2330 },
2331 "PointerEmitNull": {
2332 "k": "v"
2333 },
2334 "EmitEmpty": {
2335 "k": "v"
2336 },
2337 "PointerEmitEmpty": {
2338 "k": "v"
2339 },
2340 "EmitDefault": {
2341 "k": "v"
2342 },
2343 "PointerEmitDefault": {
2344 "k": "v"
2345 }
2346 }
2347 ]`,
2348 skip: !internal.ExpJSONFormat,
2349 }, {
2350 name: jsontest.Name("Structs/Format/Slices"),
2351 opts: []Options{jsontext.Multiline(true)},
2352 in: []structFormatSlices{{
2353 EmitNull: []string(nil), PointerEmitNull: addr([]string(nil)),
2354 EmitEmpty: []string(nil), PointerEmitEmpty: addr([]string(nil)),
2355 EmitDefault: []string(nil), PointerEmitDefault: addr([]string(nil)),
2356 }, {
2357 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
2358 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
2359 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
2360 }, {
2361 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
2362 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
2363 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
2364 }},
2365 want: `[
2366 {
2367 "EmitNull": null,
2368 "PointerEmitNull": null,
2369 "EmitEmpty": [],
2370 "PointerEmitEmpty": [],
2371 "EmitDefault": [],
2372 "PointerEmitDefault": []
2373 },
2374 {
2375 "EmitNull": [],
2376 "PointerEmitNull": [],
2377 "EmitEmpty": [],
2378 "PointerEmitEmpty": [],
2379 "EmitDefault": [],
2380 "PointerEmitDefault": []
2381 },
2382 {
2383 "EmitNull": [
2384 "v"
2385 ],
2386 "PointerEmitNull": [
2387 "v"
2388 ],
2389 "EmitEmpty": [
2390 "v"
2391 ],
2392 "PointerEmitEmpty": [
2393 "v"
2394 ],
2395 "EmitDefault": [
2396 "v"
2397 ],
2398 "PointerEmitDefault": [
2399 "v"
2400 ]
2401 }
2402 ]`,
2403 skip: !internal.ExpJSONFormat,
2404 }, {
2405 name: jsontest.Name("Structs/Format/Invalid/Bool"),
2406 in: structFormatInvalid{Bool: true},
2407 want: `{"Bool"`,
2408 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, boolType),
2409 skip: !internal.ExpJSONFormat,
2410 }, {
2411 name: jsontest.Name("Structs/Format/Invalid/String"),
2412 in: structFormatInvalid{String: "string"},
2413 want: `{"String"`,
2414 wantErr: EM(errInvalidFormatFlag).withPos(`{"String":`, "/String").withType(0, stringType),
2415 skip: !internal.ExpJSONFormat,
2416 }, {
2417 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
2418 in: structFormatInvalid{Bytes: []byte("bytes")},
2419 want: `{"Bytes"`,
2420 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bytes":`, "/Bytes").withType(0, bytesType),
2421 skip: !internal.ExpJSONFormat,
2422 }, {
2423 name: jsontest.Name("Structs/Format/Invalid/Int"),
2424 in: structFormatInvalid{Int: 1},
2425 want: `{"Int"`,
2426 wantErr: EM(errInvalidFormatFlag).withPos(`{"Int":`, "/Int").withType(0, T[int64]()),
2427 skip: !internal.ExpJSONFormat,
2428 }, {
2429 name: jsontest.Name("Structs/Format/Invalid/Uint"),
2430 in: structFormatInvalid{Uint: 1},
2431 want: `{"Uint"`,
2432 wantErr: EM(errInvalidFormatFlag).withPos(`{"Uint":`, "/Uint").withType(0, T[uint64]()),
2433 skip: !internal.ExpJSONFormat,
2434 }, {
2435 name: jsontest.Name("Structs/Format/Invalid/Float"),
2436 in: structFormatInvalid{Float: 1},
2437 want: `{"Float"`,
2438 wantErr: EM(errInvalidFormatFlag).withPos(`{"Float":`, "/Float").withType(0, T[float64]()),
2439 skip: !internal.ExpJSONFormat,
2440 }, {
2441 name: jsontest.Name("Structs/Format/Invalid/Map"),
2442 in: structFormatInvalid{Map: map[string]string{}},
2443 want: `{"Map"`,
2444 wantErr: EM(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
2445 skip: !internal.ExpJSONFormat,
2446 }, {
2447 name: jsontest.Name("Structs/Format/Invalid/Struct"),
2448 in: structFormatInvalid{Struct: structAll{Bool: true}},
2449 want: `{"Struct"`,
2450 wantErr: EM(errInvalidFormatFlag).withPos(`{"Struct":`, "/Struct").withType(0, T[structAll]()),
2451 skip: !internal.ExpJSONFormat,
2452 }, {
2453 name: jsontest.Name("Structs/Format/Invalid/Slice"),
2454 in: structFormatInvalid{Slice: []string{}},
2455 want: `{"Slice"`,
2456 wantErr: EM(errInvalidFormatFlag).withPos(`{"Slice":`, "/Slice").withType(0, T[[]string]()),
2457 skip: !internal.ExpJSONFormat,
2458 }, {
2459 name: jsontest.Name("Structs/Format/Invalid/Array"),
2460 in: structFormatInvalid{Array: [1]string{"string"}},
2461 want: `{"Array"`,
2462 wantErr: EM(errInvalidFormatFlag).withPos(`{"Array":`, "/Array").withType(0, T[[1]string]()),
2463 skip: !internal.ExpJSONFormat,
2464 }, {
2465 name: jsontest.Name("Structs/Format/Invalid/Interface"),
2466 in: structFormatInvalid{Interface: "anything"},
2467 want: `{"Interface"`,
2468 wantErr: EM(errInvalidFormatFlag).withPos(`{"Interface":`, "/Interface").withType(0, T[any]()),
2469 skip: !internal.ExpJSONFormat,
2470 }, {
2471 name: jsontest.Name("Structs/Inline/Zero"),
2472 in: structInlined{},
2473 want: `{"D":""}`,
2474 }, {
2475 name: jsontest.Name("Structs/Inline/Alloc"),
2476 in: structInlined{
2477 X: structInlinedL1{
2478 X: &structInlinedL2{},
2479 StructEmbed1: StructEmbed1{},
2480 },
2481 StructEmbed2: &StructEmbed2{},
2482 },
2483 want: `{"A":"","B":"","D":"","E":"","F":"","G":""}`,
2484 }, {
2485 name: jsontest.Name("Structs/Inline/NonZero"),
2486 in: structInlined{
2487 X: structInlinedL1{
2488 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
2489 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
2490 },
2491 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
2492 },
2493 want: `{"A":"A1","B":"B1","D":"D2","E":"E3","F":"F3","G":"G3"}`,
2494 }, {
2495 name: jsontest.Name("Structs/Inline/DualCycle"),
2496 in: cyclicA{
2497 B1: cyclicB{F: 1},
2498 B2: cyclicB{F: 2},
2499 },
2500 want: `{}`,
2501 }, {
2502 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nil"),
2503 in: structInlineTextValue{X: jsontext.Value(nil)},
2504 want: `{}`,
2505 }, {
2506 name: jsontest.Name("Structs/InlinedFallback/TextValue/Empty"),
2507 in: structInlineTextValue{X: jsontext.Value("")},
2508 want: `{}`,
2509 }, {
2510 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN1"),
2511 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)},
2512 want: `{"fizz":"buzz"}`,
2513 }, {
2514 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN2"),
2515 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `)},
2516 want: `{"fizz":"buzz","foo":"bar"}`,
2517 }, {
2518 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyWithOthers"),
2519 in: structInlineTextValue{
2520 A: 1,
2521 X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `),
2522 B: 2,
2523 },
2524
2525 want: `{"A":1,"B":2,"fizz":"buzz","foo":"bar"}`,
2526 }, {
2527 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
2528 opts: []Options{jsontext.AllowDuplicateNames(false)},
2529 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2530 want: `{"fizz":"buzz"`,
2531 wantErr: newDuplicateNameError("/fizz", nil, len64(`{"fizz":"buzz"`)),
2532 }, {
2533 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
2534 opts: []Options{jsontext.AllowDuplicateNames(true)},
2535 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2536 want: `{"fizz":"buzz","fizz":"buzz"}`,
2537 }, {
2538 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectInvalidUTF8"),
2539 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2540 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2541 want: `{`,
2542 wantErr: newInvalidUTF8Error(len64(`{"`+"\xde\xad"), ""),
2543 }, {
2544 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowInvalidUTF8"),
2545 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2546 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2547 want: `{"ޭ��":"value"}`,
2548 }, {
2549 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidWhitespace"),
2550 in: structInlineTextValue{X: jsontext.Value("\n\r\t ")},
2551 want: `{`,
2552 wantErr: EM(io.ErrUnexpectedEOF).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2553 }, {
2554 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObject"),
2555 in: structInlineTextValue{X: jsontext.Value(` true `)},
2556 want: `{`,
2557 wantErr: EM(errRawInlinedNotObject).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2558 }, {
2559 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObjectName"),
2560 in: structInlineTextValue{X: jsontext.Value(` { true : false } `)},
2561 want: `{`,
2562 wantErr: EM(newNonStringNameError(len64(" { "), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2563 }, {
2564 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidEndObject"),
2565 in: structInlineTextValue{X: jsontext.Value(` { "name" : false , } `)},
2566 want: `{"name":false`,
2567 wantErr: EM(newInvalidCharacterError(",", "at start of value", len64(` { "name" : false `), "")).withPos(`{"name":false,`, "").withType(0, T[jsontext.Value]()),
2568 }, {
2569 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidDualObject"),
2570 in: structInlineTextValue{X: jsontext.Value(`{}{}`)},
2571 want: `{`,
2572 wantErr: EM(newInvalidCharacterError("{", "after top-level value", len64(`{}`), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2573 }, {
2574 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Nil"),
2575 in: structInlinePointerInlineTextValue{},
2576 want: `{}`,
2577 }, {
2578 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nil"),
2579 in: structInlinePointerTextValue{},
2580 want: `{}`,
2581 }, {
2582 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/NonEmpty"),
2583 in: structInlinePointerTextValue{X: addr(jsontext.Value(` { "fizz" : "buzz" } `))},
2584 want: `{"fizz":"buzz"}`,
2585 }, {
2586 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
2587 in: structInlineInlinePointerTextValue{},
2588 want: `{}`,
2589 }, {
2590 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nil"),
2591 in: structInlineMapStringAny{X: nil},
2592 want: `{}`,
2593 }, {
2594 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Empty"),
2595 in: structInlineMapStringAny{X: make(jsonObject)},
2596 want: `{}`,
2597 }, {
2598 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN1"),
2599 in: structInlineMapStringAny{X: jsonObject{"fizz": nil}},
2600 want: `{"fizz":null}`,
2601 }, {
2602 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN2"),
2603 in: structInlineMapStringAny{X: jsonObject{"fizz": time.Time{}, "buzz": math.Pi}},
2604 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2605 canonicalize: true,
2606 }, {
2607 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyWithOthers"),
2608 in: structInlineMapStringAny{
2609 A: 1,
2610 X: jsonObject{"fizz": nil},
2611 B: 2,
2612 },
2613
2614 want: `{"A":1,"B":2,"fizz":null}`,
2615 }, {
2616 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectInvalidUTF8"),
2617 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2618 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2619 want: `{`,
2620 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, stringType),
2621 }, {
2622 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowInvalidUTF8"),
2623 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2624 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2625 want: `{"ޭ��":null}`,
2626 }, {
2627 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/InvalidValue"),
2628 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2629 in: structInlineMapStringAny{X: jsonObject{"name": make(chan string)}},
2630 want: `{"name"`,
2631 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2632 }, {
2633 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Nil"),
2634 in: structInlinePointerInlineMapStringAny{},
2635 want: `{}`,
2636 }, {
2637 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MarshalFunc"),
2638 opts: []Options{
2639 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2640 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2641 })),
2642 },
2643 in: structInlineMapStringAny{X: jsonObject{"fizz": 3.14159}},
2644 want: `{"fizz":"3.14159"}`,
2645 }, {
2646 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nil"),
2647 in: structInlinePointerMapStringAny{X: nil},
2648 want: `{}`,
2649 }, {
2650 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/NonEmpty"),
2651 in: structInlinePointerMapStringAny{X: addr(jsonObject{"name": "value"})},
2652 want: `{"name":"value"}`,
2653 }, {
2654 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
2655 in: structInlineInlinePointerMapStringAny{},
2656 want: `{}`,
2657 }, {
2658 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
2659 in: structInlineMapStringInt{
2660 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2661 },
2662 want: `{"one":1,"two":2,"zero":0}`,
2663 canonicalize: true,
2664 }, {
2665 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic"),
2666 opts: []Options{Deterministic(true)},
2667 in: structInlineMapStringInt{
2668 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2669 },
2670 want: `{"one":1,"two":2,"zero":0}`,
2671 }, {
2672 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
2673 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
2674 in: structInlineMapStringInt{
2675 X: map[string]int{"\xff": 0, "\xfe": 1},
2676 },
2677 want: `{"�":1`,
2678 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1`)),
2679 }, {
2680 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
2681 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
2682 in: structInlineMapStringInt{
2683 X: map[string]int{"\xff": 0, "\xfe": 1},
2684 },
2685 want: `{"�":1,"�":0}`,
2686 }, {
2687 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
2688 opts: []Options{StringifyNumbers(true)},
2689 in: structInlineMapStringInt{
2690 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2691 },
2692 want: `{"one":"1","two":"2","zero":"0"}`,
2693 canonicalize: true,
2694 }, {
2695 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/MarshalFunc"),
2696 opts: []Options{
2697 WithMarshalers(JoinMarshalers(
2698
2699 MarshalFunc(func(v string) ([]byte, error) {
2700 return []byte(fmt.Sprintf(`"%q"`, strings.ToUpper(v))), nil
2701 }),
2702 MarshalFunc(func(v int) ([]byte, error) {
2703 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2704 }),
2705 )),
2706 },
2707 in: structInlineMapStringInt{
2708 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2709 },
2710 want: `{"one":"1","two":"2","zero":"0"}`,
2711 canonicalize: true,
2712 }, {
2713 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
2714 in: structInlineMapNamedStringInt{
2715 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2716 },
2717 want: `{"one":1,"two":2,"zero":0}`,
2718 canonicalize: true,
2719 }, {
2720 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Deterministic"),
2721 opts: []Options{Deterministic(true)},
2722 in: structInlineMapNamedStringInt{
2723 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2724 },
2725 want: `{"one":1,"two":2,"zero":0}`,
2726 }, {
2727 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Nil"),
2728 in: structInlineMapNamedStringAny{X: nil},
2729 want: `{}`,
2730 }, {
2731 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Empty"),
2732 in: structInlineMapNamedStringAny{X: make(map[namedString]any)},
2733 want: `{}`,
2734 }, {
2735 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN1"),
2736 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": nil}},
2737 want: `{"fizz":null}`,
2738 }, {
2739 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN2"),
2740 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": time.Time{}, "buzz": math.Pi}},
2741 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2742 canonicalize: true,
2743 }, {
2744 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyWithOthers"),
2745 in: structInlineMapNamedStringAny{
2746 A: 1,
2747 X: map[namedString]any{"fizz": nil},
2748 B: 2,
2749 },
2750
2751 want: `{"A":1,"B":2,"fizz":null}`,
2752 }, {
2753 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectInvalidUTF8"),
2754 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2755 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2756 want: `{`,
2757 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, T[namedString]()),
2758 }, {
2759 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowInvalidUTF8"),
2760 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2761 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2762 want: `{"ޭ��":null}`,
2763 }, {
2764 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/InvalidValue"),
2765 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2766 in: structInlineMapNamedStringAny{X: map[namedString]any{"name": make(chan string)}},
2767 want: `{"name"`,
2768 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2769 }, {
2770 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MarshalFunc"),
2771 opts: []Options{
2772 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2773 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2774 })),
2775 },
2776 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": 3.14159}},
2777 want: `{"fizz":"3.14159"}`,
2778 }, {
2779 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other"),
2780 in: structNoCaseInlineTextValue{
2781 X: jsontext.Value(`{"dupe":"","dupe":""}`),
2782 },
2783 want: `{"dupe":""`,
2784 wantErr: newDuplicateNameError("", []byte(`"dupe"`), len64(`{"dupe":""`)),
2785 }, {
2786 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other/AllowDuplicateNames"),
2787 opts: []Options{jsontext.AllowDuplicateNames(true)},
2788 in: structNoCaseInlineTextValue{
2789 X: jsontext.Value(`{"dupe": "", "dupe": ""}`),
2790 },
2791 want: `{"dupe":"","dupe":""}`,
2792 }, {
2793 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferent"),
2794 in: structNoCaseInlineTextValue{
2795 X: jsontext.Value(`{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""}`),
2796 },
2797 want: `{"Aaa":"","AaA":"","AAa":"","AAA":""}`,
2798 }, {
2799 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict"),
2800 in: structNoCaseInlineTextValue{
2801 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2802 },
2803 want: `{"Aaa":""`,
2804 wantErr: newDuplicateNameError("", []byte(`"Aaa"`), len64(`{"Aaa":""`)),
2805 }, {
2806 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict/AllowDuplicateNames"),
2807 opts: []Options{jsontext.AllowDuplicateNames(true)},
2808 in: structNoCaseInlineTextValue{
2809 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2810 },
2811 want: `{"Aaa":"","Aaa":""}`,
2812 }, {
2813 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict"),
2814 in: structNoCaseInlineTextValue{
2815 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2816 },
2817 want: `{"Aaa":"","AaA":""`,
2818 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"Aaa":"","AaA":""`)),
2819 }, {
2820 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict/AllowDuplicateNames"),
2821 opts: []Options{jsontext.AllowDuplicateNames(true)},
2822 in: structNoCaseInlineTextValue{
2823 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2824 },
2825 want: `{"Aaa":"","AaA":"","aaa":""}`,
2826 }, {
2827 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferentWithField"),
2828 in: structNoCaseInlineTextValue{
2829 AAA: "x",
2830 AaA: "x",
2831 X: jsontext.Value(`{"Aaa": ""}`),
2832 },
2833 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2834 }, {
2835 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflictWithField"),
2836 in: structNoCaseInlineTextValue{
2837 AAA: "x",
2838 AaA: "x",
2839 X: jsontext.Value(`{"AAA": ""}`),
2840 },
2841 want: `{"AAA":"x","AaA":"x"`,
2842 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2843 }, {
2844 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflictWithField"),
2845 in: structNoCaseInlineTextValue{
2846 AAA: "x",
2847 AaA: "x",
2848 X: jsontext.Value(`{"aaa": ""}`),
2849 },
2850 want: `{"AAA":"x","AaA":"x"`,
2851 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2852 }, {
2853 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveDelimiter"),
2854 in: structNoCaseInlineTextValue{
2855 AaA: "x",
2856 X: jsontext.Value(`{"aa_a": ""}`),
2857 },
2858 want: `{"AaA":"x"`,
2859 wantErr: newDuplicateNameError("", []byte(`"aa_a"`), len64(`{"AaA":"x"`)),
2860 }, {
2861 name: jsontest.Name("Structs/DuplicateName/MatchCaseSensitiveDelimiter"),
2862 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
2863 in: structNoCaseInlineTextValue{
2864 AaA: "x",
2865 X: jsontext.Value(`{"aa_a": ""}`),
2866 },
2867 want: `{"AaA":"x","aa_a":""}`,
2868 }, {
2869 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2870 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2871 in: structNoCaseInlineTextValue{
2872 AaA: "x",
2873 X: jsontext.Value(`{"aa_a": ""}`),
2874 },
2875 want: `{"AaA":"x","aa_a":""}`,
2876 }, {
2877 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2878 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2879 in: structNoCaseInlineTextValue{
2880 AA_b: "x",
2881 X: jsontext.Value(`{"aa_b": ""}`),
2882 },
2883 want: `{"AA_b":"x"`,
2884 wantErr: newDuplicateNameError("", []byte(`"aa_b"`), len64(`{"AA_b":"x"`)),
2885 }, {
2886 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferent"),
2887 in: structNoCaseInlineMapStringAny{
2888 X: jsonObject{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""},
2889 },
2890 want: `{"AAA":"","AAa":"","AaA":"","Aaa":""}`,
2891 canonicalize: true,
2892 }, {
2893 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferentWithField"),
2894 in: structNoCaseInlineMapStringAny{
2895 AAA: "x",
2896 AaA: "x",
2897 X: jsonObject{"Aaa": ""},
2898 },
2899 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2900 }, {
2901 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactConflictWithField"),
2902 in: structNoCaseInlineMapStringAny{
2903 AAA: "x",
2904 AaA: "x",
2905 X: jsonObject{"AAA": ""},
2906 },
2907 want: `{"AAA":"x","AaA":"x"`,
2908 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2909 }, {
2910 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/NoCaseConflictWithField"),
2911 in: structNoCaseInlineMapStringAny{
2912 AAA: "x",
2913 AaA: "x",
2914 X: jsonObject{"aaa": ""},
2915 },
2916 want: `{"AAA":"x","AaA":"x"`,
2917 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2918 }, {
2919 name: jsontest.Name("Structs/Invalid/Conflicting"),
2920 in: structConflicting{},
2921 want: ``,
2922 wantErr: EM(errors.New("Go struct fields A and B conflict over JSON object name \"conflict\"")).withType(0, T[structConflicting]()),
2923 }, {
2924 name: jsontest.Name("Structs/Invalid/NoneExported"),
2925 in: structNoneExported{},
2926 want: ``,
2927 wantErr: EM(errNoExportedFields).withType(0, T[structNoneExported]()),
2928 }, {
2929 name: jsontest.Name("Structs/Invalid/MalformedTag"),
2930 in: structMalformedTag{},
2931 want: ``,
2932 wantErr: EM(errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter or single quote)")).withType(0, T[structMalformedTag]()),
2933 }, {
2934 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
2935 in: structUnexportedTag{},
2936 want: ``,
2937 wantErr: EM(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType(0, T[structUnexportedTag]()),
2938 }, {
2939 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
2940 in: structExportedEmbedded{"hello"},
2941 want: ``,
2942 wantErr: EM(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structExportedEmbedded]()),
2943 }, {
2944 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
2945 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2946 in: structExportedEmbedded{"hello"},
2947 want: `{"NamedString":"hello"}`,
2948 }, {
2949 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
2950 in: structExportedEmbeddedTag{"hello"},
2951 want: `{"name":"hello"}`,
2952 }, {
2953 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
2954 in: structUnexportedEmbedded{},
2955 want: ``,
2956 wantErr: EM(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structUnexportedEmbedded]()),
2957 }, {
2958 name: jsontest.Name("Structs/Valid/UnexportedEmbedded"),
2959 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2960 in: structUnexportedEmbedded{},
2961 want: `{}`,
2962 }, {
2963 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedTag"),
2964 in: structUnexportedEmbeddedTag{},
2965 wantErr: EM(errors.New("Go struct field namedString is not exported")).withType(0, T[structUnexportedEmbeddedTag]()),
2966 }, {
2967 name: jsontest.Name("Structs/Valid/UnexportedEmbeddedTag"),
2968 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2969 in: structUnexportedEmbeddedTag{},
2970 want: `{}`,
2971 }, {
2972 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedMethodTag"),
2973 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2974 in: structUnexportedEmbeddedMethodTag{},
2975 want: `{}`,
2976 }, {
2977 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/Zero"),
2978 in: structUnexportedEmbeddedStruct{},
2979 want: `{"FizzBuzz":0,"Addr":""}`,
2980 }, {
2981 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/NonZero"),
2982 in: structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2983 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2984 }, {
2985 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
2986 in: structUnexportedEmbeddedStructPointer{},
2987 want: `{"FizzBuzz":0}`,
2988 }, {
2989 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Zero"),
2990 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{}, 0, &structNestedAddr{}},
2991 want: `{"FizzBuzz":0,"Addr":""}`,
2992 }, {
2993 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/NonZero"),
2994 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2995 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2996 }, {
2997 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
2998 opts: []Options{invalidFormatOption},
2999 in: struct{}{},
3000 want: `{}`,
3001 }, {
3002 name: jsontest.Name("Slices/Interface"),
3003 in: []any{
3004 false, true,
3005 "hello", []byte("world"),
3006 int32(-32), namedInt64(-64),
3007 uint32(+32), namedUint64(+64),
3008 float32(32.32), namedFloat64(64.64),
3009 },
3010 want: `[false,true,"hello","d29ybGQ=",-32,-64,32,64,32.32,64.64]`,
3011 }, {
3012 name: jsontest.Name("Slices/Invalid/Channel"),
3013 in: [](chan string){nil},
3014 want: `[`,
3015 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3016 }, {
3017 name: jsontest.Name("Slices/RecursiveSlice"),
3018 in: recursiveSlice{
3019 nil,
3020 {},
3021 {nil},
3022 {nil, {}},
3023 },
3024 want: `[[],[],[[]],[[],[]]]`,
3025 }, {
3026 name: jsontest.Name("Slices/CyclicSlice"),
3027 in: func() recursiveSlice {
3028 s := recursiveSlice{{}}
3029 s[0] = s
3030 return s
3031 }(),
3032 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[`,
3033 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat("[", startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter+1))).withType(0, T[recursiveSlice]()),
3034 }, {
3035 name: jsontest.Name("Slices/NonCyclicSlice"),
3036 in: func() []any {
3037 v := []any{nil, nil}
3038 v[1] = v[:1]
3039 for i := 1000; i > 0; i-- {
3040 v = []any{v}
3041 }
3042 return v
3043 }(),
3044 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[null,[null]]` + strings.Repeat(`]`, startDetectingCyclesAfter),
3045 }, {
3046 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
3047 opts: []Options{invalidFormatOption},
3048 in: []string{"hello", "goodbye"},
3049 want: `["hello","goodbye"]`,
3050 }, {
3051 name: jsontest.Name("Arrays/Empty"),
3052 in: [0]struct{}{},
3053 want: `[]`,
3054 }, {
3055 name: jsontest.Name("Arrays/Bool"),
3056 in: [2]bool{false, true},
3057 want: `[false,true]`,
3058 }, {
3059 name: jsontest.Name("Arrays/String"),
3060 in: [2]string{"hello", "goodbye"},
3061 want: `["hello","goodbye"]`,
3062 }, {
3063 name: jsontest.Name("Arrays/Bytes"),
3064 in: [2][]byte{[]byte("hello"), []byte("goodbye")},
3065 want: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
3066 }, {
3067 name: jsontest.Name("Arrays/Int"),
3068 in: [2]int64{math.MinInt64, math.MaxInt64},
3069 want: `[-9223372036854775808,9223372036854775807]`,
3070 }, {
3071 name: jsontest.Name("Arrays/Uint"),
3072 in: [2]uint64{0, math.MaxUint64},
3073 want: `[0,18446744073709551615]`,
3074 }, {
3075 name: jsontest.Name("Arrays/Float"),
3076 in: [2]float64{-math.MaxFloat64, +math.MaxFloat64},
3077 want: `[-1.7976931348623157e+308,1.7976931348623157e+308]`,
3078 }, {
3079 name: jsontest.Name("Arrays/Invalid/Channel"),
3080 in: new([1]chan string),
3081 want: `[`,
3082 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3083 }, {
3084 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
3085 opts: []Options{invalidFormatOption},
3086 in: [2]string{"hello", "goodbye"},
3087 want: `["hello","goodbye"]`,
3088 }, {
3089 name: jsontest.Name("Pointers/NilL0"),
3090 in: (*int)(nil),
3091 want: `null`,
3092 }, {
3093 name: jsontest.Name("Pointers/NilL1"),
3094 in: new(*int),
3095 want: `null`,
3096 }, {
3097 name: jsontest.Name("Pointers/Bool"),
3098 in: addr(addr(bool(true))),
3099 want: `true`,
3100 }, {
3101 name: jsontest.Name("Pointers/String"),
3102 in: addr(addr(string("string"))),
3103 want: `"string"`,
3104 }, {
3105 name: jsontest.Name("Pointers/Bytes"),
3106 in: addr(addr([]byte("bytes"))),
3107 want: `"Ynl0ZXM="`,
3108 }, {
3109 name: jsontest.Name("Pointers/Int"),
3110 in: addr(addr(int(-100))),
3111 want: `-100`,
3112 }, {
3113 name: jsontest.Name("Pointers/Uint"),
3114 in: addr(addr(uint(100))),
3115 want: `100`,
3116 }, {
3117 name: jsontest.Name("Pointers/Float"),
3118 in: addr(addr(float64(3.14159))),
3119 want: `3.14159`,
3120 }, {
3121 name: jsontest.Name("Pointers/CyclicPointer"),
3122 in: func() *recursivePointer {
3123 p := new(recursivePointer)
3124 p.P = p
3125 return p
3126 }(),
3127 want: strings.Repeat(`{"P":`, startDetectingCyclesAfter) + `{"P"`,
3128 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"P":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/P", startDetectingCyclesAfter+1))).withType(0, T[*recursivePointer]()),
3129 }, {
3130 name: jsontest.Name("Pointers/IgnoreInvalidFormat"),
3131 opts: []Options{invalidFormatOption},
3132 in: addr(addr(bool(true))),
3133 want: `true`,
3134 }, {
3135 name: jsontest.Name("Interfaces/Nil/Empty"),
3136 in: [1]any{nil},
3137 want: `[null]`,
3138 }, {
3139 name: jsontest.Name("Interfaces/Nil/NonEmpty"),
3140 in: [1]io.Reader{nil},
3141 want: `[null]`,
3142 }, {
3143 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
3144 opts: []Options{invalidFormatOption},
3145 in: [1]io.Reader{nil},
3146 want: `[null]`,
3147 }, {
3148 name: jsontest.Name("Interfaces/Any"),
3149 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}, [8]byte{}}},
3150 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3151 }, {
3152 name: jsontest.Name("Interfaces/Any/Named"),
3153 in: struct{ X namedAny }{[]namedAny{nil, false, "", 0.0, map[string]namedAny{}, []namedAny{}, [8]byte{}}},
3154 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3155 }, {
3156 name: jsontest.Name("Interfaces/Any/Stringified"),
3157 opts: []Options{StringifyNumbers(true)},
3158 in: struct{ X any }{0.0},
3159 want: `{"X":"0"}`,
3160 }, {
3161 name: jsontest.Name("Interfaces/Any/MarshalFunc/Any"),
3162 opts: []Options{
3163 WithMarshalers(MarshalFunc(func(v any) ([]byte, error) {
3164 return []byte(`"called"`), nil
3165 })),
3166 },
3167 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3168 want: `"called"`,
3169 }, {
3170 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bool"),
3171 opts: []Options{
3172 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3173 return []byte(`"called"`), nil
3174 })),
3175 },
3176 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3177 want: `{"X":[null,"called","",0,{},[]]}`,
3178 }, {
3179 name: jsontest.Name("Interfaces/Any/MarshalFunc/String"),
3180 opts: []Options{
3181 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3182 return []byte(`"called"`), nil
3183 })),
3184 },
3185 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3186 want: `{"X":[null,false,"called",0,{},[]]}`,
3187 }, {
3188 name: jsontest.Name("Interfaces/Any/MarshalFunc/Float64"),
3189 opts: []Options{
3190 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
3191 return []byte(`"called"`), nil
3192 })),
3193 },
3194 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3195 want: `{"X":[null,false,"","called",{},[]]}`,
3196 }, {
3197 name: jsontest.Name("Interfaces/Any/MarshalFunc/MapStringAny"),
3198 opts: []Options{
3199 WithMarshalers(MarshalFunc(func(v map[string]any) ([]byte, error) {
3200 return []byte(`"called"`), nil
3201 })),
3202 },
3203 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3204 want: `{"X":[null,false,"",0,"called",[]]}`,
3205 }, {
3206 name: jsontest.Name("Interfaces/Any/MarshalFunc/SliceAny"),
3207 opts: []Options{
3208 WithMarshalers(MarshalFunc(func(v []any) ([]byte, error) {
3209 return []byte(`"called"`), nil
3210 })),
3211 },
3212 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3213 want: `{"X":"called"}`,
3214 }, {
3215 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bytes"),
3216 opts: []Options{
3217 WithMarshalers(MarshalFunc(func(v [8]byte) ([]byte, error) {
3218 return []byte(`"called"`), nil
3219 })),
3220 },
3221 in: struct{ X any }{[8]byte{}},
3222 want: `{"X":"called"}`,
3223 }, {
3224 name: jsontest.Name("Interfaces/Any/Float/NaN"),
3225 in: struct{ X any }{math.NaN()},
3226 want: `{"X"`,
3227 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, reflect.TypeFor[float64]()).withPos(`{"X":`, "/X"),
3228 }, {
3229 name: jsontest.Name("Interfaces/Any/Maps/Nil"),
3230 in: struct{ X any }{map[string]any(nil)},
3231 want: `{"X":{}}`,
3232 }, {
3233 name: jsontest.Name("Interfaces/Any/Maps/Nil/FormatNilMapAsNull"),
3234 opts: []Options{FormatNilMapAsNull(true)},
3235 in: struct{ X any }{map[string]any(nil)},
3236 want: `{"X":null}`,
3237 }, {
3238 name: jsontest.Name("Interfaces/Any/Maps/Empty"),
3239 in: struct{ X any }{map[string]any{}},
3240 want: `{"X":{}}`,
3241 }, {
3242 name: jsontest.Name("Interfaces/Any/Maps/Empty/Multiline"),
3243 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3244 in: struct{ X any }{map[string]any{}},
3245 want: "{\n\"X\": {}\n}",
3246 }, {
3247 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
3248 in: struct{ X any }{map[string]any{"fizz": "buzz"}},
3249 want: `{"X":{"fizz":"buzz"}}`,
3250 }, {
3251 name: jsontest.Name("Interfaces/Any/Maps/Deterministic"),
3252 opts: []Options{Deterministic(true)},
3253 in: struct{ X any }{map[string]any{"alpha": "", "bravo": ""}},
3254 want: `{"X":{"alpha":"","bravo":""}}`,
3255 }, {
3256 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
3257 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
3258 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3259 want: `{"X":{"�":""`,
3260 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3261 }, {
3262 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
3263 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3264 in: struct{ X any }{map[string]any{"\xff": "alpha", "\xfe": "bravo"}},
3265 want: `{"X":{"�":"bravo","�":"alpha"}}`,
3266 }, {
3267 name: jsontest.Name("Interfaces/Any/Maps/RejectInvalidUTF8"),
3268 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3269 want: `{"X":{`,
3270 wantErr: newInvalidUTF8Error(len64(`{"X":{`), "/X"),
3271 }, {
3272 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+RejectDuplicateNames"),
3273 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3274 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3275 want: `{"X":{"�":""`,
3276 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3277 }, {
3278 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+AllowDuplicateNames"),
3279 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3280 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3281 want: `{"X":{"�":"","�":""}}`,
3282 }, {
3283 name: jsontest.Name("Interfaces/Any/Maps/Cyclic"),
3284 in: func() any {
3285 m := map[string]any{}
3286 m[""] = m
3287 return struct{ X any }{m}
3288 }(),
3289 want: `{"X"` + strings.Repeat(`:{""`, startDetectingCyclesAfter),
3290 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`{"":`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/", startDetectingCyclesAfter))).withType(0, T[map[string]any]()),
3291 }, {
3292 name: jsontest.Name("Interfaces/Any/Slices/Nil"),
3293 in: struct{ X any }{[]any(nil)},
3294 want: `{"X":[]}`,
3295 }, {
3296 name: jsontest.Name("Interfaces/Any/Slices/Nil/FormatNilSliceAsNull"),
3297 opts: []Options{FormatNilSliceAsNull(true)},
3298 in: struct{ X any }{[]any(nil)},
3299 want: `{"X":null}`,
3300 }, {
3301 name: jsontest.Name("Interfaces/Any/Slices/Empty"),
3302 in: struct{ X any }{[]any{}},
3303 want: `{"X":[]}`,
3304 }, {
3305 name: jsontest.Name("Interfaces/Any/Slices/Empty/Multiline"),
3306 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3307 in: struct{ X any }{[]any{}},
3308 want: "{\n\"X\": []\n}",
3309 }, {
3310 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
3311 in: struct{ X any }{[]any{"fizz", "buzz"}},
3312 want: `{"X":["fizz","buzz"]}`,
3313 }, {
3314 name: jsontest.Name("Interfaces/Any/Slices/Cyclic"),
3315 in: func() any {
3316 s := make([]any, 1)
3317 s[0] = s
3318 return struct{ X any }{s}
3319 }(),
3320 want: `{"X":` + strings.Repeat(`[`, startDetectingCyclesAfter),
3321 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`[`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter))).withType(0, T[[]any]()),
3322 }, {
3323 name: jsontest.Name("Methods/NilPointer"),
3324 in: struct{ X *allMethods }{X: (*allMethods)(nil)},
3325 want: `{"X":null}`,
3326 }, {
3327
3328 name: jsontest.Name("Methods/NilInterface"),
3329 in: struct{ X MarshalerTo }{X: (*allMethods)(nil)},
3330 want: `{"X":null}`,
3331 }, {
3332 name: jsontest.Name("Methods/AllMethods"),
3333 in: struct{ X *allMethods }{X: &allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3334 want: `{"X":"hello"}`,
3335 }, {
3336 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
3337 in: struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3338 want: `{"X":"hello"}`,
3339 }, {
3340 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
3341 in: struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3342 want: `{"X":"hello"}`,
3343 }, {
3344 name: jsontest.Name("Methods/AllMethodsExceptText"),
3345 in: struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3346 want: `{"X":"hello"}`,
3347 }, {
3348 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
3349 in: struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3350 want: `{"X":"hello"}`,
3351 }, {
3352 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
3353 in: struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3354 want: `{"X":"hello"}`,
3355 }, {
3356 name: jsontest.Name("Methods/OnlyMethodText"),
3357 in: struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "MarshalText", value: []byte(`hello`)}}},
3358 want: `{"X":"hello"}`,
3359 }, {
3360 name: jsontest.Name("Methods/IP"),
3361 in: net.IPv4(192, 168, 0, 100),
3362 want: `"192.168.0.100"`,
3363 }, {
3364 name: jsontest.Name("Methods/NetIP"),
3365 in: struct {
3366 Addr netip.Addr
3367 AddrPort netip.AddrPort
3368 Prefix netip.Prefix
3369 }{
3370 Addr: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
3371 AddrPort: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 1234),
3372 Prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
3373 },
3374 want: `{"Addr":"1.2.3.4","AddrPort":"1.2.3.4:1234","Prefix":"1.2.3.4/24"}`,
3375 }, {
3376
3377 name: jsontest.Name("Methods/Anonymous"),
3378 in: struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3379 want: `{"X":"hello"}`,
3380 }, {
3381
3382 name: jsontest.Name("Methods/Addressable"),
3383 in: struct {
3384 V allMethods
3385 M map[string]allMethods
3386 I any
3387 }{
3388 V: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3389 M: map[string]allMethods{"K": {method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3390 I: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3391 },
3392 want: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
3393 }, {
3394
3395 name: jsontest.Name("Methods/MapKey/JSONv2"),
3396 in: map[structMethodJSONv2]string{{"k1"}: "v1", {"k2"}: "v2"},
3397 want: `{"k1":"v1","k2":"v2"}`,
3398 canonicalize: true,
3399 }, {
3400
3401 name: jsontest.Name("Methods/MapKey/JSONv1"),
3402 in: map[structMethodJSONv1]string{{"k1"}: "v1", {"k2"}: "v2"},
3403 want: `{"k1":"v1","k2":"v2"}`,
3404 canonicalize: true,
3405 }, {
3406 name: jsontest.Name("Methods/MapKey/Text"),
3407 in: map[structMethodText]string{{"k1"}: "v1", {"k2"}: "v2"},
3408 want: `{"k1":"v1","k2":"v2"}`,
3409 canonicalize: true,
3410 }, {
3411 name: jsontest.Name("Methods/JSONv2/ErrUnsupported"),
3412 opts: []Options{Deterministic(true)},
3413 in: unsupportedMethodJSONv2{"fizz": 123},
3414 want: `{"called":1,"fizz":123}`,
3415 }, {
3416 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
3417 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3418 return errSomeError
3419 }),
3420 wantErr: EM(errSomeError).withType(0, T[marshalJSONv2Func]()),
3421 }, {
3422 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
3423 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3424 return nil
3425 }),
3426 wantErr: EM(errNonSingularValue).withType(0, T[marshalJSONv2Func]()),
3427 }, {
3428 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
3429 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3430 enc.WriteToken(jsontext.Null)
3431 enc.WriteToken(jsontext.Null)
3432 return nil
3433 }),
3434 want: `nullnull`,
3435 wantErr: EM(errNonSingularValue).withPos(`nullnull`, "").withType(0, T[marshalJSONv2Func]()),
3436 }, {
3437 name: jsontest.Name("Methods/Invalid/JSONv2/ErrUnsupported"),
3438 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3439 return errors.ErrUnsupported
3440 }),
3441 wantErr: EM(nil).withType(0, T[marshalJSONv2Func]()),
3442 }, {
3443 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
3444 in: marshalJSONv1Func(func() ([]byte, error) {
3445 return nil, errSomeError
3446 }),
3447 wantErr: EM(errSomeError).withType(0, T[marshalJSONv1Func]()),
3448 }, {
3449 name: jsontest.Name("Methods/Invalid/JSONv1/Syntax"),
3450 in: marshalJSONv1Func(func() ([]byte, error) {
3451 return []byte("invalid"), nil
3452 }),
3453 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[marshalJSONv1Func]()),
3454 }, {
3455 name: jsontest.Name("Methods/Invalid/JSONv1/ErrUnsupported"),
3456 in: marshalJSONv1Func(func() ([]byte, error) {
3457 return nil, errors.ErrUnsupported
3458 }),
3459 wantErr: EM(errors.New("MarshalJSON method may not return errors.ErrUnsupported")).withType(0, T[marshalJSONv1Func]()),
3460 }, {
3461 name: jsontest.Name("Methods/AppendText"),
3462 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), nil }),
3463 want: `"hello"`,
3464 }, {
3465 name: jsontest.Name("Methods/AppendText/Error"),
3466 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), errSomeError }),
3467 wantErr: EM(errSomeError).withType(0, T[appendTextFunc]()),
3468 }, {
3469 name: jsontest.Name("Methods/AppendText/NeedEscape"),
3470 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, `"`...), nil }),
3471 want: `"\""`,
3472 }, {
3473 name: jsontest.Name("Methods/AppendText/RejectInvalidUTF8"),
3474 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3475 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[appendTextFunc]()),
3476 }, {
3477 name: jsontest.Name("Methods/AppendText/AllowInvalidUTF8"),
3478 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3479 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3480 want: "\"\xde\xad\ufffd\ufffd\"",
3481 }, {
3482 name: jsontest.Name("Methods/Invalid/Text/Error"),
3483 in: marshalTextFunc(func() ([]byte, error) {
3484 return nil, errSomeError
3485 }),
3486 wantErr: EM(errSomeError).withType(0, T[marshalTextFunc]()),
3487 }, {
3488 name: jsontest.Name("Methods/Text/RejectInvalidUTF8"),
3489 in: marshalTextFunc(func() ([]byte, error) {
3490 return []byte("\xde\xad\xbe\xef"), nil
3491 }),
3492 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[marshalTextFunc]()),
3493 }, {
3494 name: jsontest.Name("Methods/Text/AllowInvalidUTF8"),
3495 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3496 in: marshalTextFunc(func() ([]byte, error) {
3497 return []byte("\xde\xad\xbe\xef"), nil
3498 }),
3499 want: "\"\xde\xad\ufffd\ufffd\"",
3500 }, {
3501 name: jsontest.Name("Methods/Invalid/Text/ErrUnsupported"),
3502 in: marshalTextFunc(func() ([]byte, error) {
3503 return nil, errors.ErrUnsupported
3504 }),
3505 wantErr: EM(wrapErrUnsupported(errors.ErrUnsupported, "MarshalText method")).withType(0, T[marshalTextFunc]()),
3506 }, {
3507 name: jsontest.Name("Methods/Invalid/MapKey/JSONv2/Syntax"),
3508 in: map[any]string{
3509 addr(marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3510 return enc.WriteToken(jsontext.Null)
3511 })): "invalid",
3512 },
3513 want: `{`,
3514 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv2Func]()),
3515 }, {
3516 name: jsontest.Name("Methods/Invalid/MapKey/JSONv1/Syntax"),
3517 in: map[any]string{
3518 addr(marshalJSONv1Func(func() ([]byte, error) {
3519 return []byte(`null`), nil
3520 })): "invalid",
3521 },
3522 want: `{`,
3523 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv1Func]()),
3524 }, {
3525 name: jsontest.Name("Functions/Bool/V1"),
3526 opts: []Options{
3527 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3528 return []byte(`"called"`), nil
3529 })),
3530 },
3531 in: true,
3532 want: `"called"`,
3533 }, {
3534 name: jsontest.Name("Functions/Bool/Empty"),
3535 opts: []Options{WithMarshalers(nil)},
3536 in: true,
3537 want: `true`,
3538 }, {
3539 name: jsontest.Name("Functions/NamedBool/V1/NoMatch"),
3540 opts: []Options{
3541 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3542 return nil, errMustNotCall
3543 })),
3544 },
3545 in: true,
3546 want: `true`,
3547 }, {
3548 name: jsontest.Name("Functions/NamedBool/V1/Match"),
3549 opts: []Options{
3550 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3551 return []byte(`"called"`), nil
3552 })),
3553 },
3554 in: namedBool(true),
3555 want: `"called"`,
3556 }, {
3557 name: jsontest.Name("Functions/PointerBool/V1/Match"),
3558 opts: []Options{
3559 WithMarshalers(MarshalFunc(func(v *bool) ([]byte, error) {
3560 _ = *v
3561 return []byte(`"called"`), nil
3562 })),
3563 },
3564 in: true,
3565 want: `"called"`,
3566 }, {
3567 name: jsontest.Name("Functions/Bool/V2"),
3568 opts: []Options{
3569 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3570 return enc.WriteToken(jsontext.String("called"))
3571 })),
3572 },
3573 in: true,
3574 want: `"called"`,
3575 }, {
3576 name: jsontest.Name("Functions/NamedBool/V2/NoMatch"),
3577 opts: []Options{
3578 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3579 return errMustNotCall
3580 })),
3581 },
3582 in: true,
3583 want: `true`,
3584 }, {
3585 name: jsontest.Name("Functions/NamedBool/V2/Match"),
3586 opts: []Options{
3587 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3588 return enc.WriteToken(jsontext.String("called"))
3589 })),
3590 },
3591 in: namedBool(true),
3592 want: `"called"`,
3593 }, {
3594 name: jsontest.Name("Functions/PointerBool/V2/Match"),
3595 opts: []Options{
3596 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3597 _ = *v
3598 return enc.WriteToken(jsontext.String("called"))
3599 })),
3600 },
3601 in: true,
3602 want: `"called"`,
3603 }, {
3604 name: jsontest.Name("Functions/Bool/Empty1/NoMatch"),
3605 opts: []Options{
3606 WithMarshalers(new(Marshalers)),
3607 },
3608 in: true,
3609 want: `true`,
3610 }, {
3611 name: jsontest.Name("Functions/Bool/Empty2/NoMatch"),
3612 opts: []Options{
3613 WithMarshalers(JoinMarshalers()),
3614 },
3615 in: true,
3616 want: `true`,
3617 }, {
3618 name: jsontest.Name("Functions/Bool/V1/DirectError"),
3619 opts: []Options{
3620 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3621 return nil, errSomeError
3622 })),
3623 },
3624 in: true,
3625 wantErr: EM(errSomeError).withType(0, T[bool]()),
3626 }, {
3627 name: jsontest.Name("Functions/Bool/V1/SkipError"),
3628 opts: []Options{
3629 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3630 return nil, errors.ErrUnsupported
3631 })),
3632 },
3633 in: true,
3634 wantErr: EM(wrapErrUnsupported(errors.ErrUnsupported, "marshal function of type func(T) ([]byte, error)")).withType(0, T[bool]()),
3635 }, {
3636 name: jsontest.Name("Functions/Bool/V1/InvalidValue"),
3637 opts: []Options{
3638 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3639 return []byte("invalid"), nil
3640 })),
3641 },
3642 in: true,
3643 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[bool]()),
3644 }, {
3645 name: jsontest.Name("Functions/Bool/V2/DirectError"),
3646 opts: []Options{
3647 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3648 return errSomeError
3649 })),
3650 },
3651 in: true,
3652 wantErr: EM(errSomeError).withType(0, T[bool]()),
3653 }, {
3654 name: jsontest.Name("Functions/Bool/V2/TooFew"),
3655 opts: []Options{
3656 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3657 return nil
3658 })),
3659 },
3660 in: true,
3661 wantErr: EM(errNonSingularValue).withType(0, T[bool]()),
3662 }, {
3663 name: jsontest.Name("Functions/Bool/V2/TooMany"),
3664 opts: []Options{
3665 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3666 enc.WriteValue([]byte(`"hello"`))
3667 enc.WriteValue([]byte(`"world"`))
3668 return nil
3669 })),
3670 },
3671 in: true,
3672 want: `"hello""world"`,
3673 wantErr: EM(errNonSingularValue).withPos(`"hello""world"`, "").withType(0, T[bool]()),
3674 }, {
3675 name: jsontest.Name("Functions/Bool/V2/Skipped"),
3676 opts: []Options{
3677 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3678 return errors.ErrUnsupported
3679 })),
3680 },
3681 in: true,
3682 want: `true`,
3683 }, {
3684 name: jsontest.Name("Functions/Bool/V2/ProcessBeforeSkip"),
3685 opts: []Options{
3686 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3687 enc.WriteValue([]byte(`"hello"`))
3688 return errors.ErrUnsupported
3689 })),
3690 },
3691 in: true,
3692 want: `"hello"`,
3693 wantErr: EM(errUnsupportedMutation).withPos(`"hello"`, "").withType(0, T[bool]()),
3694 }, {
3695 name: jsontest.Name("Functions/Bool/V2/WrappedUnsupportedError"),
3696 opts: []Options{
3697 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3698 return fmt.Errorf("wrap: %w", errors.ErrUnsupported)
3699 })),
3700 },
3701 in: true,
3702 want: `true`,
3703 }, {
3704 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
3705 opts: []Options{
3706 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3707 return []byte(`"called"`), nil
3708 })),
3709 },
3710 in: map[nocaseString]string{"hello": "world"},
3711 want: `{"called":"world"}`,
3712 }, {
3713 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V1"),
3714 opts: []Options{
3715 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3716 _ = *v
3717 return []byte(`"called"`), nil
3718 })),
3719 },
3720 in: map[nocaseString]string{"hello": "world"},
3721 want: `{"called":"world"}`,
3722 }, {
3723 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
3724 opts: []Options{
3725 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3726 _ = *v.(*nocaseString)
3727 return []byte(`"called"`), nil
3728 })),
3729 },
3730 in: map[nocaseString]string{"hello": "world"},
3731 want: `{"called":"world"}`,
3732 }, {
3733 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1/InvalidValue"),
3734 opts: []Options{
3735 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3736 return []byte(`null`), nil
3737 })),
3738 },
3739 in: map[nocaseString]string{"hello": "world"},
3740 want: `{`,
3741 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3742 }, {
3743 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidKind"),
3744 opts: []Options{
3745 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3746 return []byte(`null`), nil
3747 })),
3748 },
3749 in: map[nocaseString]string{"hello": "world"},
3750 want: `{`,
3751 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3752 }, {
3753 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
3754 opts: []Options{
3755 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3756 return []byte(`"name"`), nil
3757 })),
3758 },
3759 in: map[string]string{"name1": "value", "name2": "value"},
3760 want: `{"name":"name"`,
3761 wantErr: EM(newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"name",`))).
3762 withPos(`{"name":"name",`, "").withType(0, T[string]()),
3763 }, {
3764 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
3765 opts: []Options{
3766 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3767 return enc.WriteValue([]byte(`"called"`))
3768 })),
3769 },
3770 in: map[nocaseString]string{"hello": "world"},
3771 want: `{"called":"world"}`,
3772 }, {
3773 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V2"),
3774 opts: []Options{
3775 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3776 _ = *v
3777 return enc.WriteValue([]byte(`"called"`))
3778 })),
3779 },
3780 in: map[nocaseString]string{"hello": "world"},
3781 want: `{"called":"world"}`,
3782 }, {
3783 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
3784 opts: []Options{
3785 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3786 _ = *v.(*nocaseString)
3787 return enc.WriteValue([]byte(`"called"`))
3788 })),
3789 },
3790 in: map[nocaseString]string{"hello": "world"},
3791 want: `{"called":"world"}`,
3792 }, {
3793 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidToken"),
3794 opts: []Options{
3795 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3796 return enc.WriteToken(jsontext.Null)
3797 })),
3798 },
3799 in: map[nocaseString]string{"hello": "world"},
3800 want: `{`,
3801 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3802 }, {
3803 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidValue"),
3804 opts: []Options{
3805 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3806 return enc.WriteValue([]byte(`null`))
3807 })),
3808 },
3809 in: map[nocaseString]string{"hello": "world"},
3810 want: `{`,
3811 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3812 }, {
3813 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
3814 opts: []Options{
3815 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3816 return []byte(`"called"`), nil
3817 })),
3818 },
3819 in: map[string]nocaseString{"hello": "world"},
3820 want: `{"hello":"called"}`,
3821 }, {
3822 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V1"),
3823 opts: []Options{
3824 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3825 _ = *v
3826 return []byte(`"called"`), nil
3827 })),
3828 },
3829 in: map[string]nocaseString{"hello": "world"},
3830 want: `{"hello":"called"}`,
3831 }, {
3832 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
3833 opts: []Options{
3834 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3835 _ = *v.(*nocaseString)
3836 return []byte(`"called"`), nil
3837 })),
3838 },
3839 in: map[string]nocaseString{"hello": "world"},
3840 want: `{"hello":"called"}`,
3841 }, {
3842 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
3843 opts: []Options{
3844 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3845 return enc.WriteValue([]byte(`"called"`))
3846 })),
3847 },
3848 in: map[string]nocaseString{"hello": "world"},
3849 want: `{"hello":"called"}`,
3850 }, {
3851 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V2"),
3852 opts: []Options{
3853 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3854 _ = *v
3855 return enc.WriteValue([]byte(`"called"`))
3856 })),
3857 },
3858 in: map[string]nocaseString{"hello": "world"},
3859 want: `{"hello":"called"}`,
3860 }, {
3861 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
3862 opts: []Options{
3863 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3864 _ = *v.(*nocaseString)
3865 return enc.WriteValue([]byte(`"called"`))
3866 })),
3867 },
3868 in: map[string]nocaseString{"hello": "world"},
3869 want: `{"hello":"called"}`,
3870 }, {
3871 name: jsontest.Name("Funtions/Struct/Fields"),
3872 opts: []Options{
3873 WithMarshalers(JoinMarshalers(
3874 MarshalFunc(func(v bool) ([]byte, error) {
3875 return []byte(`"called1"`), nil
3876 }),
3877 MarshalFunc(func(v *string) ([]byte, error) {
3878 return []byte(`"called2"`), nil
3879 }),
3880 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3881 return enc.WriteValue([]byte(`"called3"`))
3882 }),
3883 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3884 return enc.WriteValue([]byte(`"called4"`))
3885 }),
3886 )),
3887 },
3888 in: structScalars{},
3889 want: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":0,"Float":0}`,
3890 }, {
3891 name: jsontest.Name("Functions/Struct/OmitEmpty"),
3892 opts: []Options{
3893 WithMarshalers(JoinMarshalers(
3894 MarshalFunc(func(v bool) ([]byte, error) {
3895 return []byte(`null`), nil
3896 }),
3897 MarshalFunc(func(v string) ([]byte, error) {
3898 return []byte(`"called1"`), nil
3899 }),
3900 MarshalFunc(func(v *stringMarshalNonEmpty) ([]byte, error) {
3901 return []byte(`""`), nil
3902 }),
3903 MarshalToFunc(func(enc *jsontext.Encoder, v bytesMarshalNonEmpty) error {
3904 return enc.WriteValue([]byte(`{}`))
3905 }),
3906 MarshalToFunc(func(enc *jsontext.Encoder, v *float64) error {
3907 return enc.WriteValue([]byte(`[]`))
3908 }),
3909 MarshalFunc(func(v mapMarshalNonEmpty) ([]byte, error) {
3910 return []byte(`"called2"`), nil
3911 }),
3912 MarshalFunc(func(v []string) ([]byte, error) {
3913 return []byte(`"called3"`), nil
3914 }),
3915 MarshalToFunc(func(enc *jsontext.Encoder, v *sliceMarshalNonEmpty) error {
3916 return enc.WriteValue([]byte(`"called4"`))
3917 }),
3918 )),
3919 },
3920 in: structOmitEmptyAll{},
3921 want: `{"String":"called1","MapNonEmpty":"called2","Slice":"called3","SliceNonEmpty":"called4"}`,
3922 }, {
3923 name: jsontest.Name("Functions/Struct/OmitZero"),
3924 opts: []Options{
3925 WithMarshalers(JoinMarshalers(
3926 MarshalFunc(func(v bool) ([]byte, error) {
3927 panic("should not be called")
3928 }),
3929 MarshalFunc(func(v *string) ([]byte, error) {
3930 panic("should not be called")
3931 }),
3932 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3933 panic("should not be called")
3934 }),
3935 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3936 panic("should not be called")
3937 }),
3938 )),
3939 },
3940 in: structOmitZeroAll{},
3941 want: `{}`,
3942 }, {
3943 name: jsontest.Name("Functions/Struct/Inlined"),
3944 opts: []Options{
3945 WithMarshalers(JoinMarshalers(
3946 MarshalFunc(func(v structInlinedL1) ([]byte, error) {
3947 panic("should not be called")
3948 }),
3949 MarshalToFunc(func(enc *jsontext.Encoder, v *StructEmbed2) error {
3950 panic("should not be called")
3951 }),
3952 )),
3953 },
3954 in: structInlined{},
3955 want: `{"D":""}`,
3956 }, {
3957 name: jsontest.Name("Functions/Slice/Elem"),
3958 opts: []Options{
3959 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3960 return []byte(`"` + strconv.FormatBool(v) + `"`), nil
3961 })),
3962 },
3963 in: []bool{true, false},
3964 want: `["true","false"]`,
3965 }, {
3966 name: jsontest.Name("Functions/Array/Elem"),
3967 opts: []Options{
3968 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3969 return enc.WriteValue([]byte(`"` + strconv.FormatBool(*v) + `"`))
3970 })),
3971 },
3972 in: [2]bool{true, false},
3973 want: `["true","false"]`,
3974 }, {
3975 name: jsontest.Name("Functions/Pointer/Nil"),
3976 opts: []Options{
3977 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3978 panic("should not be called")
3979 })),
3980 },
3981 in: struct{ X *bool }{nil},
3982 want: `{"X":null}`,
3983 }, {
3984 name: jsontest.Name("Functions/Pointer/NonNil"),
3985 opts: []Options{
3986 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3987 return enc.WriteValue([]byte(`"called"`))
3988 })),
3989 },
3990 in: struct{ X *bool }{addr(false)},
3991 want: `{"X":"called"}`,
3992 }, {
3993 name: jsontest.Name("Functions/Interface/Nil"),
3994 opts: []Options{
3995 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
3996 panic("should not be called")
3997 })),
3998 },
3999 in: struct{ X fmt.Stringer }{nil},
4000 want: `{"X":null}`,
4001 }, {
4002 name: jsontest.Name("Functions/Interface/NonNil/MatchInterface"),
4003 opts: []Options{
4004 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
4005 return enc.WriteValue([]byte(`"called"`))
4006 })),
4007 },
4008 in: struct{ X fmt.Stringer }{valueStringer{}},
4009 want: `{"X":"called"}`,
4010 }, {
4011 name: jsontest.Name("Functions/Interface/NonNil/MatchConcrete"),
4012 opts: []Options{
4013 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4014 return enc.WriteValue([]byte(`"called"`))
4015 })),
4016 },
4017 in: struct{ X fmt.Stringer }{valueStringer{}},
4018 want: `{"X":"called"}`,
4019 }, {
4020 name: jsontest.Name("Functions/Interface/NonNil/MatchPointer"),
4021 opts: []Options{
4022 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4023 return enc.WriteValue([]byte(`"called"`))
4024 })),
4025 },
4026 in: struct{ X fmt.Stringer }{valueStringer{}},
4027 want: `{"X":"called"}`,
4028 }, {
4029 name: jsontest.Name("Functions/Interface/Any"),
4030 in: []any{
4031 nil,
4032 valueStringer{},
4033 (*valueStringer)(nil),
4034 addr(valueStringer{}),
4035 (**valueStringer)(nil),
4036 addr((*valueStringer)(nil)),
4037 addr(addr(valueStringer{})),
4038 pointerStringer{},
4039 (*pointerStringer)(nil),
4040 addr(pointerStringer{}),
4041 (**pointerStringer)(nil),
4042 addr((*pointerStringer)(nil)),
4043 addr(addr(pointerStringer{})),
4044 "LAST",
4045 },
4046 want: `[null,{},null,{},null,null,{},{},null,{},null,null,{},"LAST"]`,
4047 opts: []Options{
4048 WithMarshalers(func() *Marshalers {
4049 type P struct {
4050 D int
4051 N int64
4052 }
4053 type PV struct {
4054 P P
4055 V any
4056 }
4057
4058 var lastChecks []func() error
4059 checkLast := func() error {
4060 for _, fn := range lastChecks {
4061 if err := fn(); err != nil {
4062 return err
4063 }
4064 }
4065 return errors.ErrUnsupported
4066 }
4067 makeValueChecker := func(name string, want []PV) func(e *jsontext.Encoder, v any) error {
4068 checkNext := func(e *jsontext.Encoder, v any) error {
4069 xe := export.Encoder(e)
4070 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4071 rv := reflect.ValueOf(v)
4072 pv := PV{p, v}
4073 switch {
4074 case len(want) == 0:
4075 return fmt.Errorf("%s: %v: got more values than expected", name, p)
4076 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
4077 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
4078 case !reflect.DeepEqual(pv, want[0]):
4079 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
4080 default:
4081 want = want[1:]
4082 return errors.ErrUnsupported
4083 }
4084 }
4085 lastChecks = append(lastChecks, func() error {
4086 if len(want) > 0 {
4087 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4088 }
4089 return nil
4090 })
4091 return checkNext
4092 }
4093 makePositionChecker := func(name string, want []P) func(e *jsontext.Encoder, v any) error {
4094 checkNext := func(e *jsontext.Encoder, v any) error {
4095 xe := export.Encoder(e)
4096 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4097 switch {
4098 case len(want) == 0:
4099 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
4100 case p != want[0]:
4101 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
4102 default:
4103 want = want[1:]
4104 return errors.ErrUnsupported
4105 }
4106 }
4107 lastChecks = append(lastChecks, func() error {
4108 if len(want) > 0 {
4109 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4110 }
4111 return nil
4112 })
4113 return checkNext
4114 }
4115
4116 wantAny := []PV{
4117 {P{0, 0}, addr([]any{
4118 nil,
4119 valueStringer{},
4120 (*valueStringer)(nil),
4121 addr(valueStringer{}),
4122 (**valueStringer)(nil),
4123 addr((*valueStringer)(nil)),
4124 addr(addr(valueStringer{})),
4125 pointerStringer{},
4126 (*pointerStringer)(nil),
4127 addr(pointerStringer{}),
4128 (**pointerStringer)(nil),
4129 addr((*pointerStringer)(nil)),
4130 addr(addr(pointerStringer{})),
4131 "LAST",
4132 })},
4133 {P{1, 0}, addr(any(nil))},
4134 {P{1, 1}, addr(any(valueStringer{}))},
4135 {P{1, 1}, addr(valueStringer{})},
4136 {P{1, 2}, addr(any((*valueStringer)(nil)))},
4137 {P{1, 2}, addr((*valueStringer)(nil))},
4138 {P{1, 3}, addr(any(addr(valueStringer{})))},
4139 {P{1, 3}, addr(addr(valueStringer{}))},
4140 {P{1, 3}, addr(valueStringer{})},
4141 {P{1, 4}, addr(any((**valueStringer)(nil)))},
4142 {P{1, 4}, addr((**valueStringer)(nil))},
4143 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
4144 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
4145 {P{1, 5}, addr((*valueStringer)(nil))},
4146 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
4147 {P{1, 6}, addr(addr(addr(valueStringer{})))},
4148 {P{1, 6}, addr(addr(valueStringer{}))},
4149 {P{1, 6}, addr(valueStringer{})},
4150 {P{1, 7}, addr(any(pointerStringer{}))},
4151 {P{1, 7}, addr(pointerStringer{})},
4152 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
4153 {P{1, 8}, addr((*pointerStringer)(nil))},
4154 {P{1, 9}, addr(any(addr(pointerStringer{})))},
4155 {P{1, 9}, addr(addr(pointerStringer{}))},
4156 {P{1, 9}, addr(pointerStringer{})},
4157 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
4158 {P{1, 10}, addr((**pointerStringer)(nil))},
4159 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
4160 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
4161 {P{1, 11}, addr((*pointerStringer)(nil))},
4162 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
4163 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
4164 {P{1, 12}, addr(addr(pointerStringer{}))},
4165 {P{1, 12}, addr(pointerStringer{})},
4166 {P{1, 13}, addr(any("LAST"))},
4167 {P{1, 13}, addr("LAST")},
4168 }
4169 checkAny := makeValueChecker("any", wantAny)
4170 anyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v any) error {
4171 return checkAny(enc, v)
4172 })
4173
4174 var wantPointerAny []PV
4175 for _, v := range wantAny {
4176 if _, ok := v.V.(*any); ok {
4177 wantPointerAny = append(wantPointerAny, v)
4178 }
4179 }
4180 checkPointerAny := makeValueChecker("*any", wantPointerAny)
4181 pointerAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *any) error {
4182 return checkPointerAny(enc, v)
4183 })
4184
4185 checkNamedAny := makeValueChecker("namedAny", wantAny)
4186 namedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v namedAny) error {
4187 return checkNamedAny(enc, v)
4188 })
4189
4190 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
4191 pointerNamedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *namedAny) error {
4192 return checkPointerNamedAny(enc, v)
4193 })
4194
4195 type stringer = fmt.Stringer
4196 var wantStringer []PV
4197 for _, v := range wantAny {
4198 if _, ok := v.V.(stringer); ok {
4199 wantStringer = append(wantStringer, v)
4200 }
4201 }
4202 checkStringer := makeValueChecker("stringer", wantStringer)
4203 stringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v stringer) error {
4204 return checkStringer(enc, v)
4205 })
4206
4207 checkPointerStringer := makeValueChecker("*stringer", nil)
4208 pointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *stringer) error {
4209 return checkPointerStringer(enc, v)
4210 })
4211
4212 wantValueStringer := []P{{1, 1}, {1, 3}, {1, 6}}
4213 checkValueValueStringer := makePositionChecker("valueStringer", wantValueStringer)
4214 valueValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4215 return checkValueValueStringer(enc, v)
4216 })
4217
4218 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
4219 pointerValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4220 return checkPointerValueStringer(enc, v)
4221 })
4222
4223 wantPointerStringer := []P{{1, 7}, {1, 9}, {1, 12}}
4224 checkValuePointerStringer := makePositionChecker("pointerStringer", wantPointerStringer)
4225 valuePointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v pointerStringer) error {
4226 return checkValuePointerStringer(enc, v)
4227 })
4228
4229 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
4230 pointerPointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *pointerStringer) error {
4231 return checkPointerPointerStringer(enc, v)
4232 })
4233
4234 lastMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
4235 return checkLast()
4236 })
4237
4238 return JoinMarshalers(
4239 anyMarshaler,
4240 pointerAnyMarshaler,
4241 namedAnyMarshaler,
4242 pointerNamedAnyMarshaler,
4243 stringerMarshaler,
4244 pointerStringerMarshaler,
4245 valueValueStringerMarshaler,
4246 pointerValueStringerMarshaler,
4247 valuePointerStringerMarshaler,
4248 pointerPointerStringerMarshaler,
4249 lastMarshaler,
4250 )
4251 }()),
4252 },
4253 }, {
4254 name: jsontest.Name("Functions/Precedence/V1First"),
4255 opts: []Options{
4256 WithMarshalers(JoinMarshalers(
4257 MarshalFunc(func(bool) ([]byte, error) {
4258 return []byte(`"called"`), nil
4259 }),
4260 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4261 panic("should not be called")
4262 }),
4263 )),
4264 },
4265 in: true,
4266 want: `"called"`,
4267 }, {
4268 name: jsontest.Name("Functions/Precedence/V2First"),
4269 opts: []Options{
4270 WithMarshalers(JoinMarshalers(
4271 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4272 return enc.WriteToken(jsontext.String("called"))
4273 }),
4274 MarshalFunc(func(bool) ([]byte, error) {
4275 panic("should not be called")
4276 }),
4277 )),
4278 },
4279 in: true,
4280 want: `"called"`,
4281 }, {
4282 name: jsontest.Name("Functions/Precedence/V2Skipped"),
4283 opts: []Options{
4284 WithMarshalers(JoinMarshalers(
4285 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4286 return errors.ErrUnsupported
4287 }),
4288 MarshalFunc(func(bool) ([]byte, error) {
4289 return []byte(`"called"`), nil
4290 }),
4291 )),
4292 },
4293 in: true,
4294 want: `"called"`,
4295 }, {
4296 name: jsontest.Name("Functions/Precedence/NestedFirst"),
4297 opts: []Options{
4298 WithMarshalers(JoinMarshalers(
4299 JoinMarshalers(
4300 MarshalFunc(func(bool) ([]byte, error) {
4301 return []byte(`"called"`), nil
4302 }),
4303 ),
4304 MarshalFunc(func(bool) ([]byte, error) {
4305 panic("should not be called")
4306 }),
4307 )),
4308 },
4309 in: true,
4310 want: `"called"`,
4311 }, {
4312 name: jsontest.Name("Functions/Precedence/NestedLast"),
4313 opts: []Options{
4314 WithMarshalers(JoinMarshalers(
4315 MarshalFunc(func(bool) ([]byte, error) {
4316 return []byte(`"called"`), nil
4317 }),
4318 JoinMarshalers(
4319 MarshalFunc(func(bool) ([]byte, error) {
4320 panic("should not be called")
4321 }),
4322 ),
4323 )),
4324 },
4325 in: true,
4326 want: `"called"`,
4327 }, {
4328 name: jsontest.Name("Duration/Zero"),
4329 in: struct {
4330 D1 time.Duration `json:",format:units"`
4331 D2 time.Duration `json:",format:nano"`
4332 }{0, 0},
4333 want: `{"D1":"0s","D2":0}`,
4334 skip: !internal.ExpJSONFormat,
4335 }, {
4336 name: jsontest.Name("Duration/Positive"),
4337 in: struct {
4338 D1 time.Duration `json:",format:units"`
4339 D2 time.Duration `json:",format:nano"`
4340 }{
4341 123456789123456789,
4342 123456789123456789,
4343 },
4344 want: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
4345 skip: !internal.ExpJSONFormat,
4346 }, {
4347 name: jsontest.Name("Duration/Negative"),
4348 in: struct {
4349 D1 time.Duration `json:",format:units"`
4350 D2 time.Duration `json:",format:nano"`
4351 }{
4352 -123456789123456789,
4353 -123456789123456789,
4354 },
4355 want: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
4356 skip: !internal.ExpJSONFormat,
4357 }, {
4358 name: jsontest.Name("Duration/Nanos/String"),
4359 in: struct {
4360 D1 time.Duration `json:",string,format:nano"`
4361 D2 time.Duration `json:",string,format:nano"`
4362 D3 time.Duration `json:",string,format:nano"`
4363 }{
4364 math.MinInt64,
4365 0,
4366 math.MaxInt64,
4367 },
4368 want: `{"D1":"-9223372036854775808","D2":"0","D3":"9223372036854775807"}`,
4369 skip: !internal.ExpJSONFormat,
4370 }, {
4371 name: jsontest.Name("Duration/Format/Invalid"),
4372 in: struct {
4373 D time.Duration `json:",format:invalid"`
4374 }{},
4375 want: `{"D"`,
4376 wantErr: EM(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, T[time.Duration]()),
4377 skip: !internal.ExpJSONFormat,
4378 }, {
4379
4385 name: jsontest.Name("Duration/Format"),
4386 opts: []Options{jsontext.Multiline(true)},
4387 in: structDurationFormat{
4388 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4389 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4390 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4391 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4392 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4393 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4394 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4395 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4396 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4397 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4398 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4399 },
4400 want: `{
4401 "D1": "12h34m56.078090012s",
4402 "D2": "12h34m56.078090012s",
4403 "D3": 45296.078090012,
4404 "D4": "45296.078090012",
4405 "D5": 45296078.090012,
4406 "D6": "45296078.090012",
4407 "D7": 45296078090.012,
4408 "D8": "45296078090.012",
4409 "D9": 45296078090012,
4410 "D10": "45296078090012",
4411 "D11": "PT12H34M56.078090012S"
4412 }`,
4413 skip: !internal.ExpJSONFormat,
4414 }, {
4415
4424
4429 name: jsontest.Name("Duration/MapKey/Legacy"),
4430 opts: []Options{jsonflags.FormatDurationAsNano | 1},
4431 in: map[time.Duration]string{time.Second: ""},
4432 want: `{"1000000000":""}`,
4433 }, {
4434 name: jsontest.Name("Time/Zero"),
4435 in: struct {
4436 T1 time.Time
4437 T2 time.Time `json:",format:RFC822"`
4438 T3 time.Time `json:",format:'2006-01-02'"`
4439 T4 time.Time `json:",omitzero"`
4440 T5 time.Time `json:",omitempty"`
4441 }{
4442 time.Time{},
4443 time.Time{},
4444 time.Time{},
4445
4446
4447 time.Date(1, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC", 0)),
4448 time.Time{},
4449 },
4450 want: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T5":"0001-01-01T00:00:00Z"}`,
4451 skip: !internal.ExpJSONFormat,
4452 }, {
4453 name: jsontest.Name("Time/Format"),
4454 opts: []Options{jsontext.Multiline(true)},
4455 in: structTimeFormat{
4456 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4457 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4458 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4459 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4460 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4461 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4462 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4463 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4464 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4465 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4466 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4467 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4468 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4469 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4470 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4471 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4472 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4473 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4474 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4475 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4476 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4477 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4478 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4479 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4480 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4481 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4482 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4483 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4484 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4485 },
4486 want: `{
4487 "T1": "1234-01-02T03:04:05.000000006Z",
4488 "T2": "Mon Jan 2 03:04:05 1234",
4489 "T3": "Mon Jan 2 03:04:05 UTC 1234",
4490 "T4": "Mon Jan 02 03:04:05 +0000 1234",
4491 "T5": "02 Jan 34 03:04 UTC",
4492 "T6": "02 Jan 34 03:04 +0000",
4493 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
4494 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
4495 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
4496 "T10": "1234-01-02T03:04:05Z",
4497 "T11": "1234-01-02T03:04:05.000000006Z",
4498 "T12": "3:04AM",
4499 "T13": "Jan 2 03:04:05",
4500 "T14": "Jan 2 03:04:05.000",
4501 "T15": "Jan 2 03:04:05.000000",
4502 "T16": "Jan 2 03:04:05.000000006",
4503 "T17": "1234-01-02 03:04:05",
4504 "T18": "1234-01-02",
4505 "T19": "03:04:05",
4506 "T20": "1234-01-02",
4507 "T21": "\"weird\"1234",
4508 "T22": -23225777754.999999994,
4509 "T23": "-23225777754.999999994",
4510 "T24": -23225777754999.999994,
4511 "T25": "-23225777754999.999994",
4512 "T26": -23225777754999999.994,
4513 "T27": "-23225777754999999.994",
4514 "T28": -23225777754999999994,
4515 "T29": "-23225777754999999994"
4516 }`,
4517 skip: !internal.ExpJSONFormat,
4518 }, {
4519 name: jsontest.Name("Time/Format/Invalid"),
4520 in: struct {
4521 T time.Time `json:",format:UndefinedConstant"`
4522 }{},
4523 want: `{"T"`,
4524 wantErr: EM(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4525 skip: !internal.ExpJSONFormat,
4526 }, {
4527 name: jsontest.Name("Time/Format/YearOverflow"),
4528 in: struct {
4529 T1 time.Time
4530 T2 time.Time
4531 }{
4532 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4533 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC),
4534 },
4535 want: `{"T1":"9999-12-31T23:59:59Z","T2"`,
4536 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"9999-12-31T23:59:59Z","T2":`, "/T2").withType(0, timeTimeType),
4537 }, {
4538 name: jsontest.Name("Time/Format/YearUnderflow"),
4539 in: struct {
4540 T1 time.Time
4541 T2 time.Time
4542 }{
4543 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
4544 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4545 },
4546 want: `{"T1":"0000-01-01T00:00:00Z","T2"`,
4547 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"0000-01-01T00:00:00Z","T2":`, "/T2").withType(0, timeTimeType),
4548 }, {
4549 name: jsontest.Name("Time/Format/YearUnderflow"),
4550 in: struct{ T time.Time }{time.Date(-998, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second)},
4551 want: `{"T"`,
4552 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4553 }, {
4554 name: jsontest.Name("Time/Format/ZoneExact"),
4555 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 23*60*60+59*60))},
4556 want: `{"T":"2020-01-01T00:00:00+23:59"}`,
4557 }, {
4558 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4559 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 24*60*60))},
4560 want: `{"T"`,
4561 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4562 }, {
4563 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4564 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 123*60*60))},
4565 want: `{"T"`,
4566 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4567 }, {
4568 name: jsontest.Name("Time/IgnoreInvalidFormat"),
4569 opts: []Options{invalidFormatOption},
4570 in: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
4571 want: `"2000-01-01T00:00:00Z"`,
4572 }}
4573
4574 for _, tt := range tests {
4575 if tt.skip {
4576 continue
4577 }
4578 t.Run(tt.name.Name, func(t *testing.T) {
4579 var got []byte
4580 var gotErr error
4581 if tt.useWriter {
4582 bb := new(struct{ bytes.Buffer })
4583 gotErr = MarshalWrite(bb, tt.in, tt.opts...)
4584 got = bb.Bytes()
4585 } else {
4586 got, gotErr = Marshal(tt.in, tt.opts...)
4587 }
4588 if tt.canonicalize {
4589 (*jsontext.Value)(&got).Canonicalize()
4590 }
4591 if string(got) != tt.want {
4592 t.Errorf("%s: Marshal output mismatch:\ngot %s\nwant %s", tt.name.Where, got, tt.want)
4593 }
4594 if !reflect.DeepEqual(gotErr, tt.wantErr) {
4595 t.Errorf("%s: Marshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
4596 }
4597 })
4598 }
4599 }
4600
4601 func TestUnmarshal(t *testing.T) {
4602 tests := []struct {
4603 name jsontest.CaseName
4604 opts []Options
4605 inBuf string
4606 inVal any
4607 want any
4608 wantErr error
4609 skip bool
4610 }{{
4611 name: jsontest.Name("Nil"),
4612 inBuf: `null`,
4613 wantErr: EU(internal.ErrNonNilReference),
4614 }, {
4615 name: jsontest.Name("NilPointer"),
4616 inBuf: `null`,
4617 inVal: (*string)(nil),
4618 want: (*string)(nil),
4619 wantErr: EU(internal.ErrNonNilReference).withType(0, T[*string]()),
4620 }, {
4621 name: jsontest.Name("NonPointer"),
4622 inBuf: `null`,
4623 inVal: "unchanged",
4624 want: "unchanged",
4625 wantErr: EU(internal.ErrNonNilReference).withType(0, T[string]()),
4626 }, {
4627 name: jsontest.Name("Bools/TrailingJunk"),
4628 inBuf: `falsetrue`,
4629 inVal: addr(true),
4630 want: addr(false),
4631 wantErr: newInvalidCharacterError("t", "after top-level value", len64(`false`), ""),
4632 }, {
4633 name: jsontest.Name("Bools/Null"),
4634 inBuf: `null`,
4635 inVal: addr(true),
4636 want: addr(false),
4637 }, {
4638 name: jsontest.Name("Bools"),
4639 inBuf: `[null,false,true]`,
4640 inVal: new([]bool),
4641 want: addr([]bool{false, false, true}),
4642 }, {
4643 name: jsontest.Name("Bools/Named"),
4644 inBuf: `[null,false,true]`,
4645 inVal: new([]namedBool),
4646 want: addr([]namedBool{false, false, true}),
4647 }, {
4648 name: jsontest.Name("Bools/Invalid/StringifiedFalse"),
4649 opts: []Options{StringifyNumbers(true)},
4650 inBuf: `"false"`,
4651 inVal: addr(true),
4652 want: addr(true),
4653 wantErr: EU(nil).withType('"', boolType),
4654 }, {
4655 name: jsontest.Name("Bools/Invalid/StringifiedTrue"),
4656 opts: []Options{StringifyNumbers(true)},
4657 inBuf: `"true"`,
4658 inVal: addr(true),
4659 want: addr(true),
4660 wantErr: EU(nil).withType('"', boolType),
4661 }, {
4662 name: jsontest.Name("Bools/StringifiedBool/True"),
4663 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4664 inBuf: `"true"`,
4665 inVal: addr(false),
4666 want: addr(true),
4667 }, {
4668 name: jsontest.Name("Bools/StringifiedBool/False"),
4669 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4670 inBuf: `"false"`,
4671 inVal: addr(true),
4672 want: addr(false),
4673 }, {
4674 name: jsontest.Name("Bools/StringifiedBool/InvalidWhitespace"),
4675 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4676 inBuf: `"false "`,
4677 inVal: addr(true),
4678 want: addr(true),
4679 wantErr: EU(strconv.ErrSyntax).withVal(`"false "`).withType('"', boolType),
4680 }, {
4681 name: jsontest.Name("Bools/StringifiedBool/InvalidBool"),
4682 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4683 inBuf: `false`,
4684 inVal: addr(true),
4685 want: addr(true),
4686 wantErr: EU(nil).withType('f', boolType),
4687 }, {
4688 name: jsontest.Name("Bools/Invalid/Number"),
4689 inBuf: `0`,
4690 inVal: addr(true),
4691 want: addr(true),
4692 wantErr: EU(nil).withType('0', boolType),
4693 }, {
4694 name: jsontest.Name("Bools/Invalid/String"),
4695 inBuf: `""`,
4696 inVal: addr(true),
4697 want: addr(true),
4698 wantErr: EU(nil).withType('"', boolType),
4699 }, {
4700 name: jsontest.Name("Bools/Invalid/Object"),
4701 inBuf: `{}`,
4702 inVal: addr(true),
4703 want: addr(true),
4704 wantErr: EU(nil).withType('{', boolType),
4705 }, {
4706 name: jsontest.Name("Bools/Invalid/Array"),
4707 inBuf: `[]`,
4708 inVal: addr(true),
4709 want: addr(true),
4710 wantErr: EU(nil).withType('[', boolType),
4711 }, {
4712 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
4713 opts: []Options{invalidFormatOption},
4714 inBuf: `false`,
4715 inVal: addr(true),
4716 want: addr(false),
4717 }, {
4718 name: jsontest.Name("Strings/Null"),
4719 inBuf: `null`,
4720 inVal: addr("something"),
4721 want: addr(""),
4722 }, {
4723 name: jsontest.Name("Strings"),
4724 inBuf: `[null,"","hello","世界"]`,
4725 inVal: new([]string),
4726 want: addr([]string{"", "", "hello", "世界"}),
4727 }, {
4728 name: jsontest.Name("Strings/Escaped"),
4729 inBuf: `[null,"","\u0068\u0065\u006c\u006c\u006f","\u4e16\u754c"]`,
4730 inVal: new([]string),
4731 want: addr([]string{"", "", "hello", "世界"}),
4732 }, {
4733 name: jsontest.Name("Strings/Named"),
4734 inBuf: `[null,"","hello","世界"]`,
4735 inVal: new([]namedString),
4736 want: addr([]namedString{"", "", "hello", "世界"}),
4737 }, {
4738 name: jsontest.Name("Strings/Invalid/False"),
4739 inBuf: `false`,
4740 inVal: addr("nochange"),
4741 want: addr("nochange"),
4742 wantErr: EU(nil).withType('f', stringType),
4743 }, {
4744 name: jsontest.Name("Strings/Invalid/True"),
4745 inBuf: `true`,
4746 inVal: addr("nochange"),
4747 want: addr("nochange"),
4748 wantErr: EU(nil).withType('t', stringType),
4749 }, {
4750 name: jsontest.Name("Strings/Invalid/Object"),
4751 inBuf: `{}`,
4752 inVal: addr("nochange"),
4753 want: addr("nochange"),
4754 wantErr: EU(nil).withType('{', stringType),
4755 }, {
4756 name: jsontest.Name("Strings/Invalid/Array"),
4757 inBuf: `[]`,
4758 inVal: addr("nochange"),
4759 want: addr("nochange"),
4760 wantErr: EU(nil).withType('[', stringType),
4761 }, {
4762 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
4763 opts: []Options{invalidFormatOption},
4764 inBuf: `"hello"`,
4765 inVal: addr("goodbye"),
4766 want: addr("hello"),
4767 }, {
4768 name: jsontest.Name("Strings/StringifiedString"),
4769 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4770 inBuf: `"\"foo\""`,
4771 inVal: new(string),
4772 want: addr("foo"),
4773 }, {
4774 name: jsontest.Name("Strings/StringifiedString/InvalidWhitespace"),
4775 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4776 inBuf: `"\"foo\" "`,
4777 inVal: new(string),
4778 want: new(string),
4779 wantErr: EU(newInvalidCharacterError(" ", "after string value", 0, "")).withType('"', stringType),
4780 }, {
4781 name: jsontest.Name("Strings/StringifiedString/InvalidString"),
4782 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4783 inBuf: `""`,
4784 inVal: new(string),
4785 want: new(string),
4786 wantErr: EU(&jsontext.SyntacticError{Err: io.ErrUnexpectedEOF}).withType('"', stringType),
4787 }, {
4788 name: jsontest.Name("Bytes/Null"),
4789 inBuf: `null`,
4790 inVal: addr([]byte("something")),
4791 want: addr([]byte(nil)),
4792 }, {
4793 name: jsontest.Name("Bytes"),
4794 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4795 inVal: new([][]byte),
4796 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4797 }, {
4798 name: jsontest.Name("Bytes/Large"),
4799 inBuf: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
4800 inVal: new([]byte),
4801 want: addr([]byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on.")),
4802 }, {
4803 name: jsontest.Name("Bytes/Reuse"),
4804 inBuf: `"AQID"`,
4805 inVal: addr([]byte("changed")),
4806 want: addr([]byte{1, 2, 3}),
4807 }, {
4808 name: jsontest.Name("Bytes/Escaped"),
4809 inBuf: `[null,"","\u0041\u0051\u003d\u003d","\u0041\u0051\u0049\u003d","\u0041\u0051\u0049\u0044"]`,
4810 inVal: new([][]byte),
4811 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4812 }, {
4813 name: jsontest.Name("Bytes/Named"),
4814 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4815 inVal: new([]namedBytes),
4816 want: addr([]namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4817 }, {
4818 name: jsontest.Name("Bytes/NotStringified"),
4819 opts: []Options{StringifyNumbers(true)},
4820 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4821 inVal: new([][]byte),
4822 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4823 }, {
4824
4825
4826 name: jsontest.Name("Bytes/Invariant"),
4827 inBuf: `[null,[],[1],[1,2],[1,2,3]]`,
4828 inVal: new([][]namedByte),
4829 want: addr([][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4830 }, {
4831
4832
4833 name: jsontest.Name("Bytes/ByteArray"),
4834 inBuf: `"aGVsbG8="`,
4835 inVal: new([5]byte),
4836 want: addr([5]byte{'h', 'e', 'l', 'l', 'o'}),
4837 }, {
4838 name: jsontest.Name("Bytes/ByteArray0/Valid"),
4839 inBuf: `""`,
4840 inVal: new([0]byte),
4841 want: addr([0]byte{}),
4842 }, {
4843 name: jsontest.Name("Bytes/ByteArray0/Invalid"),
4844 inBuf: `"A"`,
4845 inVal: new([0]byte),
4846 want: addr([0]byte{}),
4847 wantErr: EU(func() error {
4848 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("A"))
4849 return err
4850 }()).withType('"', T[[0]byte]()),
4851 }, {
4852 name: jsontest.Name("Bytes/ByteArray0/Overflow"),
4853 inBuf: `"AA=="`,
4854 inVal: new([0]byte),
4855 want: addr([0]byte{}),
4856 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 0")).withType('"', T[[0]byte]()),
4857 }, {
4858 name: jsontest.Name("Bytes/ByteArray1/Valid"),
4859 inBuf: `"AQ=="`,
4860 inVal: new([1]byte),
4861 want: addr([1]byte{1}),
4862 }, {
4863 name: jsontest.Name("Bytes/ByteArray1/Invalid"),
4864 inBuf: `"$$=="`,
4865 inVal: new([1]byte),
4866 want: addr([1]byte{}),
4867 wantErr: EU(func() error {
4868 _, err := base64.StdEncoding.Decode(make([]byte, 1), []byte("$$=="))
4869 return err
4870 }()).withType('"', T[[1]byte]()),
4871 }, {
4872 name: jsontest.Name("Bytes/ByteArray1/Underflow"),
4873 inBuf: `""`,
4874 inVal: new([1]byte),
4875 want: addr([1]byte{}),
4876 wantErr: EU(errors.New("decoded length of 0 mismatches array length of 1")).withType('"', T[[1]byte]()),
4877 }, {
4878 name: jsontest.Name("Bytes/ByteArray1/Overflow"),
4879 inBuf: `"AQI="`,
4880 inVal: new([1]byte),
4881 want: addr([1]byte{1}),
4882 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 1")).withType('"', T[[1]byte]()),
4883 }, {
4884 name: jsontest.Name("Bytes/ByteArray2/Valid"),
4885 inBuf: `"AQI="`,
4886 inVal: new([2]byte),
4887 want: addr([2]byte{1, 2}),
4888 }, {
4889 name: jsontest.Name("Bytes/ByteArray2/Invalid"),
4890 inBuf: `"$$$="`,
4891 inVal: new([2]byte),
4892 want: addr([2]byte{}),
4893 wantErr: EU(func() error {
4894 _, err := base64.StdEncoding.Decode(make([]byte, 2), []byte("$$$="))
4895 return err
4896 }()).withType('"', T[[2]byte]()),
4897 }, {
4898 name: jsontest.Name("Bytes/ByteArray2/Underflow"),
4899 inBuf: `"AQ=="`,
4900 inVal: new([2]byte),
4901 want: addr([2]byte{1, 0}),
4902 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 2")).withType('"', T[[2]byte]()),
4903 }, {
4904 name: jsontest.Name("Bytes/ByteArray2/Underflow/Allowed"),
4905 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4906 inBuf: `"AQ=="`,
4907 inVal: new([2]byte),
4908 want: addr([2]byte{1, 0}),
4909 }, {
4910 name: jsontest.Name("Bytes/ByteArray2/Overflow"),
4911 inBuf: `"AQID"`,
4912 inVal: new([2]byte),
4913 want: addr([2]byte{1, 2}),
4914 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 2")).withType('"', T[[2]byte]()),
4915 }, {
4916 name: jsontest.Name("Bytes/ByteArray2/Overflow/Allowed"),
4917 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4918 inBuf: `"AQID"`,
4919 inVal: new([2]byte),
4920 want: addr([2]byte{1, 2}),
4921 }, {
4922 name: jsontest.Name("Bytes/ByteArray3/Valid"),
4923 inBuf: `"AQID"`,
4924 inVal: new([3]byte),
4925 want: addr([3]byte{1, 2, 3}),
4926 }, {
4927 name: jsontest.Name("Bytes/ByteArray3/Invalid"),
4928 inBuf: `"$$$$"`,
4929 inVal: new([3]byte),
4930 want: addr([3]byte{}),
4931 wantErr: EU(func() error {
4932 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("$$$$"))
4933 return err
4934 }()).withType('"', T[[3]byte]()),
4935 }, {
4936 name: jsontest.Name("Bytes/ByteArray3/Underflow"),
4937 inBuf: `"AQI="`,
4938 inVal: addr([3]byte{0xff, 0xff, 0xff}),
4939 want: addr([3]byte{1, 2, 0}),
4940 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 3")).withType('"', T[[3]byte]()),
4941 }, {
4942 name: jsontest.Name("Bytes/ByteArray3/Overflow"),
4943 inBuf: `"AQIDAQ=="`,
4944 inVal: new([3]byte),
4945 want: addr([3]byte{1, 2, 3}),
4946 wantErr: EU(errors.New("decoded length of 4 mismatches array length of 3")).withType('"', T[[3]byte]()),
4947 }, {
4948 name: jsontest.Name("Bytes/ByteArray4/Valid"),
4949 inBuf: `"AQIDBA=="`,
4950 inVal: new([4]byte),
4951 want: addr([4]byte{1, 2, 3, 4}),
4952 }, {
4953 name: jsontest.Name("Bytes/ByteArray4/Invalid"),
4954 inBuf: `"$$$$$$=="`,
4955 inVal: new([4]byte),
4956 want: addr([4]byte{}),
4957 wantErr: EU(func() error {
4958 _, err := base64.StdEncoding.Decode(make([]byte, 4), []byte("$$$$$$=="))
4959 return err
4960 }()).withType('"', T[[4]byte]()),
4961 }, {
4962 name: jsontest.Name("Bytes/ByteArray4/Underflow"),
4963 inBuf: `"AQID"`,
4964 inVal: new([4]byte),
4965 want: addr([4]byte{1, 2, 3, 0}),
4966 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 4")).withType('"', T[[4]byte]()),
4967 }, {
4968 name: jsontest.Name("Bytes/ByteArray4/Overflow"),
4969 inBuf: `"AQIDBAU="`,
4970 inVal: new([4]byte),
4971 want: addr([4]byte{1, 2, 3, 4}),
4972 wantErr: EU(errors.New("decoded length of 5 mismatches array length of 4")).withType('"', T[[4]byte]()),
4973 }, {
4974
4975
4976 name: jsontest.Name("Bytes/NamedByteArray"),
4977 inBuf: `[104,101,108,108,111]`,
4978 inVal: new([5]namedByte),
4979 want: addr([5]namedByte{'h', 'e', 'l', 'l', 'o'}),
4980 }, {
4981 name: jsontest.Name("Bytes/Valid/Denormalized"),
4982 inBuf: `"AR=="`,
4983 inVal: new([]byte),
4984 want: addr([]byte{1}),
4985 }, {
4986 name: jsontest.Name("Bytes/Invalid/Unpadded1"),
4987 inBuf: `"AQ="`,
4988 inVal: addr([]byte("nochange")),
4989 want: addr([]byte("nochange")),
4990 wantErr: EU(func() error {
4991 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ="))
4992 return err
4993 }()).withType('"', bytesType),
4994 }, {
4995 name: jsontest.Name("Bytes/Invalid/Unpadded2"),
4996 inBuf: `"AQ"`,
4997 inVal: addr([]byte("nochange")),
4998 want: addr([]byte("nochange")),
4999 wantErr: EU(func() error {
5000 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ"))
5001 return err
5002 }()).withType('"', bytesType),
5003 }, {
5004 name: jsontest.Name("Bytes/Invalid/Character"),
5005 inBuf: `"@@@@"`,
5006 inVal: addr([]byte("nochange")),
5007 want: addr([]byte("nochange")),
5008 wantErr: EU(func() error {
5009 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("@@@@"))
5010 return err
5011 }()).withType('"', bytesType),
5012 }, {
5013 name: jsontest.Name("Bytes/Invalid/Bool"),
5014 inBuf: `true`,
5015 inVal: addr([]byte("nochange")),
5016 want: addr([]byte("nochange")),
5017 wantErr: EU(nil).withType('t', bytesType),
5018 }, {
5019 name: jsontest.Name("Bytes/Invalid/Number"),
5020 inBuf: `0`,
5021 inVal: addr([]byte("nochange")),
5022 want: addr([]byte("nochange")),
5023 wantErr: EU(nil).withType('0', bytesType),
5024 }, {
5025 name: jsontest.Name("Bytes/Invalid/Object"),
5026 inBuf: `{}`,
5027 inVal: addr([]byte("nochange")),
5028 want: addr([]byte("nochange")),
5029 wantErr: EU(nil).withType('{', bytesType),
5030 }, {
5031 name: jsontest.Name("Bytes/Invalid/Array"),
5032 inBuf: `[]`,
5033 inVal: addr([]byte("nochange")),
5034 want: addr([]byte("nochange")),
5035 wantErr: EU(nil).withType('[', bytesType),
5036 }, {
5037 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
5038 opts: []Options{invalidFormatOption},
5039 inBuf: `"aGVsbG8="`,
5040 inVal: new([]byte),
5041 want: addr([]byte("hello")),
5042 }, {
5043 name: jsontest.Name("Ints/Null"),
5044 inBuf: `null`,
5045 inVal: addr(int(1)),
5046 want: addr(int(0)),
5047 }, {
5048 name: jsontest.Name("Ints/Int"),
5049 inBuf: `1`,
5050 inVal: addr(int(0)),
5051 want: addr(int(1)),
5052 }, {
5053 name: jsontest.Name("Ints/Int8/MinOverflow"),
5054 inBuf: `-129`,
5055 inVal: addr(int8(-1)),
5056 want: addr(int8(-1)),
5057 wantErr: EU(strconv.ErrRange).withVal(`-129`).withType('0', T[int8]()),
5058 }, {
5059 name: jsontest.Name("Ints/Int8/Min"),
5060 inBuf: `-128`,
5061 inVal: addr(int8(0)),
5062 want: addr(int8(-128)),
5063 }, {
5064 name: jsontest.Name("Ints/Int8/Max"),
5065 inBuf: `127`,
5066 inVal: addr(int8(0)),
5067 want: addr(int8(127)),
5068 }, {
5069 name: jsontest.Name("Ints/Int8/MaxOverflow"),
5070 inBuf: `128`,
5071 inVal: addr(int8(-1)),
5072 want: addr(int8(-1)),
5073 wantErr: EU(strconv.ErrRange).withVal(`128`).withType('0', T[int8]()),
5074 }, {
5075 name: jsontest.Name("Ints/Int16/MinOverflow"),
5076 inBuf: `-32769`,
5077 inVal: addr(int16(-1)),
5078 want: addr(int16(-1)),
5079 wantErr: EU(strconv.ErrRange).withVal(`-32769`).withType('0', T[int16]()),
5080 }, {
5081 name: jsontest.Name("Ints/Int16/Min"),
5082 inBuf: `-32768`,
5083 inVal: addr(int16(0)),
5084 want: addr(int16(-32768)),
5085 }, {
5086 name: jsontest.Name("Ints/Int16/Max"),
5087 inBuf: `32767`,
5088 inVal: addr(int16(0)),
5089 want: addr(int16(32767)),
5090 }, {
5091 name: jsontest.Name("Ints/Int16/MaxOverflow"),
5092 inBuf: `32768`,
5093 inVal: addr(int16(-1)),
5094 want: addr(int16(-1)),
5095 wantErr: EU(strconv.ErrRange).withVal(`32768`).withType('0', T[int16]()),
5096 }, {
5097 name: jsontest.Name("Ints/Int32/MinOverflow"),
5098 inBuf: `-2147483649`,
5099 inVal: addr(int32(-1)),
5100 want: addr(int32(-1)),
5101 wantErr: EU(strconv.ErrRange).withVal(`-2147483649`).withType('0', T[int32]()),
5102 }, {
5103 name: jsontest.Name("Ints/Int32/Min"),
5104 inBuf: `-2147483648`,
5105 inVal: addr(int32(0)),
5106 want: addr(int32(-2147483648)),
5107 }, {
5108 name: jsontest.Name("Ints/Int32/Max"),
5109 inBuf: `2147483647`,
5110 inVal: addr(int32(0)),
5111 want: addr(int32(2147483647)),
5112 }, {
5113 name: jsontest.Name("Ints/Int32/MaxOverflow"),
5114 inBuf: `2147483648`,
5115 inVal: addr(int32(-1)),
5116 want: addr(int32(-1)),
5117 wantErr: EU(strconv.ErrRange).withVal(`2147483648`).withType('0', T[int32]()),
5118 }, {
5119 name: jsontest.Name("Ints/Int64/MinOverflow"),
5120 inBuf: `-9223372036854775809`,
5121 inVal: addr(int64(-1)),
5122 want: addr(int64(-1)),
5123 wantErr: EU(strconv.ErrRange).withVal(`-9223372036854775809`).withType('0', T[int64]()),
5124 }, {
5125 name: jsontest.Name("Ints/Int64/Min"),
5126 inBuf: `-9223372036854775808`,
5127 inVal: addr(int64(0)),
5128 want: addr(int64(-9223372036854775808)),
5129 }, {
5130 name: jsontest.Name("Ints/Int64/Max"),
5131 inBuf: `9223372036854775807`,
5132 inVal: addr(int64(0)),
5133 want: addr(int64(9223372036854775807)),
5134 }, {
5135 name: jsontest.Name("Ints/Int64/MaxOverflow"),
5136 inBuf: `9223372036854775808`,
5137 inVal: addr(int64(-1)),
5138 want: addr(int64(-1)),
5139 wantErr: EU(strconv.ErrRange).withVal(`9223372036854775808`).withType('0', T[int64]()),
5140 }, {
5141 name: jsontest.Name("Ints/Named"),
5142 inBuf: `-6464`,
5143 inVal: addr(namedInt64(0)),
5144 want: addr(namedInt64(-6464)),
5145 }, {
5146 name: jsontest.Name("Ints/Stringified"),
5147 opts: []Options{StringifyNumbers(true)},
5148 inBuf: `"-6464"`,
5149 inVal: new(int),
5150 want: addr(int(-6464)),
5151 }, {
5152 name: jsontest.Name("Ints/Stringified/Invalid"),
5153 opts: []Options{StringifyNumbers(true)},
5154 inBuf: `-6464`,
5155 inVal: new(int),
5156 want: new(int),
5157 wantErr: EU(nil).withType('0', T[int]()),
5158 }, {
5159 name: jsontest.Name("Ints/Stringified/LeadingZero"),
5160 opts: []Options{StringifyNumbers(true)},
5161 inBuf: `"00"`,
5162 inVal: addr(int(-1)),
5163 want: addr(int(-1)),
5164 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[int]()),
5165 }, {
5166 name: jsontest.Name("Ints/Escaped"),
5167 opts: []Options{StringifyNumbers(true)},
5168 inBuf: `"\u002d\u0036\u0034\u0036\u0034"`,
5169 inVal: new(int),
5170 want: addr(int(-6464)),
5171 }, {
5172 name: jsontest.Name("Ints/Valid/NegativeZero"),
5173 inBuf: `-0`,
5174 inVal: addr(int(1)),
5175 want: addr(int(0)),
5176 }, {
5177 name: jsontest.Name("Ints/Invalid/Fraction"),
5178 inBuf: `1.0`,
5179 inVal: addr(int(-1)),
5180 want: addr(int(-1)),
5181 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[int]()),
5182 }, {
5183 name: jsontest.Name("Ints/Invalid/Exponent"),
5184 inBuf: `1e0`,
5185 inVal: addr(int(-1)),
5186 want: addr(int(-1)),
5187 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[int]()),
5188 }, {
5189 name: jsontest.Name("Ints/Invalid/StringifiedFraction"),
5190 opts: []Options{StringifyNumbers(true)},
5191 inBuf: `"1.0"`,
5192 inVal: addr(int(-1)),
5193 want: addr(int(-1)),
5194 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[int]()),
5195 }, {
5196 name: jsontest.Name("Ints/Invalid/StringifiedExponent"),
5197 opts: []Options{StringifyNumbers(true)},
5198 inBuf: `"1e0"`,
5199 inVal: addr(int(-1)),
5200 want: addr(int(-1)),
5201 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[int]()),
5202 }, {
5203 name: jsontest.Name("Ints/Invalid/Overflow"),
5204 inBuf: `100000000000000000000000000000`,
5205 inVal: addr(int(-1)),
5206 want: addr(int(-1)),
5207 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[int]()),
5208 }, {
5209 name: jsontest.Name("Ints/Invalid/OverflowSyntax"),
5210 opts: []Options{StringifyNumbers(true)},
5211 inBuf: `"100000000000000000000000000000x"`,
5212 inVal: addr(int(-1)),
5213 want: addr(int(-1)),
5214 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[int]()),
5215 }, {
5216 name: jsontest.Name("Ints/Invalid/Whitespace"),
5217 opts: []Options{StringifyNumbers(true)},
5218 inBuf: `"0 "`,
5219 inVal: addr(int(-1)),
5220 want: addr(int(-1)),
5221 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[int]()),
5222 }, {
5223 name: jsontest.Name("Ints/Invalid/Bool"),
5224 inBuf: `true`,
5225 inVal: addr(int(-1)),
5226 want: addr(int(-1)),
5227 wantErr: EU(nil).withType('t', T[int]()),
5228 }, {
5229 name: jsontest.Name("Ints/Invalid/String"),
5230 inBuf: `"0"`,
5231 inVal: addr(int(-1)),
5232 want: addr(int(-1)),
5233 wantErr: EU(nil).withType('"', T[int]()),
5234 }, {
5235 name: jsontest.Name("Ints/Invalid/Object"),
5236 inBuf: `{}`,
5237 inVal: addr(int(-1)),
5238 want: addr(int(-1)),
5239 wantErr: EU(nil).withType('{', T[int]()),
5240 }, {
5241 name: jsontest.Name("Ints/Invalid/Array"),
5242 inBuf: `[]`,
5243 inVal: addr(int(-1)),
5244 want: addr(int(-1)),
5245 wantErr: EU(nil).withType('[', T[int]()),
5246 }, {
5247 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
5248 opts: []Options{invalidFormatOption},
5249 inBuf: `1`,
5250 inVal: addr(int(0)),
5251 want: addr(int(1)),
5252 }, {
5253 name: jsontest.Name("Uints/Null"),
5254 inBuf: `null`,
5255 inVal: addr(uint(1)),
5256 want: addr(uint(0)),
5257 }, {
5258 name: jsontest.Name("Uints/Uint"),
5259 inBuf: `1`,
5260 inVal: addr(uint(0)),
5261 want: addr(uint(1)),
5262 }, {
5263 name: jsontest.Name("Uints/Uint8/Min"),
5264 inBuf: `0`,
5265 inVal: addr(uint8(1)),
5266 want: addr(uint8(0)),
5267 }, {
5268 name: jsontest.Name("Uints/Uint8/Max"),
5269 inBuf: `255`,
5270 inVal: addr(uint8(0)),
5271 want: addr(uint8(255)),
5272 }, {
5273 name: jsontest.Name("Uints/Uint8/MaxOverflow"),
5274 inBuf: `256`,
5275 inVal: addr(uint8(1)),
5276 want: addr(uint8(1)),
5277 wantErr: EU(strconv.ErrRange).withVal(`256`).withType('0', T[uint8]()),
5278 }, {
5279 name: jsontest.Name("Uints/Uint16/Min"),
5280 inBuf: `0`,
5281 inVal: addr(uint16(1)),
5282 want: addr(uint16(0)),
5283 }, {
5284 name: jsontest.Name("Uints/Uint16/Max"),
5285 inBuf: `65535`,
5286 inVal: addr(uint16(0)),
5287 want: addr(uint16(65535)),
5288 }, {
5289 name: jsontest.Name("Uints/Uint16/MaxOverflow"),
5290 inBuf: `65536`,
5291 inVal: addr(uint16(1)),
5292 want: addr(uint16(1)),
5293 wantErr: EU(strconv.ErrRange).withVal(`65536`).withType('0', T[uint16]()),
5294 }, {
5295 name: jsontest.Name("Uints/Uint32/Min"),
5296 inBuf: `0`,
5297 inVal: addr(uint32(1)),
5298 want: addr(uint32(0)),
5299 }, {
5300 name: jsontest.Name("Uints/Uint32/Max"),
5301 inBuf: `4294967295`,
5302 inVal: addr(uint32(0)),
5303 want: addr(uint32(4294967295)),
5304 }, {
5305 name: jsontest.Name("Uints/Uint32/MaxOverflow"),
5306 inBuf: `4294967296`,
5307 inVal: addr(uint32(1)),
5308 want: addr(uint32(1)),
5309 wantErr: EU(strconv.ErrRange).withVal(`4294967296`).withType('0', T[uint32]()),
5310 }, {
5311 name: jsontest.Name("Uints/Uint64/Min"),
5312 inBuf: `0`,
5313 inVal: addr(uint64(1)),
5314 want: addr(uint64(0)),
5315 }, {
5316 name: jsontest.Name("Uints/Uint64/Max"),
5317 inBuf: `18446744073709551615`,
5318 inVal: addr(uint64(0)),
5319 want: addr(uint64(18446744073709551615)),
5320 }, {
5321 name: jsontest.Name("Uints/Uint64/MaxOverflow"),
5322 inBuf: `18446744073709551616`,
5323 inVal: addr(uint64(1)),
5324 want: addr(uint64(1)),
5325 wantErr: EU(strconv.ErrRange).withVal(`18446744073709551616`).withType('0', T[uint64]()),
5326 }, {
5327 name: jsontest.Name("Uints/Uintptr"),
5328 inBuf: `1`,
5329 inVal: addr(uintptr(0)),
5330 want: addr(uintptr(1)),
5331 }, {
5332 name: jsontest.Name("Uints/Named"),
5333 inBuf: `6464`,
5334 inVal: addr(namedUint64(0)),
5335 want: addr(namedUint64(6464)),
5336 }, {
5337 name: jsontest.Name("Uints/Stringified"),
5338 opts: []Options{StringifyNumbers(true)},
5339 inBuf: `"6464"`,
5340 inVal: new(uint),
5341 want: addr(uint(6464)),
5342 }, {
5343 name: jsontest.Name("Uints/Stringified/Invalid"),
5344 opts: []Options{StringifyNumbers(true)},
5345 inBuf: `6464`,
5346 inVal: new(uint),
5347 want: new(uint),
5348 wantErr: EU(nil).withType('0', T[uint]()),
5349 }, {
5350 name: jsontest.Name("Uints/Stringified/LeadingZero"),
5351 opts: []Options{StringifyNumbers(true)},
5352 inBuf: `"00"`,
5353 inVal: addr(uint(1)),
5354 want: addr(uint(1)),
5355 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[uint]()),
5356 }, {
5357 name: jsontest.Name("Uints/Escaped"),
5358 opts: []Options{StringifyNumbers(true)},
5359 inBuf: `"\u0036\u0034\u0036\u0034"`,
5360 inVal: new(uint),
5361 want: addr(uint(6464)),
5362 }, {
5363 name: jsontest.Name("Uints/Invalid/NegativeOne"),
5364 inBuf: `-1`,
5365 inVal: addr(uint(1)),
5366 want: addr(uint(1)),
5367 wantErr: EU(strconv.ErrSyntax).withVal(`-1`).withType('0', T[uint]()),
5368 }, {
5369 name: jsontest.Name("Uints/Invalid/NegativeZero"),
5370 inBuf: `-0`,
5371 inVal: addr(uint(1)),
5372 want: addr(uint(1)),
5373 wantErr: EU(strconv.ErrSyntax).withVal(`-0`).withType('0', T[uint]()),
5374 }, {
5375 name: jsontest.Name("Uints/Invalid/Fraction"),
5376 inBuf: `1.0`,
5377 inVal: addr(uint(10)),
5378 want: addr(uint(10)),
5379 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[uint]()),
5380 }, {
5381 name: jsontest.Name("Uints/Invalid/Exponent"),
5382 inBuf: `1e0`,
5383 inVal: addr(uint(10)),
5384 want: addr(uint(10)),
5385 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[uint]()),
5386 }, {
5387 name: jsontest.Name("Uints/Invalid/StringifiedFraction"),
5388 opts: []Options{StringifyNumbers(true)},
5389 inBuf: `"1.0"`,
5390 inVal: addr(uint(10)),
5391 want: addr(uint(10)),
5392 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[uint]()),
5393 }, {
5394 name: jsontest.Name("Uints/Invalid/StringifiedExponent"),
5395 opts: []Options{StringifyNumbers(true)},
5396 inBuf: `"1e0"`,
5397 inVal: addr(uint(10)),
5398 want: addr(uint(10)),
5399 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[uint]()),
5400 }, {
5401 name: jsontest.Name("Uints/Invalid/Overflow"),
5402 inBuf: `100000000000000000000000000000`,
5403 inVal: addr(uint(1)),
5404 want: addr(uint(1)),
5405 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[uint]()),
5406 }, {
5407 name: jsontest.Name("Uints/Invalid/OverflowSyntax"),
5408 opts: []Options{StringifyNumbers(true)},
5409 inBuf: `"100000000000000000000000000000x"`,
5410 inVal: addr(uint(1)),
5411 want: addr(uint(1)),
5412 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[uint]()),
5413 }, {
5414 name: jsontest.Name("Uints/Invalid/Whitespace"),
5415 opts: []Options{StringifyNumbers(true)},
5416 inBuf: `"0 "`,
5417 inVal: addr(uint(1)),
5418 want: addr(uint(1)),
5419 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[uint]()),
5420 }, {
5421 name: jsontest.Name("Uints/Invalid/Bool"),
5422 inBuf: `true`,
5423 inVal: addr(uint(1)),
5424 want: addr(uint(1)),
5425 wantErr: EU(nil).withType('t', T[uint]()),
5426 }, {
5427 name: jsontest.Name("Uints/Invalid/String"),
5428 inBuf: `"0"`,
5429 inVal: addr(uint(1)),
5430 want: addr(uint(1)),
5431 wantErr: EU(nil).withType('"', T[uint]()),
5432 }, {
5433 name: jsontest.Name("Uints/Invalid/Object"),
5434 inBuf: `{}`,
5435 inVal: addr(uint(1)),
5436 want: addr(uint(1)),
5437 wantErr: EU(nil).withType('{', T[uint]()),
5438 }, {
5439 name: jsontest.Name("Uints/Invalid/Array"),
5440 inBuf: `[]`,
5441 inVal: addr(uint(1)),
5442 want: addr(uint(1)),
5443 wantErr: EU(nil).withType('[', T[uint]()),
5444 }, {
5445 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
5446 opts: []Options{invalidFormatOption},
5447 inBuf: `1`,
5448 inVal: addr(uint(0)),
5449 want: addr(uint(1)),
5450 }, {
5451 name: jsontest.Name("Floats/Null"),
5452 inBuf: `null`,
5453 inVal: addr(float64(64.64)),
5454 want: addr(float64(0)),
5455 }, {
5456 name: jsontest.Name("Floats/Float32/Pi"),
5457 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5458 inVal: addr(float32(32.32)),
5459 want: addr(float32(math.Pi)),
5460 }, {
5461 name: jsontest.Name("Floats/Float32/Underflow"),
5462 inBuf: `1e-1000`,
5463 inVal: addr(float32(32.32)),
5464 want: addr(float32(0)),
5465 }, {
5466 name: jsontest.Name("Floats/Float32/Overflow"),
5467 inBuf: `-1e1000`,
5468 inVal: addr(float32(32.32)),
5469 want: addr(float32(math.Inf(-1))),
5470 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float32]()),
5471 }, {
5472 name: jsontest.Name("Floats/Float64/Pi"),
5473 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5474 inVal: addr(float64(64.64)),
5475 want: addr(float64(math.Pi)),
5476 }, {
5477 name: jsontest.Name("Floats/Float64/Underflow"),
5478 inBuf: `1e-1000`,
5479 inVal: addr(float64(64.64)),
5480 want: addr(float64(0)),
5481 }, {
5482 name: jsontest.Name("Floats/Float64/Overflow"),
5483 inBuf: `-1e1000`,
5484 inVal: addr(float64(64.64)),
5485 want: addr(float64(math.Inf(-1))),
5486 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float64]()),
5487 }, {
5488 name: jsontest.Name("Floats/Any/Overflow"),
5489 inBuf: `1e1000`,
5490 inVal: new(any),
5491 want: addr(any(float64(math.Inf(+1)))),
5492 wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float64]()),
5493 }, {
5494 name: jsontest.Name("Floats/Named"),
5495 inBuf: `64.64`,
5496 inVal: addr(namedFloat64(0)),
5497 want: addr(namedFloat64(64.64)),
5498 }, {
5499 name: jsontest.Name("Floats/Stringified"),
5500 opts: []Options{StringifyNumbers(true)},
5501 inBuf: `"64.64"`,
5502 inVal: new(float64),
5503 want: addr(float64(64.64)),
5504 }, {
5505 name: jsontest.Name("Floats/Stringified/Invalid"),
5506 opts: []Options{StringifyNumbers(true)},
5507 inBuf: `64.64`,
5508 inVal: new(float64),
5509 want: new(float64),
5510 wantErr: EU(nil).withType('0', T[float64]()),
5511 }, {
5512 name: jsontest.Name("Floats/Escaped"),
5513 opts: []Options{StringifyNumbers(true)},
5514 inBuf: `"\u0036\u0034\u002e\u0036\u0034"`,
5515 inVal: new(float64),
5516 want: addr(float64(64.64)),
5517 }, {
5518 name: jsontest.Name("Floats/Invalid/NaN"),
5519 opts: []Options{StringifyNumbers(true)},
5520 inBuf: `"NaN"`,
5521 inVal: addr(float64(64.64)),
5522 want: addr(float64(64.64)),
5523 wantErr: EU(strconv.ErrSyntax).withVal(`"NaN"`).withType('"', float64Type),
5524 }, {
5525 name: jsontest.Name("Floats/Invalid/Infinity"),
5526 opts: []Options{StringifyNumbers(true)},
5527 inBuf: `"Infinity"`,
5528 inVal: addr(float64(64.64)),
5529 want: addr(float64(64.64)),
5530 wantErr: EU(strconv.ErrSyntax).withVal(`"Infinity"`).withType('"', float64Type),
5531 }, {
5532 name: jsontest.Name("Floats/Invalid/Whitespace"),
5533 opts: []Options{StringifyNumbers(true)},
5534 inBuf: `"1 "`,
5535 inVal: addr(float64(64.64)),
5536 want: addr(float64(64.64)),
5537 wantErr: EU(strconv.ErrSyntax).withVal(`"1 "`).withType('"', float64Type),
5538 }, {
5539 name: jsontest.Name("Floats/Invalid/GoSyntax"),
5540 opts: []Options{StringifyNumbers(true)},
5541 inBuf: `"1p-2"`,
5542 inVal: addr(float64(64.64)),
5543 want: addr(float64(64.64)),
5544 wantErr: EU(strconv.ErrSyntax).withVal(`"1p-2"`).withType('"', float64Type),
5545 }, {
5546 name: jsontest.Name("Floats/Invalid/Bool"),
5547 inBuf: `true`,
5548 inVal: addr(float64(64.64)),
5549 want: addr(float64(64.64)),
5550 wantErr: EU(nil).withType('t', float64Type),
5551 }, {
5552 name: jsontest.Name("Floats/Invalid/String"),
5553 inBuf: `"0"`,
5554 inVal: addr(float64(64.64)),
5555 want: addr(float64(64.64)),
5556 wantErr: EU(nil).withType('"', float64Type),
5557 }, {
5558 name: jsontest.Name("Floats/Invalid/Object"),
5559 inBuf: `{}`,
5560 inVal: addr(float64(64.64)),
5561 want: addr(float64(64.64)),
5562 wantErr: EU(nil).withType('{', float64Type),
5563 }, {
5564 name: jsontest.Name("Floats/Invalid/Array"),
5565 inBuf: `[]`,
5566 inVal: addr(float64(64.64)),
5567 want: addr(float64(64.64)),
5568 wantErr: EU(nil).withType('[', float64Type),
5569 }, {
5570 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
5571 opts: []Options{invalidFormatOption},
5572 inBuf: `1`,
5573 inVal: addr(float64(0)),
5574 want: addr(float64(1)),
5575 }, {
5576 name: jsontest.Name("Maps/Null"),
5577 inBuf: `null`,
5578 inVal: addr(map[string]string{"key": "value"}),
5579 want: new(map[string]string),
5580 }, {
5581 name: jsontest.Name("Maps/InvalidKey/Bool"),
5582 inBuf: `{"true":"false"}`,
5583 inVal: new(map[bool]bool),
5584 want: addr(make(map[bool]bool)),
5585 wantErr: EU(nil).withPos(`{`, "/true").withType('"', boolType),
5586 }, {
5587 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
5588 inBuf: `{"true":"false"}`,
5589 inVal: new(map[namedBool]bool),
5590 want: addr(make(map[namedBool]bool)),
5591 wantErr: EU(nil).withPos(`{`, "/true").withType('"', T[namedBool]()),
5592 }, {
5593 name: jsontest.Name("Maps/InvalidKey/Array"),
5594 inBuf: `{"key":"value"}`,
5595 inVal: new(map[[1]string]string),
5596 want: addr(make(map[[1]string]string)),
5597 wantErr: EU(nil).withPos(`{`, "/key").withType('"', T[[1]string]()),
5598 }, {
5599 name: jsontest.Name("Maps/InvalidKey/Channel"),
5600 inBuf: `{"key":"value"}`,
5601 inVal: new(map[chan string]string),
5602 want: addr(make(map[chan string]string)),
5603 wantErr: EU(nil).withPos(`{`, "").withType(0, T[chan string]()),
5604 }, {
5605 name: jsontest.Name("Maps/ValidKey/Int"),
5606 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5607 inVal: new(map[int]int),
5608 want: addr(map[int]int{0: 0, -1: 1, 2: 2, -3: 3}),
5609 }, {
5610 name: jsontest.Name("Maps/ValidKey/NamedInt"),
5611 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5612 inVal: new(map[namedInt64]int),
5613 want: addr(map[namedInt64]int{0: 0, -1: 1, 2: 2, -3: 3}),
5614 }, {
5615 name: jsontest.Name("Maps/ValidKey/Uint"),
5616 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5617 inVal: new(map[uint]uint),
5618 want: addr(map[uint]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5619 }, {
5620 name: jsontest.Name("Maps/ValidKey/NamedUint"),
5621 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5622 inVal: new(map[namedUint64]uint),
5623 want: addr(map[namedUint64]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5624 }, {
5625 name: jsontest.Name("Maps/ValidKey/Float"),
5626 inBuf: `{"1.234":1.234,"12.34":12.34,"123.4":123.4}`,
5627 inVal: new(map[float64]float64),
5628 want: addr(map[float64]float64{1.234: 1.234, 12.34: 12.34, 123.4: 123.4}),
5629 }, {
5630 name: jsontest.Name("Maps/DuplicateName/Int"),
5631 inBuf: `{"0":1,"-0":-1}`,
5632 inVal: new(map[int]int),
5633 want: addr(map[int]int{0: 1}),
5634 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5635 }, {
5636 name: jsontest.Name("Maps/DuplicateName/Int/MergeWithLegacySemantics"),
5637 opts: []Options{jsonflags.MergeWithLegacySemantics | 1},
5638 inBuf: `{"0":1,"-0":-1}`,
5639 inVal: new(map[int]int),
5640 want: addr(map[int]int{0: 1}),
5641 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5642 }, {
5643 name: jsontest.Name("Maps/DuplicateName/Int/AllowDuplicateNames"),
5644 opts: []Options{jsontext.AllowDuplicateNames(true)},
5645 inBuf: `{"0":1,"-0":-1}`,
5646 inVal: new(map[int]int),
5647 want: addr(map[int]int{0: -1}),
5648 }, {
5649 name: jsontest.Name("Maps/DuplicateName/Int/OverwriteExisting"),
5650 inBuf: `{"-0":-1}`,
5651 inVal: addr(map[int]int{0: 1}),
5652 want: addr(map[int]int{0: -1}),
5653 }, {
5654 name: jsontest.Name("Maps/DuplicateName/Float"),
5655 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5656 inVal: new(map[float64]string),
5657 want: addr(map[float64]string{1: "1.0"}),
5658 wantErr: newDuplicateNameError("", []byte(`"1"`), len64(`{"1.0":"1.0",`)),
5659 }, {
5660 name: jsontest.Name("Maps/DuplicateName/Float/AllowDuplicateNames"),
5661 opts: []Options{jsontext.AllowDuplicateNames(true)},
5662 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5663 inVal: new(map[float64]string),
5664 want: addr(map[float64]string{1: "1e0"}),
5665 }, {
5666 name: jsontest.Name("Maps/DuplicateName/Float/OverwriteExisting"),
5667 inBuf: `{"1.0":"1.0"}`,
5668 inVal: addr(map[float64]string{1: "1"}),
5669 want: addr(map[float64]string{1: "1.0"}),
5670 }, {
5671 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
5672 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5673 inVal: new(map[nocaseString]string),
5674 want: addr(map[nocaseString]string{"hello": "hello"}),
5675 wantErr: newDuplicateNameError("", []byte(`"HELLO"`), len64(`{"hello":"hello",`)),
5676 }, {
5677 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
5678 opts: []Options{jsontext.AllowDuplicateNames(true)},
5679 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5680 inVal: new(map[nocaseString]string),
5681 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5682 }, {
5683 name: jsontest.Name("Maps/DuplicateName/NoCaseString/OverwriteExisting"),
5684 opts: []Options{jsontext.AllowDuplicateNames(true)},
5685 inBuf: `{"HELLO":"HELLO"}`,
5686 inVal: addr(map[nocaseString]string{"hello": "hello"}),
5687 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5688 }, {
5689 name: jsontest.Name("Maps/ValidKey/Interface"),
5690 inBuf: `{"false":"false","true":"true","string":"string","0":"0","[]":"[]","{}":"{}"}`,
5691 inVal: new(map[any]string),
5692 want: addr(map[any]string{
5693 "false": "false",
5694 "true": "true",
5695 "string": "string",
5696 "0": "0",
5697 "[]": "[]",
5698 "{}": "{}",
5699 }),
5700 }, {
5701 name: jsontest.Name("Maps/InvalidValue/Channel"),
5702 inBuf: `{"key":"value"}`,
5703 inVal: new(map[string]chan string),
5704 want: addr(map[string]chan string{
5705 "key": nil,
5706 }),
5707 wantErr: EU(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
5708 }, {
5709 name: jsontest.Name("Maps/RecursiveMap"),
5710 inBuf: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
5711 inVal: new(recursiveMap),
5712 want: addr(recursiveMap{
5713 "fizz": {
5714 "foo": {},
5715 "bar": {},
5716 },
5717 "buzz": {},
5718 }),
5719 }, {
5720
5721
5722
5723 name: jsontest.Name("Maps/Merge"),
5724 opts: []Options{jsontext.AllowDuplicateNames(true)},
5725 inBuf: `{"k1":{"k2":"v2"},"k2":{"k1":"v1"},"k2":{"k2":"v2"}}`,
5726 inVal: addr(map[string]map[string]string{
5727 "k1": {"k1": "v1"},
5728 }),
5729 want: addr(map[string]map[string]string{
5730 "k1": {"k1": "v1", "k2": "v2"},
5731 "k2": {"k1": "v1", "k2": "v2"},
5732 }),
5733 }, {
5734 name: jsontest.Name("Maps/Invalid/Bool"),
5735 inBuf: `true`,
5736 inVal: addr(map[string]string{"key": "value"}),
5737 want: addr(map[string]string{"key": "value"}),
5738 wantErr: EU(nil).withType('t', T[map[string]string]()),
5739 }, {
5740 name: jsontest.Name("Maps/Invalid/String"),
5741 inBuf: `""`,
5742 inVal: addr(map[string]string{"key": "value"}),
5743 want: addr(map[string]string{"key": "value"}),
5744 wantErr: EU(nil).withType('"', T[map[string]string]()),
5745 }, {
5746 name: jsontest.Name("Maps/Invalid/Number"),
5747 inBuf: `0`,
5748 inVal: addr(map[string]string{"key": "value"}),
5749 want: addr(map[string]string{"key": "value"}),
5750 wantErr: EU(nil).withType('0', T[map[string]string]()),
5751 }, {
5752 name: jsontest.Name("Maps/Invalid/Array"),
5753 inBuf: `[]`,
5754 inVal: addr(map[string]string{"key": "value"}),
5755 want: addr(map[string]string{"key": "value"}),
5756 wantErr: EU(nil).withType('[', T[map[string]string]()),
5757 }, {
5758 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
5759 opts: []Options{invalidFormatOption},
5760 inBuf: `{"hello":"goodbye"}`,
5761 inVal: addr(map[string]string{}),
5762 want: addr(map[string]string{"hello": "goodbye"}),
5763 }, {
5764 name: jsontest.Name("Structs/Null"),
5765 inBuf: `null`,
5766 inVal: addr(structAll{String: "something"}),
5767 want: addr(structAll{}),
5768 }, {
5769 name: jsontest.Name("Structs/Empty"),
5770 inBuf: `{}`,
5771 inVal: addr(structAll{
5772 String: "hello",
5773 Map: map[string]string{},
5774 Slice: []string{},
5775 }),
5776 want: addr(structAll{
5777 String: "hello",
5778 Map: map[string]string{},
5779 Slice: []string{},
5780 }),
5781 }, {
5782 name: jsontest.Name("Structs/Normal"),
5783 inBuf: `{
5784 "Bool": true,
5785 "String": "hello",
5786 "Bytes": "AQID",
5787 "Int": -64,
5788 "Uint": 64,
5789 "Float": 3.14159,
5790 "Map": {"key": "value"},
5791 "StructScalars": {
5792 "Bool": true,
5793 "String": "hello",
5794 "Bytes": "AQID",
5795 "Int": -64,
5796 "Uint": 64,
5797 "Float": 3.14159
5798 },
5799 "StructMaps": {
5800 "MapBool": {"": true},
5801 "MapString": {"": "hello"},
5802 "MapBytes": {"": "AQID"},
5803 "MapInt": {"": -64},
5804 "MapUint": {"": 64},
5805 "MapFloat": {"": 3.14159}
5806 },
5807 "StructSlices": {
5808 "SliceBool": [true],
5809 "SliceString": ["hello"],
5810 "SliceBytes": ["AQID"],
5811 "SliceInt": [-64],
5812 "SliceUint": [64],
5813 "SliceFloat": [3.14159]
5814 },
5815 "Slice": ["fizz","buzz"],
5816 "Array": ["goodbye"],
5817 "Pointer": {},
5818 "Interface": null
5819 }`,
5820 inVal: new(structAll),
5821 want: addr(structAll{
5822 Bool: true,
5823 String: "hello",
5824 Bytes: []byte{1, 2, 3},
5825 Int: -64,
5826 Uint: +64,
5827 Float: 3.14159,
5828 Map: map[string]string{"key": "value"},
5829 StructScalars: structScalars{
5830 Bool: true,
5831 String: "hello",
5832 Bytes: []byte{1, 2, 3},
5833 Int: -64,
5834 Uint: +64,
5835 Float: 3.14159,
5836 },
5837 StructMaps: structMaps{
5838 MapBool: map[string]bool{"": true},
5839 MapString: map[string]string{"": "hello"},
5840 MapBytes: map[string][]byte{"": {1, 2, 3}},
5841 MapInt: map[string]int64{"": -64},
5842 MapUint: map[string]uint64{"": +64},
5843 MapFloat: map[string]float64{"": 3.14159},
5844 },
5845 StructSlices: structSlices{
5846 SliceBool: []bool{true},
5847 SliceString: []string{"hello"},
5848 SliceBytes: [][]byte{{1, 2, 3}},
5849 SliceInt: []int64{-64},
5850 SliceUint: []uint64{+64},
5851 SliceFloat: []float64{3.14159},
5852 },
5853 Slice: []string{"fizz", "buzz"},
5854 Array: [1]string{"goodbye"},
5855 Pointer: new(structAll),
5856 }),
5857 }, {
5858 name: jsontest.Name("Structs/Merge"),
5859 inBuf: `{
5860 "Bool": false,
5861 "String": "goodbye",
5862 "Int": -64,
5863 "Float": 3.14159,
5864 "Map": {"k2": "v2"},
5865 "StructScalars": {
5866 "Bool": true,
5867 "String": "hello",
5868 "Bytes": "AQID",
5869 "Int": -64
5870 },
5871 "StructMaps": {
5872 "MapBool": {"": true},
5873 "MapString": {"": "hello"},
5874 "MapBytes": {"": "AQID"},
5875 "MapInt": {"": -64},
5876 "MapUint": {"": 64},
5877 "MapFloat": {"": 3.14159}
5878 },
5879 "StructSlices": {
5880 "SliceString": ["hello"],
5881 "SliceBytes": ["AQID"],
5882 "SliceInt": [-64],
5883 "SliceUint": [64]
5884 },
5885 "Slice": ["fizz","buzz"],
5886 "Array": ["goodbye"],
5887 "Pointer": {},
5888 "Interface": {"k2":"v2"}
5889 }`,
5890 inVal: addr(structAll{
5891 Bool: true,
5892 String: "hello",
5893 Bytes: []byte{1, 2, 3},
5894 Uint: +64,
5895 Float: math.NaN(),
5896 Map: map[string]string{"k1": "v1"},
5897 StructScalars: structScalars{
5898 String: "hello",
5899 Bytes: make([]byte, 2, 4),
5900 Uint: +64,
5901 Float: 3.14159,
5902 },
5903 StructMaps: structMaps{
5904 MapBool: map[string]bool{"": false},
5905 MapBytes: map[string][]byte{"": {}},
5906 MapInt: map[string]int64{"": 123},
5907 MapFloat: map[string]float64{"": math.Inf(+1)},
5908 },
5909 StructSlices: structSlices{
5910 SliceBool: []bool{true},
5911 SliceBytes: [][]byte{nil, nil},
5912 SliceInt: []int64{-123},
5913 SliceUint: []uint64{+123},
5914 SliceFloat: []float64{3.14159},
5915 },
5916 Slice: []string{"buzz", "fizz", "gizz"},
5917 Array: [1]string{"hello"},
5918 Pointer: new(structAll),
5919 Interface: map[string]string{"k1": "v1"},
5920 }),
5921 want: addr(structAll{
5922 Bool: false,
5923 String: "goodbye",
5924 Bytes: []byte{1, 2, 3},
5925 Int: -64,
5926 Uint: +64,
5927 Float: 3.14159,
5928 Map: map[string]string{"k1": "v1", "k2": "v2"},
5929 StructScalars: structScalars{
5930 Bool: true,
5931 String: "hello",
5932 Bytes: []byte{1, 2, 3},
5933 Int: -64,
5934 Uint: +64,
5935 Float: 3.14159,
5936 },
5937 StructMaps: structMaps{
5938 MapBool: map[string]bool{"": true},
5939 MapString: map[string]string{"": "hello"},
5940 MapBytes: map[string][]byte{"": {1, 2, 3}},
5941 MapInt: map[string]int64{"": -64},
5942 MapUint: map[string]uint64{"": +64},
5943 MapFloat: map[string]float64{"": 3.14159},
5944 },
5945 StructSlices: structSlices{
5946 SliceBool: []bool{true},
5947 SliceString: []string{"hello"},
5948 SliceBytes: [][]byte{{1, 2, 3}},
5949 SliceInt: []int64{-64},
5950 SliceUint: []uint64{+64},
5951 SliceFloat: []float64{3.14159},
5952 },
5953 Slice: []string{"fizz", "buzz"},
5954 Array: [1]string{"goodbye"},
5955 Pointer: new(structAll),
5956 Interface: map[string]string{"k1": "v1", "k2": "v2"},
5957 }),
5958 }, {
5959 name: jsontest.Name("Structs/Stringified/Normal"),
5960 inBuf: `{
5961 "Bool": true,
5962 "String": "hello",
5963 "Bytes": "AQID",
5964 "Int": "-64",
5965 "Uint": "64",
5966 "Float": "3.14159",
5967 "Map": {"key": "value"},
5968 "StructScalars": {
5969 "Bool": true,
5970 "String": "hello",
5971 "Bytes": "AQID",
5972 "Int": "-64",
5973 "Uint": "64",
5974 "Float": "3.14159"
5975 },
5976 "StructMaps": {
5977 "MapBool": {"": true},
5978 "MapString": {"": "hello"},
5979 "MapBytes": {"": "AQID"},
5980 "MapInt": {"": "-64"},
5981 "MapUint": {"": "64"},
5982 "MapFloat": {"": "3.14159"}
5983 },
5984 "StructSlices": {
5985 "SliceBool": [true],
5986 "SliceString": ["hello"],
5987 "SliceBytes": ["AQID"],
5988 "SliceInt": ["-64"],
5989 "SliceUint": ["64"],
5990 "SliceFloat": ["3.14159"]
5991 },
5992 "Slice": ["fizz","buzz"],
5993 "Array": ["goodbye"],
5994 "Pointer": {},
5995 "Interface": null
5996 }`,
5997 inVal: new(structStringifiedAll),
5998 want: addr(structStringifiedAll{
5999 Bool: true,
6000 String: "hello",
6001 Bytes: []byte{1, 2, 3},
6002 Int: -64,
6003 Uint: +64,
6004 Float: 3.14159,
6005 Map: map[string]string{"key": "value"},
6006 StructScalars: structScalars{
6007 Bool: true,
6008 String: "hello",
6009 Bytes: []byte{1, 2, 3},
6010 Int: -64,
6011 Uint: +64,
6012 Float: 3.14159,
6013 },
6014 StructMaps: structMaps{
6015 MapBool: map[string]bool{"": true},
6016 MapString: map[string]string{"": "hello"},
6017 MapBytes: map[string][]byte{"": {1, 2, 3}},
6018 MapInt: map[string]int64{"": -64},
6019 MapUint: map[string]uint64{"": +64},
6020 MapFloat: map[string]float64{"": 3.14159},
6021 },
6022 StructSlices: structSlices{
6023 SliceBool: []bool{true},
6024 SliceString: []string{"hello"},
6025 SliceBytes: [][]byte{{1, 2, 3}},
6026 SliceInt: []int64{-64},
6027 SliceUint: []uint64{+64},
6028 SliceFloat: []float64{3.14159},
6029 },
6030 Slice: []string{"fizz", "buzz"},
6031 Array: [1]string{"goodbye"},
6032 Pointer: new(structStringifiedAll),
6033 }),
6034 }, {
6035 name: jsontest.Name("Structs/Stringified/String"),
6036 inBuf: `{
6037 "Bool": true,
6038 "String": "hello",
6039 "Bytes": "AQID",
6040 "Int": "-64",
6041 "Uint": "64",
6042 "Float": "3.14159",
6043 "Map": {"key": "value"},
6044 "StructScalars": {
6045 "Bool": true,
6046 "String": "hello",
6047 "Bytes": "AQID",
6048 "Int": "-64",
6049 "Uint": "64",
6050 "Float": "3.14159"
6051 },
6052 "StructMaps": {
6053 "MapBool": {"": true},
6054 "MapString": {"": "hello"},
6055 "MapBytes": {"": "AQID"},
6056 "MapInt": {"": "-64"},
6057 "MapUint": {"": "64"},
6058 "MapFloat": {"": "3.14159"}
6059 },
6060 "StructSlices": {
6061 "SliceBool": [true],
6062 "SliceString": ["hello"],
6063 "SliceBytes": ["AQID"],
6064 "SliceInt": ["-64"],
6065 "SliceUint": ["64"],
6066 "SliceFloat": ["3.14159"]
6067 },
6068 "Slice": ["fizz","buzz"],
6069 "Array": ["goodbye"],
6070 "Pointer": {},
6071 "Interface": null
6072 }`,
6073 inVal: new(structStringifiedAll),
6074 want: addr(structStringifiedAll{
6075 Bool: true,
6076 String: "hello",
6077 Bytes: []byte{1, 2, 3},
6078 Int: -64,
6079 Uint: +64,
6080 Float: 3.14159,
6081 Map: map[string]string{"key": "value"},
6082 StructScalars: structScalars{
6083 Bool: true,
6084 String: "hello",
6085 Bytes: []byte{1, 2, 3},
6086 Int: -64,
6087 Uint: +64,
6088 Float: 3.14159,
6089 },
6090 StructMaps: structMaps{
6091 MapBool: map[string]bool{"": true},
6092 MapString: map[string]string{"": "hello"},
6093 MapBytes: map[string][]byte{"": {1, 2, 3}},
6094 MapInt: map[string]int64{"": -64},
6095 MapUint: map[string]uint64{"": +64},
6096 MapFloat: map[string]float64{"": 3.14159},
6097 },
6098 StructSlices: structSlices{
6099 SliceBool: []bool{true},
6100 SliceString: []string{"hello"},
6101 SliceBytes: [][]byte{{1, 2, 3}},
6102 SliceInt: []int64{-64},
6103 SliceUint: []uint64{+64},
6104 SliceFloat: []float64{3.14159},
6105 },
6106 Slice: []string{"fizz", "buzz"},
6107 Array: [1]string{"goodbye"},
6108 Pointer: new(structStringifiedAll),
6109 }),
6110 }, {
6111 name: jsontest.Name("Structs/Stringified/InvalidEmpty"),
6112 inBuf: `{"Int":""}`,
6113 inVal: new(structStringifiedAll),
6114 want: new(structStringifiedAll),
6115 wantErr: EU(strconv.ErrSyntax).withVal(`""`).withPos(`{"Int":`, "/Int").withType('"', T[int64]()),
6116 }, {
6117 name: jsontest.Name("Structs/LegacyStringified"),
6118 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6119 inBuf: `{
6120 "Bool": "true",
6121 "String": "\"hello\"",
6122 "Bytes": "AQID",
6123 "Int": "-64",
6124 "Uint": "64",
6125 "Float": "3.14159",
6126 "Map": {"key": "value"},
6127 "StructScalars": {
6128 "Bool": true,
6129 "String": "hello",
6130 "Bytes": "AQID",
6131 "Int": -64,
6132 "Uint": 64,
6133 "Float": 3.14159
6134 },
6135 "StructMaps": {
6136 "MapBool": {"": true},
6137 "MapString": {"": "hello"},
6138 "MapBytes": {"": "AQID"},
6139 "MapInt": {"": -64},
6140 "MapUint": {"": 64},
6141 "MapFloat": {"": 3.14159}
6142 },
6143 "StructSlices": {
6144 "SliceBool": [true],
6145 "SliceString": ["hello"],
6146 "SliceBytes": ["AQID"],
6147 "SliceInt": [-64],
6148 "SliceUint": [64],
6149 "SliceFloat": [3.14159]
6150 },
6151 "Slice": ["fizz", "buzz"],
6152 "Array": ["goodbye"]
6153 }`,
6154 inVal: new(structStringifiedAll),
6155 want: addr(structStringifiedAll{
6156 Bool: true,
6157 String: "hello",
6158 Bytes: []byte{1, 2, 3},
6159 Int: -64,
6160 Uint: +64,
6161 Float: 3.14159,
6162 Map: map[string]string{"key": "value"},
6163 StructScalars: structScalars{
6164 Bool: true,
6165 String: "hello",
6166 Bytes: []byte{1, 2, 3},
6167 Int: -64,
6168 Uint: +64,
6169 Float: 3.14159,
6170 },
6171 StructMaps: structMaps{
6172 MapBool: map[string]bool{"": true},
6173 MapString: map[string]string{"": "hello"},
6174 MapBytes: map[string][]byte{"": {1, 2, 3}},
6175 MapInt: map[string]int64{"": -64},
6176 MapUint: map[string]uint64{"": +64},
6177 MapFloat: map[string]float64{"": 3.14159},
6178 },
6179 StructSlices: structSlices{
6180 SliceBool: []bool{true},
6181 SliceString: []string{"hello"},
6182 SliceBytes: [][]byte{{1, 2, 3}},
6183 SliceInt: []int64{-64},
6184 SliceUint: []uint64{+64},
6185 SliceFloat: []float64{3.14159},
6186 },
6187 Slice: []string{"fizz", "buzz"},
6188 Array: [1]string{"goodbye"},
6189 }),
6190 }, {
6191 name: jsontest.Name("Structs/LegacyStringified/InvalidBool"),
6192 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6193 inBuf: `{"Bool": true}`,
6194 inVal: new(structStringifiedAll),
6195 wantErr: EU(nil).withPos(`{"Bool": `, "/Bool").withType('t', T[bool]()),
6196 }, {
6197 name: jsontest.Name("Structs/LegacyStringified/InvalidString"),
6198 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6199 inBuf: `{"String": "string"}`,
6200 inVal: new(structStringifiedAll),
6201 wantErr: EU(newInvalidCharacterError("s", "at start of string (expecting '\"')", 0, "")).
6202 withPos(`{"String": `, "/String").withType('"', T[string]()),
6203 }, {
6204 name: jsontest.Name("Structs/Format/Bytes"),
6205 inBuf: `{
6206 "Base16": "0123456789abcdef",
6207 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
6208 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
6209 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
6210 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
6211 "Array": [1, 2, 3, 4]
6212 }`,
6213 inVal: new(structFormatBytes),
6214 want: addr(structFormatBytes{
6215 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
6216 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6217 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6218 Base64: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"),
6219 Base64URL: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"),
6220 Array: []byte{1, 2, 3, 4},
6221 }),
6222 skip: !internal.ExpJSONFormat,
6223 }, {
6224 name: jsontest.Name("Structs/Format/ArrayBytes"),
6225 inBuf: `{
6226 "Base16": "01020304",
6227 "Base32": "AEBAGBA=",
6228 "Base32Hex": "0410610=",
6229 "Base64": "AQIDBA==",
6230 "Base64URL": "AQIDBA==",
6231 "Array": [1, 2, 3, 4],
6232 "Default": "AQIDBA=="
6233 }`,
6234 inVal: new(structFormatArrayBytes),
6235 want: addr(structFormatArrayBytes{
6236 Base16: [4]byte{1, 2, 3, 4},
6237 Base32: [4]byte{1, 2, 3, 4},
6238 Base32Hex: [4]byte{1, 2, 3, 4},
6239 Base64: [4]byte{1, 2, 3, 4},
6240 Base64URL: [4]byte{1, 2, 3, 4},
6241 Array: [4]byte{1, 2, 3, 4},
6242 Default: [4]byte{1, 2, 3, 4},
6243 }),
6244 skip: !internal.ExpJSONFormat,
6245 }, {
6246 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
6247 opts: []Options{jsonflags.FormatBytesWithLegacySemantics | 1},
6248 inBuf: `{
6249 "Base16": "01020304",
6250 "Base32": "AEBAGBA=",
6251 "Base32Hex": "0410610=",
6252 "Base64": "AQIDBA==",
6253 "Base64URL": "AQIDBA==",
6254 "Array": [1, 2, 3, 4],
6255 "Default": [1, 2, 3, 4]
6256 }`,
6257 inVal: new(structFormatArrayBytes),
6258 want: addr(structFormatArrayBytes{
6259 Base16: [4]byte{1, 2, 3, 4},
6260 Base32: [4]byte{1, 2, 3, 4},
6261 Base32Hex: [4]byte{1, 2, 3, 4},
6262 Base64: [4]byte{1, 2, 3, 4},
6263 Base64URL: [4]byte{1, 2, 3, 4},
6264 Array: [4]byte{1, 2, 3, 4},
6265 Default: [4]byte{1, 2, 3, 4},
6266 }),
6267 skip: !internal.ExpJSONFormat,
6268 }, {
6269 name: jsontest.Name("Structs/Format/Bytes/Array"),
6270 opts: []Options{
6271 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *byte) error {
6272 if string(b) == "true" {
6273 *v = 1
6274 } else {
6275 *v = 0
6276 }
6277 return nil
6278 })),
6279 },
6280 inBuf: `{"Array":[false,true,false,true,false,true]}`,
6281 inVal: new(struct {
6282 Array []byte `json:",format:array"`
6283 }),
6284 want: addr(struct {
6285 Array []byte `json:",format:array"`
6286 }{
6287 Array: []byte{0, 1, 0, 1, 0, 1},
6288 }),
6289 skip: !internal.ExpJSONFormat,
6290 }, {
6291 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/WrongKind"),
6292 inBuf: `{"Base16": [1,2,3,4]}`,
6293 inVal: new(structFormatBytes),
6294 wantErr: EU(nil).withPos(`{"Base16": `, "/Base16").withType('[', T[[]byte]()),
6295 skip: !internal.ExpJSONFormat,
6296 }, {
6297 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/AllPadding"),
6298 inBuf: `{"Base16": "===="}`,
6299 inVal: new(structFormatBytes),
6300 wantErr: EU(func() error {
6301 _, err := hex.Decode(make([]byte, 2), []byte("====="))
6302 return err
6303 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6304 skip: !internal.ExpJSONFormat,
6305 }, {
6306 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/EvenPadding"),
6307 inBuf: `{"Base16": "0123456789abcdef="}`,
6308 inVal: new(structFormatBytes),
6309 wantErr: EU(func() error {
6310 _, err := hex.Decode(make([]byte, 8), []byte("0123456789abcdef="))
6311 return err
6312 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6313 skip: !internal.ExpJSONFormat,
6314 }, {
6315 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/OddPadding"),
6316 inBuf: `{"Base16": "0123456789abcdef0="}`,
6317 inVal: new(structFormatBytes),
6318 wantErr: EU(func() error {
6319 _, err := hex.Decode(make([]byte, 9), []byte("0123456789abcdef0="))
6320 return err
6321 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6322 skip: !internal.ExpJSONFormat,
6323 }, {
6324 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/LineFeed"),
6325 inBuf: `{"Base16": "aa\naa"}`,
6326 inVal: new(structFormatBytes),
6327 wantErr: EU(func() error {
6328 _, err := hex.Decode(make([]byte, 9), []byte("aa\naa"))
6329 return err
6330 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6331 skip: !internal.ExpJSONFormat,
6332 }, {
6333 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/CarriageReturn"),
6334 inBuf: `{"Base16": "aa\raa"}`,
6335 inVal: new(structFormatBytes),
6336 wantErr: EU(func() error {
6337 _, err := hex.Decode(make([]byte, 9), []byte("aa\raa"))
6338 return err
6339 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6340 skip: !internal.ExpJSONFormat,
6341 }, {
6342 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/Space"),
6343 inBuf: `{"Base16": "aa aa"}`,
6344 inVal: new(structFormatBytes),
6345 wantErr: EU(func() error {
6346 _, err := hex.Decode(make([]byte, 9), []byte("aa aa"))
6347 return err
6348 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6349 skip: !internal.ExpJSONFormat,
6350 }, {
6351 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Padding"),
6352 inBuf: `[
6353 {"Base32": "NA======"},
6354 {"Base32": "NBSQ===="},
6355 {"Base32": "NBSWY==="},
6356 {"Base32": "NBSWY3A="},
6357 {"Base32": "NBSWY3DP"}
6358 ]`,
6359 inVal: new([]structFormatBytes),
6360 want: addr([]structFormatBytes{
6361 {Base32: []byte("h")},
6362 {Base32: []byte("he")},
6363 {Base32: []byte("hel")},
6364 {Base32: []byte("hell")},
6365 {Base32: []byte("hello")},
6366 }),
6367 skip: !internal.ExpJSONFormat,
6368 }, {
6369 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Invalid/NoPadding"),
6370 inBuf: `[
6371 {"Base32": "NA"},
6372 {"Base32": "NBSQ"},
6373 {"Base32": "NBSWY"},
6374 {"Base32": "NBSWY3A"},
6375 {"Base32": "NBSWY3DP"}
6376 ]`,
6377 inVal: new([]structFormatBytes),
6378 wantErr: EU(func() error {
6379 _, err := base32.StdEncoding.Decode(make([]byte, 1), []byte("NA"))
6380 return err
6381 }()).withPos(`[`+"\n\t\t\t\t"+`{"Base32": `, "/0/Base32").withType('"', T[[]byte]()),
6382 skip: !internal.ExpJSONFormat,
6383 }, {
6384 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/WrongAlphabet"),
6385 inBuf: `{"Base32": "0123456789ABCDEFGHIJKLMNOPQRSTUV"}`,
6386 inVal: new(structFormatBytes),
6387 wantErr: EU(func() error {
6388 _, err := base32.StdEncoding.Decode(make([]byte, 20), []byte("0123456789ABCDEFGHIJKLMNOPQRSTUV"))
6389 return err
6390 }()).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6391 skip: !internal.ExpJSONFormat,
6392 }, {
6393 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32Hex/WrongAlphabet"),
6394 inBuf: `{"Base32Hex": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"}`,
6395 inVal: new(structFormatBytes),
6396 wantErr: EU(func() error {
6397 _, err := base32.HexEncoding.Decode(make([]byte, 20), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"))
6398 return err
6399 }()).withPos(`{"Base32Hex": `, "/Base32Hex").withType('"', T[[]byte]()),
6400 skip: !internal.ExpJSONFormat,
6401 }, {
6402 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/LineFeed"),
6403 inBuf: `{"Base32": "AAAA\nAAAA"}`,
6404 inVal: new(structFormatBytes),
6405 wantErr: EU(errors.New("illegal character '\\n' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6406 skip: !internal.ExpJSONFormat,
6407 }, {
6408 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/CarriageReturn"),
6409 inBuf: `{"Base32": "AAAA\rAAAA"}`,
6410 inVal: new(structFormatBytes),
6411 wantErr: EU(errors.New("illegal character '\\r' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6412 skip: !internal.ExpJSONFormat,
6413 }, {
6414 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/Space"),
6415 inBuf: `{"Base32": "AAAA AAAA"}`,
6416 inVal: new(structFormatBytes),
6417 wantErr: EU(base32.CorruptInputError(4)).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6418 skip: !internal.ExpJSONFormat,
6419 }, {
6420 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/WrongAlphabet"),
6421 inBuf: `{"Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"}`,
6422 inVal: new(structFormatBytes),
6423 wantErr: EU(func() error {
6424 _, err := base64.StdEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"))
6425 return err
6426 }()).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6427 skip: !internal.ExpJSONFormat,
6428 }, {
6429 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64URL/WrongAlphabet"),
6430 inBuf: `{"Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}`,
6431 inVal: new(structFormatBytes),
6432 wantErr: EU(func() error {
6433 _, err := base64.URLEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
6434 return err
6435 }()).withPos(`{"Base64URL": `, "/Base64URL").withType('"', T[[]byte]()),
6436 skip: !internal.ExpJSONFormat,
6437 }, {
6438 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/LineFeed"),
6439 inBuf: `{"Base64": "aa=\n="}`,
6440 inVal: new(structFormatBytes),
6441 wantErr: EU(errors.New("illegal character '\\n' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6442 skip: !internal.ExpJSONFormat,
6443 }, {
6444 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/CarriageReturn"),
6445 inBuf: `{"Base64": "aa=\r="}`,
6446 inVal: new(structFormatBytes),
6447 wantErr: EU(errors.New("illegal character '\\r' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6448 skip: !internal.ExpJSONFormat,
6449 }, {
6450 name: jsontest.Name("Structs/Format/Bytes/Base64/NonAlphabet/Ignored"),
6451 opts: []Options{jsonflags.ParseBytesWithLooseRFC4648 | 1},
6452 inBuf: `{"Base64": "aa=\r\n="}`,
6453 inVal: new(structFormatBytes),
6454 want: &structFormatBytes{Base64: []byte{105}},
6455 skip: !internal.ExpJSONFormat,
6456 }, {
6457 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/Space"),
6458 inBuf: `{"Base64": "aa= ="}`,
6459 inVal: new(structFormatBytes),
6460 wantErr: EU(base64.CorruptInputError(2)).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6461 skip: !internal.ExpJSONFormat,
6462 }, {
6463 name: jsontest.Name("Structs/Format/Floats"),
6464 inBuf: `[
6465 {"NonFinite": 3.141592653589793, "PointerNonFinite": 3.141592653589793},
6466 {"NonFinite": "-Infinity", "PointerNonFinite": "-Infinity"},
6467 {"NonFinite": "Infinity", "PointerNonFinite": "Infinity"}
6468 ]`,
6469 inVal: new([]structFormatFloats),
6470 want: addr([]structFormatFloats{
6471 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
6472 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
6473 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
6474 }),
6475 skip: !internal.ExpJSONFormat,
6476 }, {
6477 name: jsontest.Name("Structs/Format/Floats/NaN"),
6478 inBuf: `{"NonFinite": "NaN"}`,
6479 inVal: new(structFormatFloats),
6480
6481 skip: !internal.ExpJSONFormat,
6482 }, {
6483 name: jsontest.Name("Structs/Format/Floats/Invalid/NaN"),
6484 inBuf: `{"NonFinite": "nan"}`,
6485 inVal: new(structFormatFloats),
6486 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6487 skip: !internal.ExpJSONFormat,
6488 }, {
6489 name: jsontest.Name("Structs/Format/Floats/Invalid/PositiveInfinity"),
6490 inBuf: `{"NonFinite": "+Infinity"}`,
6491 inVal: new(structFormatFloats),
6492 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6493 skip: !internal.ExpJSONFormat,
6494 }, {
6495 name: jsontest.Name("Structs/Format/Floats/Invalid/NegativeInfinitySpace"),
6496 inBuf: `{"NonFinite": "-Infinity "}`,
6497 inVal: new(structFormatFloats),
6498 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6499 skip: !internal.ExpJSONFormat,
6500 }, {
6501 name: jsontest.Name("Structs/Format/Maps"),
6502 inBuf: `[
6503 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6504 {"EmitNull": {}, "PointerEmitNull": {}, "EmitEmpty": {}, "PointerEmitEmpty": {}, "EmitDefault": {}, "PointerEmitDefault": {}},
6505 {"EmitNull": {"k": "v"}, "PointerEmitNull": {"k": "v"}, "EmitEmpty": {"k": "v"}, "PointerEmitEmpty": {"k": "v"}, "EmitDefault": {"k": "v"}, "PointerEmitDefault": {"k": "v"}}
6506 ]`,
6507 inVal: new([]structFormatMaps),
6508 want: addr([]structFormatMaps{{
6509 EmitNull: map[string]string(nil), PointerEmitNull: (*map[string]string)(nil),
6510 EmitEmpty: map[string]string(nil), PointerEmitEmpty: (*map[string]string)(nil),
6511 EmitDefault: map[string]string(nil), PointerEmitDefault: (*map[string]string)(nil),
6512 }, {
6513 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
6514 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
6515 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
6516 }, {
6517 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
6518 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
6519 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
6520 }}),
6521 skip: !internal.ExpJSONFormat,
6522 }, {
6523 name: jsontest.Name("Structs/Format/Slices"),
6524 inBuf: `[
6525 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6526 {"EmitNull": [], "PointerEmitNull": [], "EmitEmpty": [], "PointerEmitEmpty": [], "EmitDefault": [], "PointerEmitDefault": []},
6527 {"EmitNull": ["v"], "PointerEmitNull": ["v"], "EmitEmpty": ["v"], "PointerEmitEmpty": ["v"], "EmitDefault": ["v"], "PointerEmitDefault": ["v"]}
6528 ]`,
6529 inVal: new([]structFormatSlices),
6530 want: addr([]structFormatSlices{{
6531 EmitNull: []string(nil), PointerEmitNull: (*[]string)(nil),
6532 EmitEmpty: []string(nil), PointerEmitEmpty: (*[]string)(nil),
6533 EmitDefault: []string(nil), PointerEmitDefault: (*[]string)(nil),
6534 }, {
6535 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
6536 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
6537 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
6538 }, {
6539 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
6540 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
6541 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
6542 }}),
6543 skip: !internal.ExpJSONFormat,
6544 }, {
6545 name: jsontest.Name("Structs/Format/Invalid/Bool"),
6546 inBuf: `{"Bool":true}`,
6547 inVal: new(structFormatInvalid),
6548 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, T[bool]()),
6549 skip: !internal.ExpJSONFormat,
6550 }, {
6551 name: jsontest.Name("Structs/Format/Invalid/String"),
6552 inBuf: `{"String": "string"}`,
6553 inVal: new(structFormatInvalid),
6554 wantErr: EU(errInvalidFormatFlag).withPos(`{"String": `, "/String").withType(0, T[string]()),
6555 skip: !internal.ExpJSONFormat,
6556 }, {
6557 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
6558 inBuf: `{"Bytes": "bytes"}`,
6559 inVal: new(structFormatInvalid),
6560 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bytes": `, "/Bytes").withType(0, T[[]byte]()),
6561 skip: !internal.ExpJSONFormat,
6562 }, {
6563 name: jsontest.Name("Structs/Format/Invalid/Int"),
6564 inBuf: `{"Int": 1}`,
6565 inVal: new(structFormatInvalid),
6566 wantErr: EU(errInvalidFormatFlag).withPos(`{"Int": `, "/Int").withType(0, T[int64]()),
6567 skip: !internal.ExpJSONFormat,
6568 }, {
6569 name: jsontest.Name("Structs/Format/Invalid/Uint"),
6570 inBuf: `{"Uint": 1}`,
6571 inVal: new(structFormatInvalid),
6572 wantErr: EU(errInvalidFormatFlag).withPos(`{"Uint": `, "/Uint").withType(0, T[uint64]()),
6573 skip: !internal.ExpJSONFormat,
6574 }, {
6575 name: jsontest.Name("Structs/Format/Invalid/Float"),
6576 inBuf: `{"Float" : 1}`,
6577 inVal: new(structFormatInvalid),
6578 wantErr: EU(errInvalidFormatFlag).withPos(`{"Float" : `, "/Float").withType(0, T[float64]()),
6579 skip: !internal.ExpJSONFormat,
6580 }, {
6581 name: jsontest.Name("Structs/Format/Invalid/Map"),
6582 inBuf: `{"Map":{}}`,
6583 inVal: new(structFormatInvalid),
6584 wantErr: EU(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
6585 skip: !internal.ExpJSONFormat,
6586 }, {
6587 name: jsontest.Name("Structs/Format/Invalid/Struct"),
6588 inBuf: `{"Struct": {}}`,
6589 inVal: new(structFormatInvalid),
6590 wantErr: EU(errInvalidFormatFlag).withPos(`{"Struct": `, "/Struct").withType(0, T[structAll]()),
6591 skip: !internal.ExpJSONFormat,
6592 }, {
6593 name: jsontest.Name("Structs/Format/Invalid/Slice"),
6594 inBuf: `{"Slice": {}}`,
6595 inVal: new(structFormatInvalid),
6596 wantErr: EU(errInvalidFormatFlag).withPos(`{"Slice": `, "/Slice").withType(0, T[[]string]()),
6597 skip: !internal.ExpJSONFormat,
6598 }, {
6599 name: jsontest.Name("Structs/Format/Invalid/Array"),
6600 inBuf: `{"Array": []}`,
6601 inVal: new(structFormatInvalid),
6602 wantErr: EU(errInvalidFormatFlag).withPos(`{"Array": `, "/Array").withType(0, T[[1]string]()),
6603 skip: !internal.ExpJSONFormat,
6604 }, {
6605 name: jsontest.Name("Structs/Format/Invalid/Interface"),
6606 inBuf: `{"Interface": "anything"}`,
6607 inVal: new(structFormatInvalid),
6608 wantErr: EU(errInvalidFormatFlag).withPos(`{"Interface": `, "/Interface").withType(0, T[any]()),
6609 skip: !internal.ExpJSONFormat,
6610 }, {
6611 name: jsontest.Name("Structs/Inline/Zero"),
6612 inBuf: `{"D":""}`,
6613 inVal: new(structInlined),
6614 want: new(structInlined),
6615 }, {
6616 name: jsontest.Name("Structs/Inline/Alloc"),
6617 inBuf: `{"E":"","F":"","G":"","A":"","B":"","D":""}`,
6618 inVal: new(structInlined),
6619 want: addr(structInlined{
6620 X: structInlinedL1{
6621 X: &structInlinedL2{},
6622 StructEmbed1: StructEmbed1{},
6623 },
6624 StructEmbed2: &StructEmbed2{},
6625 }),
6626 }, {
6627 name: jsontest.Name("Structs/Inline/NonZero"),
6628 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6629 inVal: new(structInlined),
6630 want: addr(structInlined{
6631 X: structInlinedL1{
6632 X: &structInlinedL2{A: "A1", B: "B1" },
6633 StructEmbed1: StructEmbed1{ D: "D2" },
6634 },
6635 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6636 }),
6637 }, {
6638 name: jsontest.Name("Structs/Inline/Merge"),
6639 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6640 inVal: addr(structInlined{
6641 X: structInlinedL1{
6642 X: &structInlinedL2{B: "##", C: "C1"},
6643 StructEmbed1: StructEmbed1{C: "C2", E: "E2"},
6644 },
6645 StructEmbed2: &StructEmbed2{E: "##", G: "G3"},
6646 }),
6647 want: addr(structInlined{
6648 X: structInlinedL1{
6649 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
6650 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
6651 },
6652 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6653 }),
6654 }, {
6655 name: jsontest.Name("Structs/InlinedFallback/TextValue/Noop"),
6656 inBuf: `{"A":1,"B":2}`,
6657 inVal: new(structInlineTextValue),
6658 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(nil), B: 2}),
6659 }, {
6660 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Nil"),
6661 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6662 inVal: new(structInlineTextValue),
6663 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6664 }, {
6665 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Empty"),
6666 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6667 inVal: addr(structInlineTextValue{X: jsontext.Value{}}),
6668 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6669 }, {
6670 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Whitespace"),
6671 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6672 inVal: addr(structInlineTextValue{X: jsontext.Value("\n\r\t ")}),
6673 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("")}),
6674 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6675 }, {
6676 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Null"),
6677 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6678 inVal: addr(structInlineTextValue{X: jsontext.Value("null")}),
6679 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("null")}),
6680 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6681 }, {
6682 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/ObjectN0"),
6683 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6684 inVal: addr(structInlineTextValue{X: jsontext.Value(` { } `)}),
6685 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` {"fizz":"buzz"}`), B: 2}),
6686 }, {
6687 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN2/ObjectN1"),
6688 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6689 inVal: addr(structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)}),
6690 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` { "fizz" : "buzz","fizz":"buzz","foo":[ 1 , 2 , 3 ]}`), B: 2}),
6691 }, {
6692 name: jsontest.Name("Structs/InlinedFallback/TextValue/Merge/EndObject"),
6693 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6694 inVal: addr(structInlineTextValue{X: jsontext.Value(` } `)}),
6695
6696
6697 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`,"fizz":"buzz"}`), B: 2}),
6698 }, {
6699 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeInvalidValue"),
6700 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6701 inVal: new(structInlineTextValue),
6702 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":`)}),
6703 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6704 }, {
6705 name: jsontest.Name("Structs/InlinedFallback/TextValue/CaseSensitive"),
6706 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6707 inVal: new(structInlineTextValue),
6708 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","a":3}`), B: 2}),
6709 }, {
6710 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
6711 opts: []Options{jsontext.AllowDuplicateNames(false)},
6712 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6713 inVal: new(structInlineTextValue),
6714 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6715 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6716 }, {
6717 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
6718 opts: []Options{jsontext.AllowDuplicateNames(true)},
6719 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6720 inVal: new(structInlineTextValue),
6721 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`), B: 2}),
6722 }, {
6723 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Noop"),
6724 inBuf: `{}`,
6725 inVal: new(structInlinePointerInlineTextValue),
6726 want: new(structInlinePointerInlineTextValue),
6727 }, {
6728 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Alloc"),
6729 inBuf: `{"A":1,"fizz":"buzz"}`,
6730 inVal: new(structInlinePointerInlineTextValue),
6731 want: addr(structInlinePointerInlineTextValue{
6732 X: &struct {
6733 A int
6734 X jsontext.Value `json:",inline"`
6735 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6736 }),
6737 }, {
6738 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Merge"),
6739 inBuf: `{"fizz":"buzz"}`,
6740 inVal: addr(structInlinePointerInlineTextValue{
6741 X: &struct {
6742 A int
6743 X jsontext.Value `json:",inline"`
6744 }{A: 1},
6745 }),
6746 want: addr(structInlinePointerInlineTextValue{
6747 X: &struct {
6748 A int
6749 X jsontext.Value `json:",inline"`
6750 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6751 }),
6752 }, {
6753 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Noop"),
6754 inBuf: `{"A":1,"B":2}`,
6755 inVal: new(structInlinePointerTextValue),
6756 want: addr(structInlinePointerTextValue{A: 1, X: nil, B: 2}),
6757 }, {
6758 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Alloc"),
6759 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6760 inVal: new(structInlinePointerTextValue),
6761 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz"}`)), B: 2}),
6762 }, {
6763 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Merge"),
6764 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6765 inVal: addr(structInlinePointerTextValue{X: addr(jsontext.Value(`{"fizz":"buzz"}`))}),
6766 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`)), B: 2}),
6767 }, {
6768 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
6769 inBuf: `{"fizz":"buzz"}`,
6770 inVal: new(structInlineInlinePointerTextValue),
6771 want: addr(structInlineInlinePointerTextValue{
6772 X: struct {
6773 X *jsontext.Value `json:",inline"`
6774 }{X: addr(jsontext.Value(`{"fizz":"buzz"}`))},
6775 }),
6776 }, {
6777 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Noop"),
6778 inBuf: `{"A":1,"B":2}`,
6779 inVal: new(structInlineMapStringAny),
6780 want: addr(structInlineMapStringAny{A: 1, X: nil, B: 2}),
6781 }, {
6782 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Nil"),
6783 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6784 inVal: new(structInlineMapStringAny),
6785 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6786 }, {
6787 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Empty"),
6788 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6789 inVal: addr(structInlineMapStringAny{X: jsonObject{}}),
6790 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6791 }, {
6792 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/ObjectN1"),
6793 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6794 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": jsonObject{
6795 "alpha": "bravo",
6796 "charlie": "delta",
6797 }}}),
6798 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{
6799 "alpha": "bravo",
6800 "charlie": "DELTA",
6801 "echo": "foxtrot",
6802 }}, B: 2}),
6803 }, {
6804 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN2/ObjectN1"),
6805 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6806 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": "wuzz"}}),
6807 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6808 }, {
6809 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue"),
6810 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6811 inVal: new(structInlineMapStringAny),
6812 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": nil}}),
6813 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6814 }, {
6815 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue/Existing"),
6816 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6817 inVal: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6818 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6819 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6820 }, {
6821 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/CaseSensitive"),
6822 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6823 inVal: new(structInlineMapStringAny),
6824 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "a": 3.0}, B: 2}),
6825 }, {
6826 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectDuplicateNames"),
6827 opts: []Options{jsontext.AllowDuplicateNames(false)},
6828 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6829 inVal: new(structInlineMapStringAny),
6830 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6831 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6832 }, {
6833 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowDuplicateNames"),
6834 opts: []Options{jsontext.AllowDuplicateNames(true)},
6835 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
6836 inVal: new(structInlineMapStringAny),
6837 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
6838 }, {
6839 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Noop"),
6840 inBuf: `{}`,
6841 inVal: new(structInlinePointerInlineMapStringAny),
6842 want: new(structInlinePointerInlineMapStringAny),
6843 }, {
6844 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Alloc"),
6845 inBuf: `{"A":1,"fizz":"buzz"}`,
6846 inVal: new(structInlinePointerInlineMapStringAny),
6847 want: addr(structInlinePointerInlineMapStringAny{
6848 X: &struct {
6849 A int
6850 X jsonObject `json:",inline"`
6851 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6852 }),
6853 }, {
6854 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Merge"),
6855 inBuf: `{"fizz":"buzz"}`,
6856 inVal: addr(structInlinePointerInlineMapStringAny{
6857 X: &struct {
6858 A int
6859 X jsonObject `json:",inline"`
6860 }{A: 1},
6861 }),
6862 want: addr(structInlinePointerInlineMapStringAny{
6863 X: &struct {
6864 A int
6865 X jsonObject `json:",inline"`
6866 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6867 }),
6868 }, {
6869 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6870 opts: []Options{
6871 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
6872 var err error
6873 *v, err = strconv.ParseFloat(string(bytes.Trim(b, `"`)), 64)
6874 return err
6875 })),
6876 },
6877 inBuf: `{"D":"1.1","E":"2.2","F":"3.3"}`,
6878 inVal: new(structInlineMapStringAny),
6879 want: addr(structInlineMapStringAny{X: jsonObject{"D": 1.1, "E": 2.2, "F": 3.3}}),
6880 }, {
6881 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Noop"),
6882 inBuf: `{"A":1,"B":2}`,
6883 inVal: new(structInlinePointerMapStringAny),
6884 want: addr(structInlinePointerMapStringAny{A: 1, X: nil, B: 2}),
6885 }, {
6886 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Alloc"),
6887 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6888 inVal: new(structInlinePointerMapStringAny),
6889 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "buzz"}), B: 2}),
6890 }, {
6891 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Merge"),
6892 inBuf: `{"A":1,"fizz":"wuzz","B":2}`,
6893 inVal: addr(structInlinePointerMapStringAny{X: addr(jsonObject{"fizz": "buzz"})}),
6894 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "wuzz"}), B: 2}),
6895 }, {
6896 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
6897 inBuf: `{"fizz":"buzz"}`,
6898 inVal: new(structInlineInlinePointerMapStringAny),
6899 want: addr(structInlineInlinePointerMapStringAny{
6900 X: struct {
6901 X *jsonObject `json:",inline"`
6902 }{X: addr(jsonObject{"fizz": "buzz"})},
6903 }),
6904 }, {
6905 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
6906 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6907 inVal: new(structInlineMapStringInt),
6908 want: addr(structInlineMapStringInt{
6909 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6910 }),
6911 }, {
6912 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Null"),
6913 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6914 inVal: new(structInlineMapStringInt),
6915 want: addr(structInlineMapStringInt{
6916 X: map[string]int{"zero": 0, "one": 0, "two": 2},
6917 }),
6918 }, {
6919 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Invalid"),
6920 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6921 inVal: new(structInlineMapStringInt),
6922 want: addr(structInlineMapStringInt{
6923 X: map[string]int{"zero": 0, "one": 0},
6924 }),
6925 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6926 }, {
6927 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
6928 opts: []Options{StringifyNumbers(true)},
6929 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6930 inVal: new(structInlineMapStringInt),
6931 want: addr(structInlineMapStringInt{
6932 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6933 }),
6934 }, {
6935 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6936 opts: []Options{
6937 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6938 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6939 if err != nil {
6940 return err
6941 }
6942 *v = int(i)
6943 return nil
6944 })),
6945 },
6946 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6947 inVal: new(structInlineMapStringInt),
6948 want: addr(structInlineMapStringInt{
6949 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6950 }),
6951 }, {
6952 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
6953 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6954 inVal: new(structInlineMapNamedStringInt),
6955 want: addr(structInlineMapNamedStringInt{
6956 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6957 }),
6958 }, {
6959 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Null"),
6960 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6961 inVal: new(structInlineMapNamedStringInt),
6962 want: addr(structInlineMapNamedStringInt{
6963 X: map[namedString]int{"zero": 0, "one": 0, "two": 2},
6964 }),
6965 }, {
6966 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Invalid"),
6967 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6968 inVal: new(structInlineMapNamedStringInt),
6969 want: addr(structInlineMapNamedStringInt{
6970 X: map[namedString]int{"zero": 0, "one": 0},
6971 }),
6972 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6973 }, {
6974 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/StringifiedNumbers"),
6975 opts: []Options{StringifyNumbers(true)},
6976 inBuf: `{"zero": "0", "one": 1, "two": "2"}`,
6977 inVal: new(structInlineMapNamedStringInt),
6978 want: addr(structInlineMapNamedStringInt{
6979 X: map[namedString]int{"zero": 0, "one": 0},
6980 }),
6981 wantErr: EU(nil).withPos(`{"zero": "0", "one": `, "/one").withType('0', T[int]()),
6982 }, {
6983 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/UnmarshalFunc"),
6984 opts: []Options{
6985 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6986 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6987 if err != nil {
6988 return err
6989 }
6990 *v = int(i)
6991 return nil
6992 })),
6993 },
6994 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6995 inVal: new(structInlineMapNamedStringInt),
6996 want: addr(structInlineMapNamedStringInt{
6997 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6998 }),
6999 }, {
7000 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Noop"),
7001 inBuf: `{"A":1,"B":2}`,
7002 inVal: new(structInlineMapNamedStringAny),
7003 want: addr(structInlineMapNamedStringAny{A: 1, X: nil, B: 2}),
7004 }, {
7005 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Nil"),
7006 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7007 inVal: new(structInlineMapNamedStringAny),
7008 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
7009 }, {
7010 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Empty"),
7011 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7012 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{}}),
7013 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
7014 }, {
7015 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/ObjectN1"),
7016 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
7017 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": jsonObject{
7018 "alpha": "bravo",
7019 "charlie": "delta",
7020 }}}),
7021 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": jsonObject{
7022 "alpha": "bravo",
7023 "charlie": "DELTA",
7024 "echo": "foxtrot",
7025 }}, B: 2}),
7026 }, {
7027 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN2/ObjectN1"),
7028 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
7029 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": "wuzz"}}),
7030 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
7031 }, {
7032 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue"),
7033 inBuf: `{"A":1,"fizz":nil,"B":2}`,
7034 inVal: new(structInlineMapNamedStringAny),
7035 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": nil}}),
7036 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
7037 }, {
7038 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue/Existing"),
7039 inBuf: `{"A":1,"fizz":nil,"B":2}`,
7040 inVal: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
7041 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
7042 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
7043 }, {
7044 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/CaseSensitive"),
7045 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
7046 inVal: new(structInlineMapNamedStringAny),
7047 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "a": 3.0}, B: 2}),
7048 }, {
7049 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectDuplicateNames"),
7050 opts: []Options{jsontext.AllowDuplicateNames(false)},
7051 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
7052 inVal: new(structInlineMapNamedStringAny),
7053 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
7054 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
7055 }, {
7056 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowDuplicateNames"),
7057 opts: []Options{jsontext.AllowDuplicateNames(true)},
7058 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
7059 inVal: new(structInlineMapNamedStringAny),
7060 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": map[string]any{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
7061 }, {
7062 name: jsontest.Name("Structs/InlinedFallback/RejectUnknownMembers"),
7063 opts: []Options{RejectUnknownMembers(true)},
7064 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7065 inVal: new(structInlineTextValue),
7066 want: addr(structInlineTextValue{
7067 A: 1,
7068 X: jsontext.Value(`{"fizz":"buzz"}`),
7069 B: 2,
7070 }),
7071 }, {
7072 name: jsontest.Name("Structs/UnknownIgnored"),
7073 opts: []Options{RejectUnknownMembers(false)},
7074 inBuf: `{"unknown":"fizzbuzz"}`,
7075 inVal: new(structAll),
7076 want: new(structAll),
7077 }, {
7078 name: jsontest.Name("Structs/RejectUnknownMembers"),
7079 opts: []Options{RejectUnknownMembers(true)},
7080 inBuf: `{"unknown":"fizzbuzz"}`,
7081 inVal: new(structAll),
7082 want: new(structAll),
7083 wantErr: EU(ErrUnknownName).withPos(`{`, "/unknown").withType('"', T[structAll]()),
7084 }, {
7085 name: jsontest.Name("Structs/UnexportedIgnored"),
7086 inBuf: `{"ignored":"unused"}`,
7087 inVal: new(structUnexportedIgnored),
7088 want: new(structUnexportedIgnored),
7089 }, {
7090 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
7091 inBuf: `{"namedString":"unused"}`,
7092 inVal: new(structIgnoredUnexportedEmbedded),
7093 want: new(structIgnoredUnexportedEmbedded),
7094 }, {
7095 name: jsontest.Name("Structs/WeirdNames"),
7096 inBuf: `{"":"empty",",":"comma","\"":"quote"}`,
7097 inVal: new(structWeirdNames),
7098 want: addr(structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"}),
7099 skip: !internal.ExpJSONFormat,
7100 }, {
7101 name: jsontest.Name("Structs/NoCase/Exact"),
7102 inBuf: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
7103 inVal: new(structNoCase),
7104 want: addr(structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"}),
7105 }, {
7106 name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault"),
7107 inBuf: `{"aa_a":"aa_a"}`,
7108 inVal: new(structNoCase),
7109 want: addr(structNoCase{AaA: "aa_a"}),
7110 }, {
7111 name: jsontest.Name("Structs/NoCase/MatchCaseSensitiveDelimiter"),
7112 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
7113 inBuf: `{"aa_a":"aa_a"}`,
7114 inVal: new(structNoCase),
7115 want: addr(structNoCase{}),
7116 }, {
7117 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
7118 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
7119 inBuf: `{"aa_a":"aa_a"}`,
7120 inVal: new(structNoCase),
7121 want: addr(structNoCase{AA_A: "aa_a"}),
7122 }, {
7123 name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames"),
7124 opts: []Options{jsontext.AllowDuplicateNames(true)},
7125 inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`,
7126 inVal: new(structNoCase),
7127 want: addr(structNoCase{AaA: "aAa"}),
7128 }, {
7129 name: jsontest.Name("Structs/NoCase/Merge/RejectDuplicateNames"),
7130 opts: []Options{jsontext.AllowDuplicateNames(false)},
7131 inBuf: `{"AaA":"AaA","aaa":"aaa"}`,
7132 inVal: new(structNoCase),
7133 want: addr(structNoCase{AaA: "AaA"}),
7134 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AaA":"AaA",`)),
7135 }, {
7136 name: jsontest.Name("Structs/CaseSensitive"),
7137 inBuf: `{"BOOL": true, "STRING": "hello", "BYTES": "AQID", "INT": -64, "UINT": 64, "FLOAT": 3.14159}`,
7138 inVal: new(structScalars),
7139 want: addr(structScalars{}),
7140 }, {
7141 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactDifferent"),
7142 inBuf: `{"AAA":"AAA","AaA":"AaA","AAa":"AAa","Aaa":"Aaa"}`,
7143 inVal: addr(structNoCaseInlineTextValue{}),
7144 want: addr(structNoCaseInlineTextValue{AAA: "AAA", AaA: "AaA", AAa: "AAa", Aaa: "Aaa"}),
7145 }, {
7146 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactConflict"),
7147 inBuf: `{"AAA":"AAA","AAA":"AAA"}`,
7148 inVal: addr(structNoCaseInlineTextValue{}),
7149 want: addr(structNoCaseInlineTextValue{AAA: "AAA"}),
7150 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"AAA",`)),
7151 }, {
7152 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteExact"),
7153 inBuf: `{"AAA":"after"}`,
7154 inVal: addr(structNoCaseInlineTextValue{AAA: "before"}),
7155 want: addr(structNoCaseInlineTextValue{AAA: "after"}),
7156 }, {
7157 name: jsontest.Name("Structs/DuplicateName/NoCase/NoCaseConflict"),
7158 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7159 inVal: addr(structNoCaseInlineTextValue{}),
7160 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7161 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7162 }, {
7163 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteNoCase"),
7164 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7165 inVal: addr(structNoCaseInlineTextValue{}),
7166 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7167 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7168 }, {
7169 name: jsontest.Name("Structs/DuplicateName/Inline/Unknown"),
7170 inBuf: `{"unknown":""}`,
7171 inVal: addr(structNoCaseInlineTextValue{}),
7172 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7173 }, {
7174 name: jsontest.Name("Structs/DuplicateName/Inline/UnknownMerge"),
7175 inBuf: `{"unknown":""}`,
7176 inVal: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7177 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":"","unknown":""}`)}),
7178 }, {
7179 name: jsontest.Name("Structs/DuplicateName/Inline/NoCaseOkay"),
7180 inBuf: `{"b":"","B":""}`,
7181 inVal: addr(structNoCaseInlineTextValue{}),
7182 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":"","B":""}`)}),
7183 }, {
7184 name: jsontest.Name("Structs/DuplicateName/Inline/ExactConflict"),
7185 inBuf: `{"b":"","b":""}`,
7186 inVal: addr(structNoCaseInlineTextValue{}),
7187 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":""}`)}),
7188 wantErr: newDuplicateNameError("", []byte(`"b"`), len64(`{"b":"",`)),
7189 }, {
7190 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7191 inBuf: ``,
7192 inVal: addr(structAll{}),
7193 want: addr(structAll{}),
7194 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF},
7195 }, {
7196 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7197 inBuf: " \n\r\t",
7198 inVal: addr(structAll{}),
7199 want: addr(structAll{}),
7200 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF, ByteOffset: len64(" \n\r\t")},
7201 }, {
7202 name: jsontest.Name("Structs/Invalid/NestedErrUnexpectedEOF"),
7203 inBuf: `{"Pointer":`,
7204 inVal: addr(structAll{}),
7205 want: addr(structAll{Pointer: new(structAll)}),
7206 wantErr: &jsontext.SyntacticError{ByteOffset: len64(`{"Pointer":`), JSONPointer: "/Pointer", Err: io.ErrUnexpectedEOF},
7207 }, {
7208 name: jsontest.Name("Structs/Invalid/Conflicting"),
7209 inBuf: `{}`,
7210 inVal: addr(structConflicting{}),
7211 want: addr(structConflicting{}),
7212 wantErr: EU(errors.New(`Go struct fields A and B conflict over JSON object name "conflict"`)).withType('{', T[structConflicting]()),
7213 }, {
7214 name: jsontest.Name("Structs/Invalid/NoneExported"),
7215 inBuf: ` {}`,
7216 inVal: addr(structNoneExported{}),
7217 want: addr(structNoneExported{}),
7218 wantErr: EU(errNoExportedFields).withPos(` `, "").withType('{', T[structNoneExported]()),
7219 }, {
7220 name: jsontest.Name("Structs/Invalid/MalformedTag"),
7221 inBuf: `{}`,
7222 inVal: addr(structMalformedTag{}),
7223 want: addr(structMalformedTag{}),
7224 wantErr: EU(errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter or single quote)")).withType('{', T[structMalformedTag]()),
7225 }, {
7226 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
7227 inBuf: `{}`,
7228 inVal: addr(structUnexportedTag{}),
7229 want: addr(structUnexportedTag{}),
7230 wantErr: EU(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType('{', T[structUnexportedTag]()),
7231 }, {
7232 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
7233 inBuf: `{"NamedString":"hello"}`,
7234 inVal: addr(structExportedEmbedded{}),
7235 want: addr(structExportedEmbedded{}),
7236 wantErr: EU(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structExportedEmbedded]()),
7237 }, {
7238 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
7239 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
7240 inBuf: `{"NamedString":"hello"}`,
7241 inVal: addr(structExportedEmbedded{}),
7242 want: addr(structExportedEmbedded{"hello"}),
7243 }, {
7244 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
7245 inBuf: `{"name":"hello"}`,
7246 inVal: addr(structExportedEmbeddedTag{}),
7247 want: addr(structExportedEmbeddedTag{"hello"}),
7248 }, {
7249 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
7250 inBuf: `{}`,
7251 inVal: addr(structUnexportedEmbedded{}),
7252 want: addr(structUnexportedEmbedded{}),
7253 wantErr: EU(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structUnexportedEmbedded]()),
7254 }, {
7255 name: jsontest.Name("Structs/UnexportedEmbeddedStruct"),
7256 inBuf: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7257 inVal: addr(structUnexportedEmbeddedStruct{}),
7258 want: addr(structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7259 }, {
7260 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7261 inBuf: `{"Bool":true,"FizzBuzz":5}`,
7262 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7263 wantErr: EU(errNilField).withPos(`{"Bool":`, "/Bool").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7264 }, {
7265 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7266 inBuf: `{"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7267 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7268 wantErr: EU(errNilField).withPos(`{"FizzBuzz":5,"Addr":`, "/Addr").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7269 }, {
7270 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7271 inBuf: `{"Bool":true,"FizzBuzz":10,"Addr":"192.168.0.1"}`,
7272 inVal: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Int: 5}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{127, 0, 0, 1})}}),
7273 want: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true, Int: 5}, 10, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7274 }, {
7275 name: jsontest.Name("Structs/Unknown"),
7276 inBuf: `{
7277 "object0": {},
7278 "object1": {"key1": "value"},
7279 "object2": {"key1": "value", "key2": "value"},
7280 "objects": {"":{"":{"":{}}}},
7281 "array0": [],
7282 "array1": ["value1"],
7283 "array2": ["value1", "value2"],
7284 "array": [[[]]],
7285 "scalars": [null, false, true, "string", 12.345]
7286 }`,
7287 inVal: addr(struct{}{}),
7288 want: addr(struct{}{}),
7289 }, {
7290 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
7291 opts: []Options{invalidFormatOption},
7292 inBuf: `{"Field":"Value"}`,
7293 inVal: addr(struct{ Field string }{}),
7294 want: addr(struct{ Field string }{"Value"}),
7295 }, {
7296 name: jsontest.Name("Slices/Null"),
7297 inBuf: `null`,
7298 inVal: addr([]string{"something"}),
7299 want: addr([]string(nil)),
7300 }, {
7301 name: jsontest.Name("Slices/Bool"),
7302 inBuf: `[true,false]`,
7303 inVal: new([]bool),
7304 want: addr([]bool{true, false}),
7305 }, {
7306 name: jsontest.Name("Slices/String"),
7307 inBuf: `["hello","goodbye"]`,
7308 inVal: new([]string),
7309 want: addr([]string{"hello", "goodbye"}),
7310 }, {
7311 name: jsontest.Name("Slices/Bytes"),
7312 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7313 inVal: new([][]byte),
7314 want: addr([][]byte{[]byte("hello"), []byte("goodbye")}),
7315 }, {
7316 name: jsontest.Name("Slices/Int"),
7317 inBuf: `[-2,-1,0,1,2]`,
7318 inVal: new([]int),
7319 want: addr([]int{-2, -1, 0, 1, 2}),
7320 }, {
7321 name: jsontest.Name("Slices/Uint"),
7322 inBuf: `[0,1,2,3,4]`,
7323 inVal: new([]uint),
7324 want: addr([]uint{0, 1, 2, 3, 4}),
7325 }, {
7326 name: jsontest.Name("Slices/Float"),
7327 inBuf: `[3.14159,12.34]`,
7328 inVal: new([]float64),
7329 want: addr([]float64{3.14159, 12.34}),
7330 }, {
7331
7332
7333
7334 name: jsontest.Name("Slices/Merge"),
7335 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7336 inVal: addr([]map[string]string{{"k1": "v1"}, {"k2": "v2"}}[:1]),
7337 want: addr([]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7338 }, {
7339 name: jsontest.Name("Slices/Invalid/Channel"),
7340 inBuf: `["hello"]`,
7341 inVal: new([]chan string),
7342 want: addr([]chan string{nil}),
7343 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7344 }, {
7345 name: jsontest.Name("Slices/RecursiveSlice"),
7346 inBuf: `[[],[],[[]],[[],[]]]`,
7347 inVal: new(recursiveSlice),
7348 want: addr(recursiveSlice{
7349 {},
7350 {},
7351 {{}},
7352 {{}, {}},
7353 }),
7354 }, {
7355 name: jsontest.Name("Slices/Invalid/Bool"),
7356 inBuf: `true`,
7357 inVal: addr([]string{"nochange"}),
7358 want: addr([]string{"nochange"}),
7359 wantErr: EU(nil).withType('t', T[[]string]()),
7360 }, {
7361 name: jsontest.Name("Slices/Invalid/String"),
7362 inBuf: `""`,
7363 inVal: addr([]string{"nochange"}),
7364 want: addr([]string{"nochange"}),
7365 wantErr: EU(nil).withType('"', T[[]string]()),
7366 }, {
7367 name: jsontest.Name("Slices/Invalid/Number"),
7368 inBuf: `0`,
7369 inVal: addr([]string{"nochange"}),
7370 want: addr([]string{"nochange"}),
7371 wantErr: EU(nil).withType('0', T[[]string]()),
7372 }, {
7373 name: jsontest.Name("Slices/Invalid/Object"),
7374 inBuf: `{}`,
7375 inVal: addr([]string{"nochange"}),
7376 want: addr([]string{"nochange"}),
7377 wantErr: EU(nil).withType('{', T[[]string]()),
7378 }, {
7379 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
7380 opts: []Options{invalidFormatOption},
7381 inBuf: `[false,true]`,
7382 inVal: addr([]bool{true, false}),
7383 want: addr([]bool{false, true}),
7384 }, {
7385 name: jsontest.Name("Arrays/Null"),
7386 inBuf: `null`,
7387 inVal: addr([1]string{"something"}),
7388 want: addr([1]string{}),
7389 }, {
7390 name: jsontest.Name("Arrays/Bool"),
7391 inBuf: `[true,false]`,
7392 inVal: new([2]bool),
7393 want: addr([2]bool{true, false}),
7394 }, {
7395 name: jsontest.Name("Arrays/String"),
7396 inBuf: `["hello","goodbye"]`,
7397 inVal: new([2]string),
7398 want: addr([2]string{"hello", "goodbye"}),
7399 }, {
7400 name: jsontest.Name("Arrays/Bytes"),
7401 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7402 inVal: new([2][]byte),
7403 want: addr([2][]byte{[]byte("hello"), []byte("goodbye")}),
7404 }, {
7405 name: jsontest.Name("Arrays/Int"),
7406 inBuf: `[-2,-1,0,1,2]`,
7407 inVal: new([5]int),
7408 want: addr([5]int{-2, -1, 0, 1, 2}),
7409 }, {
7410 name: jsontest.Name("Arrays/Uint"),
7411 inBuf: `[0,1,2,3,4]`,
7412 inVal: new([5]uint),
7413 want: addr([5]uint{0, 1, 2, 3, 4}),
7414 }, {
7415 name: jsontest.Name("Arrays/Float"),
7416 inBuf: `[3.14159,12.34]`,
7417 inVal: new([2]float64),
7418 want: addr([2]float64{3.14159, 12.34}),
7419 }, {
7420
7421
7422 name: jsontest.Name("Arrays/Merge"),
7423 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7424 inVal: addr([2]map[string]string{{"k1": "v1"}, {"k2": "v2"}}),
7425 want: addr([2]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7426 }, {
7427 name: jsontest.Name("Arrays/Invalid/Channel"),
7428 inBuf: `["hello"]`,
7429 inVal: new([1]chan string),
7430 want: new([1]chan string),
7431 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7432 }, {
7433 name: jsontest.Name("Arrays/Invalid/Underflow"),
7434 inBuf: `{"F":[ ]}`,
7435 inVal: new(struct{ F [1]string }),
7436 want: addr(struct{ F [1]string }{}),
7437 wantErr: EU(errArrayUnderflow).withPos(`{"F":[ `, "/F").withType(']', T[[1]string]()),
7438 }, {
7439 name: jsontest.Name("Arrays/Invalid/Underflow/UnmarshalArrayFromAnyLength"),
7440 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7441 inBuf: `[-1,-2]`,
7442 inVal: addr([4]int{1, 2, 3, 4}),
7443 want: addr([4]int{-1, -2, 0, 0}),
7444 }, {
7445 name: jsontest.Name("Arrays/Invalid/Overflow"),
7446 inBuf: `["1","2"]`,
7447 inVal: new([1]string),
7448 want: addr([1]string{"1"}),
7449 wantErr: EU(errArrayOverflow).withPos(`["1","2"`, "").withType(']', T[[1]string]()),
7450 }, {
7451 name: jsontest.Name("Arrays/Invalid/Overflow/UnmarshalArrayFromAnyLength"),
7452 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7453 inBuf: `[-1,-2,-3,-4,-5,-6]`,
7454 inVal: addr([4]int{1, 2, 3, 4}),
7455 want: addr([4]int{-1, -2, -3, -4}),
7456 }, {
7457 name: jsontest.Name("Arrays/Invalid/Bool"),
7458 inBuf: `true`,
7459 inVal: addr([1]string{"nochange"}),
7460 want: addr([1]string{"nochange"}),
7461 wantErr: EU(nil).withType('t', T[[1]string]()),
7462 }, {
7463 name: jsontest.Name("Arrays/Invalid/String"),
7464 inBuf: `""`,
7465 inVal: addr([1]string{"nochange"}),
7466 want: addr([1]string{"nochange"}),
7467 wantErr: EU(nil).withType('"', T[[1]string]()),
7468 }, {
7469 name: jsontest.Name("Arrays/Invalid/Number"),
7470 inBuf: `0`,
7471 inVal: addr([1]string{"nochange"}),
7472 want: addr([1]string{"nochange"}),
7473 wantErr: EU(nil).withType('0', T[[1]string]()),
7474 }, {
7475 name: jsontest.Name("Arrays/Invalid/Object"),
7476 inBuf: `{}`,
7477 inVal: addr([1]string{"nochange"}),
7478 want: addr([1]string{"nochange"}),
7479 wantErr: EU(nil).withType('{', T[[1]string]()),
7480 }, {
7481 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
7482 opts: []Options{invalidFormatOption},
7483 inBuf: `[false,true]`,
7484 inVal: addr([2]bool{true, false}),
7485 want: addr([2]bool{false, true}),
7486 }, {
7487 name: jsontest.Name("Pointers/NullL0"),
7488 inBuf: `null`,
7489 inVal: new(*string),
7490 want: addr((*string)(nil)),
7491 }, {
7492 name: jsontest.Name("Pointers/NullL1"),
7493 inBuf: `null`,
7494 inVal: addr(new(*string)),
7495 want: addr((**string)(nil)),
7496 }, {
7497 name: jsontest.Name("Pointers/Bool"),
7498 inBuf: `true`,
7499 inVal: addr(new(bool)),
7500 want: addr(addr(true)),
7501 }, {
7502 name: jsontest.Name("Pointers/String"),
7503 inBuf: `"hello"`,
7504 inVal: addr(new(string)),
7505 want: addr(addr("hello")),
7506 }, {
7507 name: jsontest.Name("Pointers/Bytes"),
7508 inBuf: `"aGVsbG8="`,
7509 inVal: addr(new([]byte)),
7510 want: addr(addr([]byte("hello"))),
7511 }, {
7512 name: jsontest.Name("Pointers/Int"),
7513 inBuf: `-123`,
7514 inVal: addr(new(int)),
7515 want: addr(addr(int(-123))),
7516 }, {
7517 name: jsontest.Name("Pointers/Uint"),
7518 inBuf: `123`,
7519 inVal: addr(new(int)),
7520 want: addr(addr(int(123))),
7521 }, {
7522 name: jsontest.Name("Pointers/Float"),
7523 inBuf: `123.456`,
7524 inVal: addr(new(float64)),
7525 want: addr(addr(float64(123.456))),
7526 }, {
7527 name: jsontest.Name("Pointers/Allocate"),
7528 inBuf: `"hello"`,
7529 inVal: addr((*string)(nil)),
7530 want: addr(addr("hello")),
7531 }, {
7532 name: jsontest.Name("Points/IgnoreInvalidFormat"),
7533 opts: []Options{invalidFormatOption},
7534 inBuf: `true`,
7535 inVal: addr(new(bool)),
7536 want: addr(addr(true)),
7537 }, {
7538 name: jsontest.Name("Interfaces/Empty/Null"),
7539 inBuf: `null`,
7540 inVal: new(any),
7541 want: new(any),
7542 }, {
7543 name: jsontest.Name("Interfaces/NonEmpty/Null"),
7544 inBuf: `null`,
7545 inVal: new(io.Reader),
7546 want: new(io.Reader),
7547 }, {
7548 name: jsontest.Name("Interfaces/NonEmpty/Invalid"),
7549 inBuf: `"hello"`,
7550 inVal: new(io.Reader),
7551 want: new(io.Reader),
7552 wantErr: EU(internal.ErrNilInterface).withType(0, T[io.Reader]()),
7553 }, {
7554 name: jsontest.Name("Interfaces/Empty/False"),
7555 inBuf: `false`,
7556 inVal: new(any),
7557 want: func() any {
7558 var vi any = false
7559 return &vi
7560 }(),
7561 }, {
7562 name: jsontest.Name("Interfaces/Empty/True"),
7563 inBuf: `true`,
7564 inVal: new(any),
7565 want: func() any {
7566 var vi any = true
7567 return &vi
7568 }(),
7569 }, {
7570 name: jsontest.Name("Interfaces/Empty/String"),
7571 inBuf: `"string"`,
7572 inVal: new(any),
7573 want: func() any {
7574 var vi any = "string"
7575 return &vi
7576 }(),
7577 }, {
7578 name: jsontest.Name("Interfaces/Empty/Number"),
7579 inBuf: `3.14159`,
7580 inVal: new(any),
7581 want: func() any {
7582 var vi any = 3.14159
7583 return &vi
7584 }(),
7585 }, {
7586 name: jsontest.Name("Interfaces/Empty/Object"),
7587 inBuf: `{"k":"v"}`,
7588 inVal: new(any),
7589 want: func() any {
7590 var vi any = map[string]any{"k": "v"}
7591 return &vi
7592 }(),
7593 }, {
7594 name: jsontest.Name("Interfaces/Empty/Array"),
7595 inBuf: `["v"]`,
7596 inVal: new(any),
7597 want: func() any {
7598 var vi any = []any{"v"}
7599 return &vi
7600 }(),
7601 }, {
7602 name: jsontest.Name("Interfaces/NamedAny/String"),
7603 inBuf: `"string"`,
7604 inVal: new(namedAny),
7605 want: func() namedAny {
7606 var vi namedAny = "string"
7607 return &vi
7608 }(),
7609 }, {
7610 name: jsontest.Name("Interfaces/Invalid"),
7611 inBuf: `]`,
7612 inVal: new(any),
7613 want: new(any),
7614 wantErr: newInvalidCharacterError("]", "at start of value", 0, ""),
7615 }, {
7616
7617
7618
7619
7620 name: jsontest.Name("Interfaces/Merge/Map"),
7621 inBuf: `{"k2":"v2"}`,
7622 inVal: func() any {
7623 var vi any = map[string]string{"k1": "v1"}
7624 return &vi
7625 }(),
7626 want: func() any {
7627 var vi any = map[string]string{"k1": "v1", "k2": "v2"}
7628 return &vi
7629 }(),
7630 }, {
7631 name: jsontest.Name("Interfaces/Merge/Struct"),
7632 inBuf: `{"Array":["goodbye"]}`,
7633 inVal: func() any {
7634 var vi any = structAll{String: "hello"}
7635 return &vi
7636 }(),
7637 want: func() any {
7638 var vi any = structAll{String: "hello", Array: [1]string{"goodbye"}}
7639 return &vi
7640 }(),
7641 }, {
7642 name: jsontest.Name("Interfaces/Merge/NamedInt"),
7643 inBuf: `64`,
7644 inVal: func() any {
7645 var vi any = namedInt64(-64)
7646 return &vi
7647 }(),
7648 want: func() any {
7649 var vi any = namedInt64(+64)
7650 return &vi
7651 }(),
7652 }, {
7653 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
7654 opts: []Options{invalidFormatOption},
7655 inBuf: `true`,
7656 inVal: new(any),
7657 want: func() any {
7658 var vi any = true
7659 return &vi
7660 }(),
7661 }, {
7662 name: jsontest.Name("Interfaces/Any"),
7663 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7664 inVal: new(struct{ X any }),
7665 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7666 }, {
7667 name: jsontest.Name("Interfaces/Any/Named"),
7668 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7669 inVal: new(struct{ X namedAny }),
7670 want: addr(struct{ X namedAny }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7671 }, {
7672 name: jsontest.Name("Interfaces/Any/Stringified"),
7673 opts: []Options{StringifyNumbers(true)},
7674 inBuf: `{"X":"0"}`,
7675 inVal: new(struct{ X any }),
7676 want: addr(struct{ X any }{"0"}),
7677 }, {
7678 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Any"),
7679 opts: []Options{
7680 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
7681 *v = "called"
7682 return nil
7683 })),
7684 },
7685 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7686 inVal: new(struct{ X any }),
7687 want: addr(struct{ X any }{"called"}),
7688 }, {
7689 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Bool"),
7690 opts: []Options{
7691 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *bool) error {
7692 *v = string(b) != "true"
7693 return nil
7694 })),
7695 },
7696 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7697 inVal: new(struct{ X any }),
7698 want: addr(struct{ X any }{[]any{nil, true, false, "", 0.0, map[string]any{}, []any{}}}),
7699 }, {
7700 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/String"),
7701 opts: []Options{
7702 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7703 *v = "called"
7704 return nil
7705 })),
7706 },
7707 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7708 inVal: new(struct{ X any }),
7709 want: addr(struct{ X any }{[]any{nil, false, true, "called", 0.0, map[string]any{}, []any{}}}),
7710 }, {
7711 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Float64"),
7712 opts: []Options{
7713 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *float64) error {
7714 *v = 3.14159
7715 return nil
7716 })),
7717 },
7718 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7719 inVal: new(struct{ X any }),
7720 want: addr(struct{ X any }{[]any{nil, false, true, "", 3.14159, map[string]any{}, []any{}}}),
7721 }, {
7722 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/MapStringAny"),
7723 opts: []Options{
7724 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *map[string]any) error {
7725 *v = map[string]any{"called": nil}
7726 return nil
7727 })),
7728 },
7729 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7730 inVal: new(struct{ X any }),
7731 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{"called": nil}, []any{}}}),
7732 }, {
7733 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/SliceAny"),
7734 opts: []Options{
7735 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *[]any) error {
7736 *v = []any{"called"}
7737 return nil
7738 })),
7739 },
7740 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7741 inVal: new(struct{ X any }),
7742 want: addr(struct{ X any }{[]any{"called"}}),
7743 }, {
7744 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
7745 inBuf: `{"X":{"fizz":"buzz"}}`,
7746 inVal: new(struct{ X any }),
7747 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7748 }, {
7749 name: jsontest.Name("Interfaces/Any/Maps/RejectDuplicateNames"),
7750 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7751 inVal: new(struct{ X any }),
7752 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7753 wantErr: newDuplicateNameError("/X", []byte(`"fizz"`), len64(`{"X":{"fizz":"buzz",`)),
7754 }, {
7755 name: jsontest.Name("Interfaces/Any/Maps/AllowDuplicateNames"),
7756 opts: []Options{jsontext.AllowDuplicateNames(true)},
7757 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7758 inVal: new(struct{ X any }),
7759 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7760 wantErr: EU(nil).withPos(`{"X":{"fizz":"buzz","fizz":`, "/X/fizz").withType('t', T[string]()),
7761 }, {
7762 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
7763 inBuf: `{"X":["fizz","buzz"]}`,
7764 inVal: new(struct{ X any }),
7765 want: addr(struct{ X any }{[]any{"fizz", "buzz"}}),
7766 }, {
7767 name: jsontest.Name("Methods/NilPointer/Null"),
7768 inBuf: `{"X":null}`,
7769 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7770 want: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7771 }, {
7772 name: jsontest.Name("Methods/NilPointer/Value"),
7773 inBuf: `{"X":"value"}`,
7774 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7775 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7776 }, {
7777 name: jsontest.Name("Methods/NilInterface/Null"),
7778 inBuf: `{"X":null}`,
7779 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7780 want: addr(struct{ X MarshalerTo }{X: nil}),
7781 }, {
7782 name: jsontest.Name("Methods/NilInterface/Value"),
7783 inBuf: `{"X":"value"}`,
7784 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7785 want: addr(struct{ X MarshalerTo }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7786 }, {
7787 name: jsontest.Name("Methods/AllMethods"),
7788 inBuf: `{"X":"hello"}`,
7789 inVal: new(struct{ X *allMethods }),
7790 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}),
7791 }, {
7792 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
7793 inBuf: `{"X":"hello"}`,
7794 inVal: new(struct{ X *allMethodsExceptJSONv2 }),
7795 want: addr(struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7796 }, {
7797 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
7798 inBuf: `{"X":"hello"}`,
7799 inVal: new(struct{ X *allMethodsExceptJSONv1 }),
7800 want: addr(struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7801 }, {
7802 name: jsontest.Name("Methods/AllMethodsExceptText"),
7803 inBuf: `{"X":"hello"}`,
7804 inVal: new(struct{ X *allMethodsExceptText }),
7805 want: addr(struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7806 }, {
7807 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
7808 inBuf: `{"X":"hello"}`,
7809 inVal: new(struct{ X *onlyMethodJSONv2 }),
7810 want: addr(struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7811 }, {
7812 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
7813 inBuf: `{"X":"hello"}`,
7814 inVal: new(struct{ X *onlyMethodJSONv1 }),
7815 want: addr(struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7816 }, {
7817 name: jsontest.Name("Methods/OnlyMethodText"),
7818 inBuf: `{"X":"hello"}`,
7819 inVal: new(struct{ X *onlyMethodText }),
7820 want: addr(struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "UnmarshalText", value: []byte(`hello`)}}}),
7821 }, {
7822 name: jsontest.Name("Methods/Text/Null"),
7823 inBuf: `{"X":null}`,
7824 inVal: addr(struct{ X unmarshalTextFunc }{unmarshalTextFunc(func(b []byte) error {
7825 return errMustNotCall
7826 })}),
7827 want: addr(struct{ X unmarshalTextFunc }{nil}),
7828 }, {
7829 name: jsontest.Name("Methods/IP"),
7830 inBuf: `"192.168.0.100"`,
7831 inVal: new(net.IP),
7832 want: addr(net.IPv4(192, 168, 0, 100)),
7833 }, {
7834
7835 name: jsontest.Name("Methods/Anonymous"),
7836 inBuf: `{"X":"hello"}`,
7837 inVal: new(struct{ X struct{ allMethods } }),
7838 want: addr(struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7839 }, {
7840
7841 name: jsontest.Name("Methods/Addressable"),
7842 inBuf: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
7843 inVal: addr(struct {
7844 V allMethods
7845 M map[string]allMethods
7846 I any
7847 }{
7848 I: allMethods{},
7849 }),
7850 want: addr(struct {
7851 V allMethods
7852 M map[string]allMethods
7853 I any
7854 }{
7855 V: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7856 M: map[string]allMethods{"K": {method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}},
7857 I: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7858 }),
7859 }, {
7860
7861 name: jsontest.Name("Methods/MapKey/JSONv2"),
7862 inBuf: `{"k1":"v1b","k2":"v2"}`,
7863 inVal: addr(map[structMethodJSONv2]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7864 want: addr(map[structMethodJSONv2]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7865 }, {
7866
7867 name: jsontest.Name("Methods/MapKey/JSONv1"),
7868 inBuf: `{"k1":"v1b","k2":"v2"}`,
7869 inVal: addr(map[structMethodJSONv1]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7870 want: addr(map[structMethodJSONv1]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7871 }, {
7872 name: jsontest.Name("Methods/MapKey/Text"),
7873 inBuf: `{"k1":"v1b","k2":"v2"}`,
7874 inVal: addr(map[structMethodText]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7875 want: addr(map[structMethodText]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7876 }, {
7877 name: jsontest.Name("Methods/JSONv2/ErrUnsupported"),
7878 inBuf: `{"fizz":123}`,
7879 inVal: addr(unsupportedMethodJSONv2{}),
7880 want: addr(unsupportedMethodJSONv2{"called": 1, "fizz": 123}),
7881 }, {
7882 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
7883 inBuf: `{}`,
7884 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7885 return errSomeError
7886 })),
7887 wantErr: EU(errSomeError).withType(0, T[unmarshalJSONv2Func]()),
7888 }, {
7889 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
7890 inBuf: `{}`,
7891 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7892 return nil
7893 })),
7894 wantErr: EU(errNonSingularValue).withType(0, T[unmarshalJSONv2Func]()),
7895 }, {
7896 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
7897 inBuf: `{}{}`,
7898 inVal: addr(unmarshalJSONv2Func(func(dec *jsontext.Decoder) error {
7899 dec.ReadValue()
7900 dec.ReadValue()
7901 return nil
7902 })),
7903 wantErr: EU(errNonSingularValue).withPos(`{}`, "").withType(0, T[unmarshalJSONv2Func]()),
7904 }, {
7905 name: jsontest.Name("Methods/Invalid/JSONv2/ErrUnsupported"),
7906 inBuf: `{}`,
7907 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7908 return errors.ErrUnsupported
7909 })),
7910 wantErr: EU(nil).withType(0, T[unmarshalJSONv2Func]()),
7911 }, {
7912 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
7913 inBuf: `{}`,
7914 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7915 return errSomeError
7916 })),
7917 wantErr: EU(errSomeError).withType('{', T[unmarshalJSONv1Func]()),
7918 }, {
7919 name: jsontest.Name("Methods/Invalid/JSONv1/ErrUnsupported"),
7920 inBuf: `{}`,
7921 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7922 return errors.ErrUnsupported
7923 })),
7924 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "UnmarshalJSON method")).withType('{', T[unmarshalJSONv1Func]()),
7925 }, {
7926 name: jsontest.Name("Methods/Invalid/Text/Error"),
7927 inBuf: `"value"`,
7928 inVal: addr(unmarshalTextFunc(func([]byte) error {
7929 return errSomeError
7930 })),
7931 wantErr: EU(errSomeError).withType('"', T[unmarshalTextFunc]()),
7932 }, {
7933 name: jsontest.Name("Methods/Invalid/Text/Syntax"),
7934 inBuf: `{}`,
7935 inVal: addr(unmarshalTextFunc(func([]byte) error {
7936 panic("should not be called")
7937 })),
7938 wantErr: EU(errNonStringValue).withType('{', T[unmarshalTextFunc]()),
7939 }, {
7940 name: jsontest.Name("Methods/Invalid/Text/ErrUnsupported"),
7941 inBuf: `"value"`,
7942 inVal: addr(unmarshalTextFunc(func([]byte) error {
7943 return errors.ErrUnsupported
7944 })),
7945 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "UnmarshalText method")).withType('"', T[unmarshalTextFunc]()),
7946 }, {
7947 name: jsontest.Name("Functions/String/V1"),
7948 opts: []Options{
7949 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7950 if string(b) != `""` {
7951 return fmt.Errorf("got %s, want %s", b, `""`)
7952 }
7953 *v = "called"
7954 return nil
7955 })),
7956 },
7957 inBuf: `""`,
7958 inVal: addr(""),
7959 want: addr("called"),
7960 }, {
7961 name: jsontest.Name("Functions/String/Empty"),
7962 opts: []Options{WithUnmarshalers(nil)},
7963 inBuf: `"hello"`,
7964 inVal: addr(""),
7965 want: addr("hello"),
7966 }, {
7967 name: jsontest.Name("Functions/NamedString/V1/NoMatch"),
7968 opts: []Options{
7969 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7970 panic("should not be called")
7971 })),
7972 },
7973 inBuf: `""`,
7974 inVal: addr(""),
7975 want: addr(""),
7976 }, {
7977 name: jsontest.Name("Functions/NamedString/V1/Match"),
7978 opts: []Options{
7979 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7980 if string(b) != `""` {
7981 return fmt.Errorf("got %s, want %s", b, `""`)
7982 }
7983 *v = "called"
7984 return nil
7985 })),
7986 },
7987 inBuf: `""`,
7988 inVal: addr(namedString("")),
7989 want: addr(namedString("called")),
7990 }, {
7991 name: jsontest.Name("Functions/String/V2"),
7992 opts: []Options{
7993 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
7994 switch b, err := dec.ReadValue(); {
7995 case err != nil:
7996 return err
7997 case string(b) != `""`:
7998 return fmt.Errorf("got %s, want %s", b, `""`)
7999 }
8000 *v = "called"
8001 return nil
8002 })),
8003 },
8004 inBuf: `""`,
8005 inVal: addr(""),
8006 want: addr("called"),
8007 }, {
8008 name: jsontest.Name("Functions/NamedString/V2/NoMatch"),
8009 opts: []Options{
8010 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
8011 panic("should not be called")
8012 })),
8013 },
8014 inBuf: `""`,
8015 inVal: addr(""),
8016 want: addr(""),
8017 }, {
8018 name: jsontest.Name("Functions/NamedString/V2/Match"),
8019 opts: []Options{
8020 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
8021 switch t, err := dec.ReadToken(); {
8022 case err != nil:
8023 return err
8024 case t.String() != ``:
8025 return fmt.Errorf("got %q, want %q", t, ``)
8026 }
8027 *v = "called"
8028 return nil
8029 })),
8030 },
8031 inBuf: `""`,
8032 inVal: addr(namedString("")),
8033 want: addr(namedString("called")),
8034 }, {
8035 name: jsontest.Name("Functions/String/Empty1/NoMatch"),
8036 opts: []Options{
8037 WithUnmarshalers(new(Unmarshalers)),
8038 },
8039 inBuf: `""`,
8040 inVal: addr(""),
8041 want: addr(""),
8042 }, {
8043 name: jsontest.Name("Functions/String/Empty2/NoMatch"),
8044 opts: []Options{
8045 WithUnmarshalers(JoinUnmarshalers()),
8046 },
8047 inBuf: `""`,
8048 inVal: addr(""),
8049 want: addr(""),
8050 }, {
8051 name: jsontest.Name("Functions/String/V1/DirectError"),
8052 opts: []Options{
8053 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8054 return errSomeError
8055 })),
8056 },
8057 inBuf: `""`,
8058 inVal: addr(""),
8059 want: addr(""),
8060 wantErr: EU(errSomeError).withType('"', reflect.PointerTo(stringType)),
8061 }, {
8062 name: jsontest.Name("Functions/String/V1/SkipError"),
8063 opts: []Options{
8064 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8065 return errors.ErrUnsupported
8066 })),
8067 },
8068 inBuf: `""`,
8069 inVal: addr(""),
8070 want: addr(""),
8071 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "unmarshal function of type func([]byte, T) error")).withType('"', reflect.PointerTo(stringType)),
8072 }, {
8073 name: jsontest.Name("Functions/String/V2/DirectError"),
8074 opts: []Options{
8075 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8076 return errSomeError
8077 })),
8078 },
8079 inBuf: `""`,
8080 inVal: addr(""),
8081 want: addr(""),
8082 wantErr: EU(errSomeError).withType(0, reflect.PointerTo(stringType)),
8083 }, {
8084 name: jsontest.Name("Functions/String/V2/TooFew"),
8085 opts: []Options{
8086 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8087 return nil
8088 })),
8089 },
8090 inBuf: `""`,
8091 inVal: addr(""),
8092 want: addr(""),
8093 wantErr: EU(errNonSingularValue).withType(0, reflect.PointerTo(stringType)),
8094 }, {
8095 name: jsontest.Name("Functions/String/V2/TooMany"),
8096 opts: []Options{
8097 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8098 if _, err := dec.ReadValue(); err != nil {
8099 return err
8100 }
8101 if _, err := dec.ReadValue(); err != nil {
8102 return err
8103 }
8104 return nil
8105 })),
8106 },
8107 inBuf: `{"X":["",""]}`,
8108 inVal: addr(struct{ X []string }{}),
8109 want: addr(struct{ X []string }{[]string{""}}),
8110 wantErr: EU(errNonSingularValue).withPos(`{"X":["",`, "/X").withType(0, reflect.PointerTo(stringType)),
8111 }, {
8112 name: jsontest.Name("Functions/String/V2/Skipped"),
8113 opts: []Options{
8114 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8115 return errors.ErrUnsupported
8116 })),
8117 },
8118 inBuf: `""`,
8119 inVal: addr(""),
8120 want: addr(""),
8121 }, {
8122 name: jsontest.Name("Functions/String/V2/ProcessBeforeSkip"),
8123 opts: []Options{
8124 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8125 if _, err := dec.ReadValue(); err != nil {
8126 return err
8127 }
8128 return errors.ErrUnsupported
8129 })),
8130 },
8131 inBuf: `""`,
8132 inVal: addr(""),
8133 want: addr(""),
8134 wantErr: EU(errUnsupportedMutation).withType(0, reflect.PointerTo(stringType)),
8135 }, {
8136 name: jsontest.Name("Functions/String/V2/WrappedUnsupported"),
8137 opts: []Options{
8138 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8139 return fmt.Errorf("wrap: %w", errors.ErrUnsupported)
8140 })),
8141 },
8142 inBuf: `""`,
8143 inVal: addr(""),
8144 want: addr(""),
8145 }, {
8146 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
8147 opts: []Options{
8148 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8149 if string(b) != `"hello"` {
8150 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8151 }
8152 *v = "called"
8153 return nil
8154 })),
8155 },
8156 inBuf: `{"hello":"world"}`,
8157 inVal: addr(map[nocaseString]string{}),
8158 want: addr(map[nocaseString]string{"called": "world"}),
8159 }, {
8160 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
8161 opts: []Options{
8162 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8163 if string(b) != `"hello"` {
8164 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8165 }
8166 *v.(*nocaseString) = "called"
8167 return nil
8168 })),
8169 },
8170 inBuf: `{"hello":"world"}`,
8171 inVal: addr(map[nocaseString]string{}),
8172 want: addr(map[nocaseString]string{"called": "world"}),
8173 }, {
8174 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
8175 opts: []Options{
8176 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8177 switch t, err := dec.ReadToken(); {
8178 case err != nil:
8179 return err
8180 case t.String() != "hello":
8181 return fmt.Errorf("got %q, want %q", t, "hello")
8182 }
8183 *v = "called"
8184 return nil
8185 })),
8186 },
8187 inBuf: `{"hello":"world"}`,
8188 inVal: addr(map[nocaseString]string{}),
8189 want: addr(map[nocaseString]string{"called": "world"}),
8190 }, {
8191 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
8192 opts: []Options{
8193 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8194 switch b, err := dec.ReadValue(); {
8195 case err != nil:
8196 return err
8197 case string(b) != `"hello"`:
8198 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8199 }
8200 *v.(*nocaseString) = "called"
8201 return nil
8202 })),
8203 },
8204 inBuf: `{"hello":"world"}`,
8205 inVal: addr(map[nocaseString]string{}),
8206 want: addr(map[nocaseString]string{"called": "world"}),
8207 }, {
8208 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
8209 opts: []Options{
8210 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8211 if _, err := dec.ReadValue(); err != nil {
8212 return err
8213 }
8214 xd := export.Decoder(dec)
8215 *v = fmt.Sprintf("%d-%d", len(xd.Tokens.Stack), xd.Tokens.Last.Length())
8216 return nil
8217 })),
8218 },
8219 inBuf: `{"name":"value","name":"value"}`,
8220 inVal: addr(map[string]string{}),
8221 want: addr(map[string]string{"1-1": "1-2"}),
8222 wantErr: newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"value",`)),
8223 }, {
8224 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
8225 opts: []Options{
8226 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8227 if string(b) != `"world"` {
8228 return fmt.Errorf("got %s, want %s", b, `"world"`)
8229 }
8230 *v = "called"
8231 return nil
8232 })),
8233 },
8234 inBuf: `{"hello":"world"}`,
8235 inVal: addr(map[string]nocaseString{}),
8236 want: addr(map[string]nocaseString{"hello": "called"}),
8237 }, {
8238 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
8239 opts: []Options{
8240 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8241 if string(b) != `"world"` {
8242 return fmt.Errorf("got %s, want %s", b, `"world"`)
8243 }
8244 *v.(*nocaseString) = "called"
8245 return nil
8246 })),
8247 },
8248 inBuf: `{"hello":"world"}`,
8249 inVal: addr(map[string]nocaseString{}),
8250 want: addr(map[string]nocaseString{"hello": "called"}),
8251 }, {
8252 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
8253 opts: []Options{
8254 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8255 switch t, err := dec.ReadToken(); {
8256 case err != nil:
8257 return err
8258 case t.String() != "world":
8259 return fmt.Errorf("got %q, want %q", t, "world")
8260 }
8261 *v = "called"
8262 return nil
8263 })),
8264 },
8265 inBuf: `{"hello":"world"}`,
8266 inVal: addr(map[string]nocaseString{}),
8267 want: addr(map[string]nocaseString{"hello": "called"}),
8268 }, {
8269 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
8270 opts: []Options{
8271 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8272 switch b, err := dec.ReadValue(); {
8273 case err != nil:
8274 return err
8275 case string(b) != `"world"`:
8276 return fmt.Errorf("got %s, want %s", b, `"world"`)
8277 }
8278 *v.(*nocaseString) = "called"
8279 return nil
8280 })),
8281 },
8282 inBuf: `{"hello":"world"}`,
8283 inVal: addr(map[string]nocaseString{}),
8284 want: addr(map[string]nocaseString{"hello": "called"}),
8285 }, {
8286 name: jsontest.Name("Funtions/Struct/Fields"),
8287 opts: []Options{
8288 WithUnmarshalers(JoinUnmarshalers(
8289 UnmarshalFunc(func(b []byte, v *bool) error {
8290 if string(b) != `"called1"` {
8291 return fmt.Errorf("got %s, want %s", b, `"called1"`)
8292 }
8293 *v = true
8294 return nil
8295 }),
8296 UnmarshalFunc(func(b []byte, v *string) error {
8297 if string(b) != `"called2"` {
8298 return fmt.Errorf("got %s, want %s", b, `"called2"`)
8299 }
8300 *v = "called2"
8301 return nil
8302 }),
8303 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[]byte) error {
8304 switch t, err := dec.ReadToken(); {
8305 case err != nil:
8306 return err
8307 case t.String() != "called3":
8308 return fmt.Errorf("got %q, want %q", t, "called3")
8309 }
8310 *v = []byte("called3")
8311 return nil
8312 }),
8313 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *int64) error {
8314 switch b, err := dec.ReadValue(); {
8315 case err != nil:
8316 return err
8317 case string(b) != `"called4"`:
8318 return fmt.Errorf("got %s, want %s", b, `"called4"`)
8319 }
8320 *v = 123
8321 return nil
8322 }),
8323 )),
8324 },
8325 inBuf: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":456,"Float":789}`,
8326 inVal: addr(structScalars{}),
8327 want: addr(structScalars{Bool: true, String: "called2", Bytes: []byte("called3"), Int: 123, Uint: 456, Float: 789}),
8328 }, {
8329 name: jsontest.Name("Functions/Struct/Inlined"),
8330 opts: []Options{
8331 WithUnmarshalers(JoinUnmarshalers(
8332 UnmarshalFunc(func([]byte, *structInlinedL1) error {
8333 panic("should not be called")
8334 }),
8335 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *StructEmbed2) error {
8336 panic("should not be called")
8337 }),
8338 )),
8339 },
8340 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
8341 inVal: new(structInlined),
8342 want: addr(structInlined{
8343 X: structInlinedL1{
8344 X: &structInlinedL2{A: "A1", B: "B1" },
8345 StructEmbed1: StructEmbed1{ D: "D2" },
8346 },
8347 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
8348 }),
8349 }, {
8350 name: jsontest.Name("Functions/Slice/Elem"),
8351 opts: []Options{
8352 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8353 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8354 return nil
8355 })),
8356 },
8357 inBuf: `["hello","World"]`,
8358 inVal: addr([]string{}),
8359 want: addr([]string{"HELLO", "WORLD"}),
8360 }, {
8361 name: jsontest.Name("Functions/Array/Elem"),
8362 opts: []Options{
8363 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8364 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8365 return nil
8366 })),
8367 },
8368 inBuf: `["hello","World"]`,
8369 inVal: addr([2]string{}),
8370 want: addr([2]string{"HELLO", "WORLD"}),
8371 }, {
8372 name: jsontest.Name("Functions/Pointer/Nil"),
8373 opts: []Options{
8374 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8375 t, err := dec.ReadToken()
8376 *v = strings.ToUpper(t.String())
8377 return err
8378 })),
8379 },
8380 inBuf: `{"X":"hello"}`,
8381 inVal: addr(struct{ X *string }{nil}),
8382 want: addr(struct{ X *string }{addr("HELLO")}),
8383 }, {
8384 name: jsontest.Name("Functions/Pointer/NonNil"),
8385 opts: []Options{
8386 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8387 t, err := dec.ReadToken()
8388 *v = strings.ToUpper(t.String())
8389 return err
8390 })),
8391 },
8392 inBuf: `{"X":"hello"}`,
8393 inVal: addr(struct{ X *string }{addr("")}),
8394 want: addr(struct{ X *string }{addr("HELLO")}),
8395 }, {
8396 name: jsontest.Name("Functions/Interface/Nil"),
8397 opts: []Options{
8398 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v fmt.Stringer) error {
8399 panic("should not be called")
8400 })),
8401 },
8402 inBuf: `{"X":"hello"}`,
8403 inVal: addr(struct{ X fmt.Stringer }{nil}),
8404 want: addr(struct{ X fmt.Stringer }{nil}),
8405 wantErr: EU(internal.ErrNilInterface).withPos(`{"X":`, "/X").withType(0, T[fmt.Stringer]()),
8406 }, {
8407 name: jsontest.Name("Functions/Interface/NetIP"),
8408 opts: []Options{
8409 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8410 *v = net.IP{}
8411 return errors.ErrUnsupported
8412 })),
8413 },
8414 inBuf: `{"X":"1.1.1.1"}`,
8415 inVal: addr(struct{ X fmt.Stringer }{nil}),
8416 want: addr(struct{ X fmt.Stringer }{net.IPv4(1, 1, 1, 1)}),
8417 }, {
8418 name: jsontest.Name("Functions/Interface/NewPointerNetIP"),
8419 opts: []Options{
8420 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8421 *v = new(net.IP)
8422 return errors.ErrUnsupported
8423 })),
8424 },
8425 inBuf: `{"X":"1.1.1.1"}`,
8426 inVal: addr(struct{ X fmt.Stringer }{nil}),
8427 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}),
8428 }, {
8429 name: jsontest.Name("Functions/Interface/NilPointerNetIP"),
8430 opts: []Options{
8431 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8432 *v = (*net.IP)(nil)
8433 return errors.ErrUnsupported
8434 })),
8435 },
8436 inBuf: `{"X":"1.1.1.1"}`,
8437 inVal: addr(struct{ X fmt.Stringer }{nil}),
8438 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}),
8439 }, {
8440 name: jsontest.Name("Functions/Interface/NilPointerNetIP/Override"),
8441 opts: []Options{
8442 WithUnmarshalers(JoinUnmarshalers(
8443 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8444 *v = (*net.IP)(nil)
8445 return errors.ErrUnsupported
8446 }),
8447 UnmarshalFunc(func(b []byte, v *net.IP) error {
8448 b = bytes.ReplaceAll(b, []byte(`1`), []byte(`8`))
8449 return v.UnmarshalText(bytes.Trim(b, `"`))
8450 }),
8451 )),
8452 },
8453 inBuf: `{"X":"1.1.1.1"}`,
8454 inVal: addr(struct{ X fmt.Stringer }{nil}),
8455 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(8, 8, 8, 8))}),
8456 }, {
8457 name: jsontest.Name("Functions/Interface/Any"),
8458 inBuf: `[null,{},{},{},{},{},{},{},{},{},{},{},{},"LAST"]`,
8459 inVal: addr([...]any{
8460 nil,
8461 valueStringer{},
8462 (*valueStringer)(nil),
8463 addr(valueStringer{}),
8464 (**valueStringer)(nil),
8465 addr((*valueStringer)(nil)),
8466 addr(addr(valueStringer{})),
8467 pointerStringer{},
8468 (*pointerStringer)(nil),
8469 addr(pointerStringer{}),
8470 (**pointerStringer)(nil),
8471 addr((*pointerStringer)(nil)),
8472 addr(addr(pointerStringer{})),
8473 "LAST",
8474 }),
8475 opts: []Options{
8476 WithUnmarshalers(func() *Unmarshalers {
8477 type P struct {
8478 D int
8479 N int64
8480 }
8481 type PV struct {
8482 P P
8483 V any
8484 }
8485
8486 var lastChecks []func() error
8487 checkLast := func() error {
8488 for _, fn := range lastChecks {
8489 if err := fn(); err != nil {
8490 return err
8491 }
8492 }
8493 return errors.ErrUnsupported
8494 }
8495 makeValueChecker := func(name string, want []PV) func(d *jsontext.Decoder, v any) error {
8496 checkNext := func(d *jsontext.Decoder, v any) error {
8497 xd := export.Decoder(d)
8498 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8499 rv := reflect.ValueOf(v)
8500 pv := PV{p, v}
8501 switch {
8502 case len(want) == 0:
8503 return fmt.Errorf("%s: %v: got more values than expected", name, p)
8504 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
8505 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
8506 case !reflect.DeepEqual(pv, want[0]):
8507 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
8508 default:
8509 want = want[1:]
8510 return errors.ErrUnsupported
8511 }
8512 }
8513 lastChecks = append(lastChecks, func() error {
8514 if len(want) > 0 {
8515 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8516 }
8517 return nil
8518 })
8519 return checkNext
8520 }
8521 makePositionChecker := func(name string, want []P) func(d *jsontext.Decoder, v any) error {
8522 checkNext := func(d *jsontext.Decoder, v any) error {
8523 xd := export.Decoder(d)
8524 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8525 switch {
8526 case len(want) == 0:
8527 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
8528 case p != want[0]:
8529 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
8530 default:
8531 want = want[1:]
8532 return errors.ErrUnsupported
8533 }
8534 }
8535 lastChecks = append(lastChecks, func() error {
8536 if len(want) > 0 {
8537 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8538 }
8539 return nil
8540 })
8541 return checkNext
8542 }
8543
8544
8545
8546 wantAny := []PV{
8547 {P{1, 0}, addr(any(nil))},
8548 {P{1, 1}, addr(any(valueStringer{}))},
8549 {P{1, 1}, addr(valueStringer{})},
8550 {P{1, 2}, addr(any((*valueStringer)(nil)))},
8551 {P{1, 2}, addr((*valueStringer)(nil))},
8552 {P{1, 2}, addr(valueStringer{})},
8553 {P{1, 3}, addr(any(addr(valueStringer{})))},
8554 {P{1, 3}, addr(addr(valueStringer{}))},
8555 {P{1, 3}, addr(valueStringer{})},
8556 {P{1, 4}, addr(any((**valueStringer)(nil)))},
8557 {P{1, 4}, addr((**valueStringer)(nil))},
8558 {P{1, 4}, addr((*valueStringer)(nil))},
8559 {P{1, 4}, addr(valueStringer{})},
8560 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
8561 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
8562 {P{1, 5}, addr((*valueStringer)(nil))},
8563 {P{1, 5}, addr(valueStringer{})},
8564 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
8565 {P{1, 6}, addr(addr(addr(valueStringer{})))},
8566 {P{1, 6}, addr(addr(valueStringer{}))},
8567 {P{1, 6}, addr(valueStringer{})},
8568 {P{1, 7}, addr(any(pointerStringer{}))},
8569 {P{1, 7}, addr(pointerStringer{})},
8570 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
8571 {P{1, 8}, addr((*pointerStringer)(nil))},
8572 {P{1, 8}, addr(pointerStringer{})},
8573 {P{1, 9}, addr(any(addr(pointerStringer{})))},
8574 {P{1, 9}, addr(addr(pointerStringer{}))},
8575 {P{1, 9}, addr(pointerStringer{})},
8576 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
8577 {P{1, 10}, addr((**pointerStringer)(nil))},
8578 {P{1, 10}, addr((*pointerStringer)(nil))},
8579 {P{1, 10}, addr(pointerStringer{})},
8580 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
8581 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
8582 {P{1, 11}, addr((*pointerStringer)(nil))},
8583 {P{1, 11}, addr(pointerStringer{})},
8584 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
8585 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
8586 {P{1, 12}, addr(addr(pointerStringer{}))},
8587 {P{1, 12}, addr(pointerStringer{})},
8588 {P{1, 13}, addr(any("LAST"))},
8589 {P{1, 13}, addr("LAST")},
8590 }
8591 checkAny := makeValueChecker("any", wantAny)
8592 anyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v any) error {
8593 return checkAny(dec, v)
8594 })
8595
8596 var wantPointerAny []PV
8597 for _, v := range wantAny {
8598 if _, ok := v.V.(*any); ok {
8599 wantPointerAny = append(wantPointerAny, v)
8600 }
8601 }
8602 checkPointerAny := makeValueChecker("*any", wantPointerAny)
8603 pointerAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *any) error {
8604 return checkPointerAny(dec, v)
8605 })
8606
8607 checkNamedAny := makeValueChecker("namedAny", wantAny)
8608 namedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v namedAny) error {
8609 return checkNamedAny(dec, v)
8610 })
8611
8612 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
8613 pointerNamedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedAny) error {
8614 return checkPointerNamedAny(dec, v)
8615 })
8616
8617 type stringer = fmt.Stringer
8618 var wantStringer []PV
8619 for _, v := range wantAny {
8620 if _, ok := v.V.(stringer); ok {
8621 wantStringer = append(wantStringer, v)
8622 }
8623 }
8624 checkStringer := makeValueChecker("stringer", wantStringer)
8625 stringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v stringer) error {
8626 return checkStringer(dec, v)
8627 })
8628
8629 checkPointerStringer := makeValueChecker("*stringer", nil)
8630 pointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *stringer) error {
8631 return checkPointerStringer(dec, v)
8632 })
8633
8634 wantValueStringer := []P{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}}
8635 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
8636 pointerValueStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *valueStringer) error {
8637 return checkPointerValueStringer(dec, v)
8638 })
8639
8640 wantPointerStringer := []P{{1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}}
8641 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
8642 pointerPointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *pointerStringer) error {
8643 return checkPointerPointerStringer(dec, v)
8644 })
8645
8646 lastUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8647 return checkLast()
8648 })
8649
8650 return JoinUnmarshalers(
8651
8652
8653 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[14]any) error {
8654 if _, err := dec.ReadToken(); err != nil {
8655 return err
8656 }
8657 for i := range len(*v) {
8658 if err := UnmarshalDecode(dec, &(*v)[i]); err != nil {
8659 return err
8660 }
8661 }
8662 if _, err := dec.ReadToken(); err != nil {
8663 return err
8664 }
8665 return nil
8666 }),
8667
8668 anyUnmarshaler,
8669 pointerAnyUnmarshaler,
8670 namedAnyUnmarshaler,
8671 pointerNamedAnyUnmarshaler,
8672 stringerUnmarshaler,
8673 pointerStringerUnmarshaler,
8674 pointerValueStringerUnmarshaler,
8675 pointerPointerStringerUnmarshaler,
8676 lastUnmarshaler,
8677 )
8678 }()),
8679 },
8680 }, {
8681 name: jsontest.Name("Functions/Precedence/V1First"),
8682 opts: []Options{
8683 WithUnmarshalers(JoinUnmarshalers(
8684 UnmarshalFunc(func(b []byte, v *string) error {
8685 if string(b) != `"called"` {
8686 return fmt.Errorf("got %s, want %s", b, `"called"`)
8687 }
8688 *v = "called"
8689 return nil
8690 }),
8691 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8692 panic("should not be called")
8693 }),
8694 )),
8695 },
8696 inBuf: `"called"`,
8697 inVal: addr(""),
8698 want: addr("called"),
8699 }, {
8700 name: jsontest.Name("Functions/Precedence/V2First"),
8701 opts: []Options{
8702 WithUnmarshalers(JoinUnmarshalers(
8703 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8704 switch t, err := dec.ReadToken(); {
8705 case err != nil:
8706 return err
8707 case t.String() != "called":
8708 return fmt.Errorf("got %q, want %q", t, "called")
8709 }
8710 *v = "called"
8711 return nil
8712 }),
8713 UnmarshalFunc(func([]byte, *string) error {
8714 panic("should not be called")
8715 }),
8716 )),
8717 },
8718 inBuf: `"called"`,
8719 inVal: addr(""),
8720 want: addr("called"),
8721 }, {
8722 name: jsontest.Name("Functions/Precedence/V2Skipped"),
8723 opts: []Options{
8724 WithUnmarshalers(JoinUnmarshalers(
8725 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8726 return errors.ErrUnsupported
8727 }),
8728 UnmarshalFunc(func(b []byte, v *string) error {
8729 if string(b) != `"called"` {
8730 return fmt.Errorf("got %s, want %s", b, `"called"`)
8731 }
8732 *v = "called"
8733 return nil
8734 }),
8735 )),
8736 },
8737 inBuf: `"called"`,
8738 inVal: addr(""),
8739 want: addr("called"),
8740 }, {
8741 name: jsontest.Name("Functions/Precedence/NestedFirst"),
8742 opts: []Options{
8743 WithUnmarshalers(JoinUnmarshalers(
8744 JoinUnmarshalers(
8745 UnmarshalFunc(func(b []byte, v *string) error {
8746 if string(b) != `"called"` {
8747 return fmt.Errorf("got %s, want %s", b, `"called"`)
8748 }
8749 *v = "called"
8750 return nil
8751 }),
8752 ),
8753 UnmarshalFunc(func([]byte, *string) error {
8754 panic("should not be called")
8755 }),
8756 )),
8757 },
8758 inBuf: `"called"`,
8759 inVal: addr(""),
8760 want: addr("called"),
8761 }, {
8762 name: jsontest.Name("Functions/Precedence/NestedLast"),
8763 opts: []Options{
8764 WithUnmarshalers(JoinUnmarshalers(
8765 UnmarshalFunc(func(b []byte, v *string) error {
8766 if string(b) != `"called"` {
8767 return fmt.Errorf("got %s, want %s", b, `"called"`)
8768 }
8769 *v = "called"
8770 return nil
8771 }),
8772 JoinUnmarshalers(
8773 UnmarshalFunc(func([]byte, *string) error {
8774 panic("should not be called")
8775 }),
8776 ),
8777 )),
8778 },
8779 inBuf: `"called"`,
8780 inVal: addr(""),
8781 want: addr("called"),
8782 }, {
8783 name: jsontest.Name("Duration/Null"),
8784 inBuf: `{"D1":null,"D2":null}`,
8785 inVal: addr(struct {
8786 D1 time.Duration `json:",format:units"`
8787 D2 time.Duration `json:",format:nano"`
8788 }{1, 1}),
8789 want: addr(struct {
8790 D1 time.Duration `json:",format:units"`
8791 D2 time.Duration `json:",format:nano"`
8792 }{0, 0}),
8793 skip: !internal.ExpJSONFormat,
8794 }, {
8795 name: jsontest.Name("Duration/Zero"),
8796 inBuf: `{"D1":"0s","D2":0}`,
8797 inVal: addr(struct {
8798 D1 time.Duration `json:",format:units"`
8799 D2 time.Duration `json:",format:nano"`
8800 }{1, 1}),
8801 want: addr(struct {
8802 D1 time.Duration `json:",format:units"`
8803 D2 time.Duration `json:",format:nano"`
8804 }{0, 0}),
8805 skip: !internal.ExpJSONFormat,
8806 }, {
8807 name: jsontest.Name("Duration/Positive"),
8808 inBuf: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
8809 inVal: new(struct {
8810 D1 time.Duration `json:",format:units"`
8811 D2 time.Duration `json:",format:nano"`
8812 }),
8813 want: addr(struct {
8814 D1 time.Duration `json:",format:units"`
8815 D2 time.Duration `json:",format:nano"`
8816 }{
8817 123456789123456789,
8818 123456789123456789,
8819 }),
8820 skip: !internal.ExpJSONFormat,
8821 }, {
8822 name: jsontest.Name("Duration/Negative"),
8823 inBuf: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
8824 inVal: new(struct {
8825 D1 time.Duration `json:",format:units"`
8826 D2 time.Duration `json:",format:nano"`
8827 }),
8828 want: addr(struct {
8829 D1 time.Duration `json:",format:units"`
8830 D2 time.Duration `json:",format:nano"`
8831 }{
8832 -123456789123456789,
8833 -123456789123456789,
8834 }),
8835 skip: !internal.ExpJSONFormat,
8836 }, {
8837 name: jsontest.Name("Duration/Nanos/String"),
8838 inBuf: `{"D":"12345"}`,
8839 inVal: addr(struct {
8840 D time.Duration `json:",string,format:nano"`
8841 }{1}),
8842 want: addr(struct {
8843 D time.Duration `json:",string,format:nano"`
8844 }{12345}),
8845 skip: !internal.ExpJSONFormat,
8846 }, {
8847 name: jsontest.Name("Duration/Nanos/String/Invalid"),
8848 inBuf: `{"D":"+12345"}`,
8849 inVal: addr(struct {
8850 D time.Duration `json:",string,format:nano"`
8851 }{1}),
8852 want: addr(struct {
8853 D time.Duration `json:",string,format:nano"`
8854 }{1}),
8855 wantErr: EU(fmt.Errorf(`invalid duration "+12345": %w`, strconv.ErrSyntax)).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8856 skip: !internal.ExpJSONFormat,
8857 }, {
8858 name: jsontest.Name("Duration/Nanos/Mismatch"),
8859 inBuf: `{"D":"34293h33m9.123456789s"}`,
8860 inVal: addr(struct {
8861 D time.Duration `json:",format:nano"`
8862 }{1}),
8863 want: addr(struct {
8864 D time.Duration `json:",format:nano"`
8865 }{1}),
8866 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8867 skip: !internal.ExpJSONFormat,
8868 }, {
8869 name: jsontest.Name("Duration/Nanos"),
8870 inBuf: `{"D":1.324}`,
8871 inVal: addr(struct {
8872 D time.Duration `json:",format:nano"`
8873 }{-1}),
8874 want: addr(struct {
8875 D time.Duration `json:",format:nano"`
8876 }{1}),
8877 skip: !internal.ExpJSONFormat,
8878 }, {
8879 name: jsontest.Name("Duration/String/Mismatch"),
8880 inBuf: `{"D":-123456789123456789}`,
8881 inVal: addr(struct {
8882 D time.Duration `json:",format:units"`
8883 }{1}),
8884 want: addr(struct {
8885 D time.Duration `json:",format:units"`
8886 }{1}),
8887 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('0', timeDurationType),
8888 skip: !internal.ExpJSONFormat,
8889 }, {
8890 name: jsontest.Name("Duration/String/Invalid"),
8891 inBuf: `{"D":"5minkutes"}`,
8892 inVal: addr(struct {
8893 D time.Duration `json:",format:units"`
8894 }{1}),
8895 want: addr(struct {
8896 D time.Duration `json:",format:units"`
8897 }{1}),
8898 wantErr: EU(func() error {
8899 _, err := time.ParseDuration("5minkutes")
8900 return err
8901 }()).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8902 skip: !internal.ExpJSONFormat,
8903 }, {
8904 name: jsontest.Name("Duration/Syntax/Invalid"),
8905 inBuf: `{"D":x}`,
8906 inVal: addr(struct {
8907 D time.Duration `json:",format:units"`
8908 }{1}),
8909 want: addr(struct {
8910 D time.Duration `json:",format:units"`
8911 }{1}),
8912 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"D":`), "/D"),
8913 skip: !internal.ExpJSONFormat,
8914 }, {
8915 name: jsontest.Name("Duration/Format"),
8916 inBuf: `{
8917 "D1": "12h34m56.078090012s",
8918 "D2": "12h34m56.078090012s",
8919 "D3": 45296.078090012,
8920 "D4": "45296.078090012",
8921 "D5": 45296078.090012,
8922 "D6": "45296078.090012",
8923 "D7": 45296078090.012,
8924 "D8": "45296078090.012",
8925 "D9": 45296078090012,
8926 "D10": "45296078090012",
8927 "D11": "PT12H34M56.078090012S"
8928 }`,
8929 inVal: new(structDurationFormat),
8930 want: addr(structDurationFormat{
8931 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8932 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8933 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8934 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8935 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8936 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8937 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8938 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8939 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8940 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8941 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8942 }),
8943 skip: !internal.ExpJSONFormat,
8944 }, {
8945 name: jsontest.Name("Duration/Format/Invalid"),
8946 inBuf: `{"D":"0s"}`,
8947 inVal: addr(struct {
8948 D time.Duration `json:",format:invalid"`
8949 }{1}),
8950 want: addr(struct {
8951 D time.Duration `json:",format:invalid"`
8952 }{1}),
8953 wantErr: EU(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, timeDurationType),
8954 skip: !internal.ExpJSONFormat,
8955 }, {
8956
8966
8972 name: jsontest.Name("Duration/MapKey/Legacy"),
8973 opts: []Options{jsonflags.FormatDurationAsNano | 1},
8974 inBuf: `{"1000000000":""}`,
8975 inVal: new(map[time.Duration]string),
8976 want: addr(map[time.Duration]string{time.Second: ""}),
8977 skip: !internal.ExpJSONFormat,
8978 }, {
8979
8986 name: jsontest.Name("Time/Zero"),
8987 inBuf: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T4":"0001-01-01T00:00:00Z","T5":"0001-01-01T00:00:00Z"}`,
8988 inVal: new(struct {
8989 T1 time.Time
8990 T2 time.Time `json:",format:RFC822"`
8991 T3 time.Time `json:",format:'2006-01-02'"`
8992 T4 time.Time `json:",omitzero"`
8993 T5 time.Time `json:",omitempty"`
8994 }),
8995 want: addr(struct {
8996 T1 time.Time
8997 T2 time.Time `json:",format:RFC822"`
8998 T3 time.Time `json:",format:'2006-01-02'"`
8999 T4 time.Time `json:",omitzero"`
9000 T5 time.Time `json:",omitempty"`
9001 }{
9002 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
9003 mustParseTime(time.RFC822, "01 Jan 01 00:00 UTC"),
9004 mustParseTime("2006-01-02", "0001-01-01"),
9005 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
9006 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
9007 }),
9008 skip: !internal.ExpJSONFormat,
9009 }, {
9010 name: jsontest.Name("Time/Format"),
9011 inBuf: `{
9012 "T1": "1234-01-02T03:04:05.000000006Z",
9013 "T2": "Mon Jan 2 03:04:05 1234",
9014 "T3": "Mon Jan 2 03:04:05 UTC 1234",
9015 "T4": "Mon Jan 02 03:04:05 +0000 1234",
9016 "T5": "02 Jan 34 03:04 UTC",
9017 "T6": "02 Jan 34 03:04 +0000",
9018 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
9019 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
9020 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
9021 "T10": "1234-01-02T03:04:05Z",
9022 "T11": "1234-01-02T03:04:05.000000006Z",
9023 "T12": "3:04AM",
9024 "T13": "Jan 2 03:04:05",
9025 "T14": "Jan 2 03:04:05.000",
9026 "T15": "Jan 2 03:04:05.000000",
9027 "T16": "Jan 2 03:04:05.000000006",
9028 "T17": "1234-01-02 03:04:05",
9029 "T18": "1234-01-02",
9030 "T19": "03:04:05",
9031 "T20": "1234-01-02",
9032 "T21": "\"weird\"1234",
9033 "T22": -23225777754.999999994,
9034 "T23": "-23225777754.999999994",
9035 "T24": -23225777754999.999994,
9036 "T25": "-23225777754999.999994",
9037 "T26": -23225777754999999.994,
9038 "T27": "-23225777754999999.994",
9039 "T28": -23225777754999999994,
9040 "T29": "-23225777754999999994"
9041 }`,
9042 inVal: new(structTimeFormat),
9043 want: addr(structTimeFormat{
9044 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9045 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9046 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9047 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9048 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9049 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9050 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9051 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9052 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9053 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9054 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9055 mustParseTime(time.Kitchen, "3:04AM"),
9056 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9057 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9058 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9059 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9060 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9061 mustParseTime(time.DateOnly, "1234-01-02"),
9062 mustParseTime(time.TimeOnly, "03:04:05"),
9063 mustParseTime("2006-01-02", "1234-01-02"),
9064 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9065 time.Unix(-23225777755, 6).UTC(),
9066 time.Unix(-23225777755, 6).UTC(),
9067 time.Unix(-23225777755, 6).UTC(),
9068 time.Unix(-23225777755, 6).UTC(),
9069 time.Unix(-23225777755, 6).UTC(),
9070 time.Unix(-23225777755, 6).UTC(),
9071 time.Unix(-23225777755, 6).UTC(),
9072 time.Unix(-23225777755, 6).UTC(),
9073 }),
9074 skip: !internal.ExpJSONFormat,
9075 }, {
9076 name: jsontest.Name("Time/Format/UnixString/InvalidNumber"),
9077 inBuf: `{
9078 "T23": -23225777754.999999994,
9079 "T25": -23225777754999.999994,
9080 "T27": -23225777754999999.994,
9081 "T29": -23225777754999999994
9082 }`,
9083 inVal: new(structTimeFormat),
9084 want: new(structTimeFormat),
9085 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T23": `, "/T23").withType('0', timeTimeType),
9086 skip: !internal.ExpJSONFormat,
9087 }, {
9088 name: jsontest.Name("Time/Format/UnixString/InvalidString"),
9089 inBuf: `{
9090 "T22": "-23225777754.999999994",
9091 "T24": "-23225777754999.999994",
9092 "T26": "-23225777754999999.994",
9093 "T28": "-23225777754999999994"
9094 }`,
9095 inVal: new(structTimeFormat),
9096 want: new(structTimeFormat),
9097 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T22": `, "/T22").withType('"', timeTimeType),
9098 skip: !internal.ExpJSONFormat,
9099 }, {
9100 name: jsontest.Name("Time/Format/Null"),
9101 inBuf: `{"T1":null,"T2":null,"T3":null,"T4":null,"T5":null,"T6":null,"T7":null,"T8":null,"T9":null,"T10":null,"T11":null,"T12":null,"T13":null,"T14":null,"T15":null,"T16":null,"T17":null,"T18":null,"T19":null,"T20":null,"T21":null,"T22":null,"T23":null,"T24":null,"T25":null,"T26":null,"T27":null,"T28":null,"T29":null}`,
9102 inVal: addr(structTimeFormat{
9103 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9104 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9105 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9106 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9107 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9108 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9109 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9110 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9111 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9112 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9113 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9114 mustParseTime(time.Kitchen, "3:04AM"),
9115 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9116 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9117 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9118 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9119 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9120 mustParseTime(time.DateOnly, "1234-01-02"),
9121 mustParseTime(time.TimeOnly, "03:04:05"),
9122 mustParseTime("2006-01-02", "1234-01-02"),
9123 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9124 time.Unix(-23225777755, 6).UTC(),
9125 time.Unix(-23225777755, 6).UTC(),
9126 time.Unix(-23225777755, 6).UTC(),
9127 time.Unix(-23225777755, 6).UTC(),
9128 time.Unix(-23225777755, 6).UTC(),
9129 time.Unix(-23225777755, 6).UTC(),
9130 time.Unix(-23225777755, 6).UTC(),
9131 time.Unix(-23225777755, 6).UTC(),
9132 }),
9133 want: new(structTimeFormat),
9134 skip: !internal.ExpJSONFormat,
9135 }, {
9136 name: jsontest.Name("Time/RFC3339/Mismatch"),
9137 inBuf: `{"T":1234}`,
9138 inVal: new(struct {
9139 T time.Time
9140 }),
9141 wantErr: EU(nil).withPos(`{"T":`, "/T").withType('0', timeTimeType),
9142 }, {
9143 name: jsontest.Name("Time/RFC3339/ParseError"),
9144 inBuf: `{"T":"2021-09-29T12:44:52"}`,
9145 inVal: new(struct {
9146 T time.Time
9147 }),
9148 wantErr: EU(func() error {
9149 _, err := time.Parse(time.RFC3339, "2021-09-29T12:44:52")
9150 return err
9151 }()).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9152 }, {
9153 name: jsontest.Name("Time/Format/Invalid"),
9154 inBuf: `{"T":""}`,
9155 inVal: new(struct {
9156 T time.Time `json:",format:UndefinedConstant"`
9157 }),
9158 wantErr: EU(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
9159 skip: !internal.ExpJSONFormat,
9160 }, {
9161 name: jsontest.Name("Time/Format/SingleDigitHour"),
9162 inBuf: `{"T":"2000-01-01T1:12:34Z"}`,
9163 inVal: new(struct{ T time.Time }),
9164 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T1:12:34Z", "15", "1", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9165 }, {
9166 name: jsontest.Name("Time/Format/SubsecondComma"),
9167 inBuf: `{"T":"2000-01-01T00:00:00,000Z"}`,
9168 inVal: new(struct{ T time.Time }),
9169 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00,000Z", ".", ",", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9170 }, {
9171 name: jsontest.Name("Time/Format/TimezoneHourOverflow"),
9172 inBuf: `{"T":"2000-01-01T00:00:00+24:00"}`,
9173 inVal: new(struct{ T time.Time }),
9174 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00+24:00", "Z07:00", "+24:00", ": timezone hour out of range")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9175 }, {
9176 name: jsontest.Name("Time/Format/TimezoneMinuteOverflow"),
9177 inBuf: `{"T":"2000-01-01T00:00:00+00:60"}`,
9178 inVal: new(struct{ T time.Time }),
9179 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00+00:60", "Z07:00", "+00:60", ": timezone minute out of range")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9180 }, {
9181 name: jsontest.Name("Time/Syntax/Invalid"),
9182 inBuf: `{"T":x}`,
9183 inVal: new(struct {
9184 T time.Time
9185 }),
9186 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"T":`), "/T"),
9187 }, {
9188 name: jsontest.Name("Time/IgnoreInvalidFormat"),
9189 opts: []Options{invalidFormatOption},
9190 inBuf: `"2000-01-01T00:00:00Z"`,
9191 inVal: addr(time.Time{}),
9192 want: addr(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)),
9193 }}
9194
9195 for _, tt := range tests {
9196 if tt.skip {
9197 continue
9198 }
9199 t.Run(tt.name.Name, func(t *testing.T) {
9200 got := tt.inVal
9201 gotErr := Unmarshal([]byte(tt.inBuf), got, tt.opts...)
9202 if !reflect.DeepEqual(got, tt.want) && tt.want != nil {
9203 t.Errorf("%s: Unmarshal output mismatch:\ngot %v\nwant %v", tt.name.Where, got, tt.want)
9204 }
9205 if !reflect.DeepEqual(gotErr, tt.wantErr) {
9206 t.Errorf("%s: Unmarshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
9207 }
9208 })
9209 }
9210 }
9211
9212 func TestMarshalInvalidNamespace(t *testing.T) {
9213 tests := []struct {
9214 name jsontest.CaseName
9215 val any
9216 }{
9217 {jsontest.Name("Map"), map[string]string{"X": "\xde\xad\xbe\xef"}},
9218 {jsontest.Name("Struct"), struct{ X string }{"\xde\xad\xbe\xef"}},
9219 }
9220 for _, tt := range tests {
9221 t.Run(tt.name.Name, func(t *testing.T) {
9222 enc := jsontext.NewEncoder(new(bytes.Buffer))
9223 if err := MarshalEncode(enc, tt.val); err == nil {
9224 t.Fatalf("%s: MarshalEncode error is nil, want non-nil", tt.name.Where)
9225 }
9226 for _, tok := range []jsontext.Token{
9227 jsontext.Null, jsontext.String(""), jsontext.Int(0), jsontext.BeginObject, jsontext.EndObject, jsontext.BeginArray, jsontext.EndArray,
9228 } {
9229 if err := enc.WriteToken(tok); err == nil {
9230 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9231 }
9232 }
9233 for _, val := range []string{`null`, `""`, `0`, `{}`, `[]`} {
9234 if err := enc.WriteValue([]byte(val)); err == nil {
9235 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9236 }
9237 }
9238 })
9239 }
9240 }
9241
9242 func TestUnmarshalInvalidNamespace(t *testing.T) {
9243 tests := []struct {
9244 name jsontest.CaseName
9245 val any
9246 }{
9247 {jsontest.Name("Map"), addr(map[string]int{})},
9248 {jsontest.Name("Struct"), addr(struct{ X int }{})},
9249 }
9250 for _, tt := range tests {
9251 t.Run(tt.name.Name, func(t *testing.T) {
9252 dec := jsontext.NewDecoder(strings.NewReader(`{"X":""}`))
9253 if err := UnmarshalDecode(dec, tt.val); err == nil {
9254 t.Fatalf("%s: UnmarshalDecode error is nil, want non-nil", tt.name.Where)
9255 }
9256 if _, err := dec.ReadToken(); err == nil {
9257 t.Fatalf("%s: ReadToken error is nil, want non-nil", tt.name.Where)
9258 }
9259 if _, err := dec.ReadValue(); err == nil {
9260 t.Fatalf("%s: ReadValue error is nil, want non-nil", tt.name.Where)
9261 }
9262 })
9263 }
9264 }
9265
9266 func TestUnmarshalReuse(t *testing.T) {
9267 t.Run("Bytes", func(t *testing.T) {
9268 in := make([]byte, 3)
9269 want := &in[0]
9270 if err := Unmarshal([]byte(`"AQID"`), &in); err != nil {
9271 t.Fatalf("Unmarshal error: %v", err)
9272 }
9273 got := &in[0]
9274 if got != want {
9275 t.Errorf("input buffer was not reused")
9276 }
9277 })
9278 t.Run("Slices", func(t *testing.T) {
9279 in := make([]int, 3)
9280 want := &in[0]
9281 if err := Unmarshal([]byte(`[0,1,2]`), &in); err != nil {
9282 t.Fatalf("Unmarshal error: %v", err)
9283 }
9284 got := &in[0]
9285 if got != want {
9286 t.Errorf("input slice was not reused")
9287 }
9288 })
9289 t.Run("Maps", func(t *testing.T) {
9290 in := make(map[string]string)
9291 want := reflect.ValueOf(in).Pointer()
9292 if err := Unmarshal([]byte(`{"key":"value"}`), &in); err != nil {
9293 t.Fatalf("Unmarshal error: %v", err)
9294 }
9295 got := reflect.ValueOf(in).Pointer()
9296 if got != want {
9297 t.Errorf("input map was not reused")
9298 }
9299 })
9300 t.Run("Pointers", func(t *testing.T) {
9301 in := addr(addr(addr("hello")))
9302 want := **in
9303 if err := Unmarshal([]byte(`"goodbye"`), &in); err != nil {
9304 t.Fatalf("Unmarshal error: %v", err)
9305 }
9306 got := **in
9307 if got != want {
9308 t.Errorf("input pointer was not reused")
9309 }
9310 })
9311 }
9312
9313 type unmarshalerEOF struct{}
9314
9315 func (unmarshalerEOF) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
9316 return io.EOF
9317 }
9318
9319
9320
9321 func TestUnmarshalEOF(t *testing.T) {
9322 opts := WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ *struct{}) error {
9323 return io.EOF
9324 }))
9325
9326 for _, in := range []string{"", "[", "[null", "[null]"} {
9327 for _, newOut := range []func() any{
9328 func() any { return new(unmarshalerEOF) },
9329 func() any { return new([]unmarshalerEOF) },
9330 func() any { return new(struct{}) },
9331 func() any { return new([]struct{}) },
9332 } {
9333 wantErr := io.ErrUnexpectedEOF
9334 if gotErr := Unmarshal([]byte(in), newOut(), opts); !errors.Is(gotErr, wantErr) {
9335 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9336 }
9337 if gotErr := UnmarshalRead(strings.NewReader(in), newOut(), opts); !errors.Is(gotErr, wantErr) {
9338 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9339 }
9340 switch gotErr := UnmarshalDecode(jsontext.NewDecoder(strings.NewReader(in)), newOut(), opts); {
9341 case in != "" && !errors.Is(gotErr, wantErr):
9342 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9343 case in == "" && gotErr != io.EOF:
9344 t.Errorf("Unmarshal = %v, want %v", gotErr, io.EOF)
9345 }
9346 }
9347 }
9348 }
9349
9350 type ReaderFunc func([]byte) (int, error)
9351
9352 func (f ReaderFunc) Read(b []byte) (int, error) { return f(b) }
9353
9354 type WriterFunc func([]byte) (int, error)
9355
9356 func (f WriterFunc) Write(b []byte) (int, error) { return f(b) }
9357
9358 func TestCoderBufferGrowth(t *testing.T) {
9359
9360
9361 checkGrowth := func(ns []int) {
9362 t.Helper()
9363 var sumBytes, sumRates, numGrows float64
9364 prev := ns[0]
9365 for i := 1; i < len(ns)-1; i++ {
9366 n := ns[i]
9367 if n != prev {
9368 sumRates += float64(n) / float64(prev)
9369 numGrows++
9370 prev = n
9371 }
9372 if n > 1<<20 {
9373 t.Fatalf("single Read/Write too large: %d", n)
9374 }
9375 sumBytes += float64(n)
9376 }
9377 if mean := sumBytes / float64(len(ns)); mean < 1<<10 {
9378 t.Fatalf("average Read/Write too small: %0.1f", mean)
9379 }
9380 switch mean := sumRates / numGrows; {
9381 case mean < 1.25:
9382 t.Fatalf("average growth rate too slow: %0.3f", mean)
9383 case mean > 2.00:
9384 t.Fatalf("average growth rate too fast: %0.3f", mean)
9385 }
9386 }
9387
9388
9389
9390 bb := struct{ *bytes.Buffer }{new(bytes.Buffer)}
9391
9392 var writeSizes []int
9393 if err := MarshalWrite(WriterFunc(func(b []byte) (int, error) {
9394 n, err := bb.Write(b)
9395 writeSizes = append(writeSizes, n)
9396 return n, err
9397 }), make([]struct{}, 1e6)); err != nil {
9398 t.Fatalf("MarshalWrite error: %v", err)
9399 }
9400 checkGrowth(writeSizes)
9401
9402 var readSizes []int
9403 if err := UnmarshalRead(ReaderFunc(func(b []byte) (int, error) {
9404 n, err := bb.Read(b)
9405 readSizes = append(readSizes, n)
9406 return n, err
9407 }), new([]struct{})); err != nil {
9408 t.Fatalf("UnmarshalRead error: %v", err)
9409 }
9410 checkGrowth(readSizes)
9411 }
9412
9413 func TestUintSet(t *testing.T) {
9414 type operation any
9415 type has struct {
9416 in uint
9417 want bool
9418 }
9419 type insert struct {
9420 in uint
9421 want bool
9422 }
9423
9424
9425 ops := []operation{
9426 has{0, false},
9427 has{63, false},
9428 has{64, false},
9429 has{1234, false},
9430 insert{3, true},
9431 has{2, false},
9432 has{3, true},
9433 has{4, false},
9434 has{63, false},
9435 insert{3, false},
9436 insert{63, true},
9437 has{63, true},
9438 insert{64, true},
9439 insert{64, false},
9440 has{64, true},
9441 insert{3264, true},
9442 has{3264, true},
9443 insert{3, false},
9444 has{3, true},
9445 }
9446
9447 var us uintSet
9448 for i, op := range ops {
9449 switch op := op.(type) {
9450 case has:
9451 if got := us.has(op.in); got != op.want {
9452 t.Fatalf("%d: uintSet.has(%v) = %v, want %v", i, op.in, got, op.want)
9453 }
9454 case insert:
9455 if got := us.insert(op.in); got != op.want {
9456 t.Fatalf("%d: uintSet.insert(%v) = %v, want %v", i, op.in, got, op.want)
9457 }
9458 default:
9459 panic(fmt.Sprintf("unknown operation: %T", op))
9460 }
9461 }
9462 }
9463
9464 func TestUnmarshalDecodeOptions(t *testing.T) {
9465 var calledFuncs int
9466 var calledOptions Options
9467 in := strings.NewReader(strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9468 dec := jsontext.NewDecoder(in,
9469 jsontext.AllowInvalidUTF8(true),
9470 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ any) error {
9471 opts := dec.Options()
9472 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9473 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9474 }
9475 calledFuncs++
9476 calledOptions = opts
9477 return errors.ErrUnsupported
9478 })),
9479 )
9480
9481 if err := UnmarshalDecode(dec, new(string)); err != nil {
9482 t.Fatalf("UnmarshalDecode: %v", err)
9483 }
9484 if calledFuncs != 1 {
9485 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9486 }
9487 if err := UnmarshalDecode(dec, new(string), calledOptions); err != nil {
9488 t.Fatalf("UnmarshalDecode: %v", err)
9489 }
9490 if calledFuncs != 2 {
9491 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9492 }
9493 if err := UnmarshalDecode(dec, new(string),
9494 jsontext.AllowInvalidUTF8(false),
9495 WithUnmarshalers(nil),
9496 ); err != nil {
9497 t.Fatalf("UnmarshalDecode: %v", err)
9498 }
9499 if calledFuncs != 2 {
9500 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9501 }
9502 if err := UnmarshalDecode(dec, new(string)); err != nil {
9503 t.Fatalf("UnmarshalDecode: %v", err)
9504 }
9505 if calledFuncs != 3 {
9506 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9507 }
9508 if err := UnmarshalDecode(dec, new(string), JoinOptions(
9509 jsontext.AllowInvalidUTF8(false),
9510 WithUnmarshalers(UnmarshalFromFunc(func(_ *jsontext.Decoder, _ any) error {
9511 opts := dec.Options()
9512 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9513 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9514 }
9515 calledFuncs = math.MaxInt
9516 return errors.ErrUnsupported
9517 })),
9518 )); err != nil {
9519 t.Fatalf("UnmarshalDecode: %v", err)
9520 }
9521 if calledFuncs != math.MaxInt {
9522 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9523 }
9524
9525
9526
9527 opts := dec.Options()
9528 dec.Reset(in, jsontext.AllowInvalidUTF8(false), opts)
9529 if v, _ := GetOption(dec.Options(), jsontext.AllowInvalidUTF8); v == false {
9530 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9531 }
9532 }
9533
9534 func TestUnmarshalDecodeStream(t *testing.T) {
9535 tests := []struct {
9536 in string
9537 want []any
9538 err error
9539 }{
9540 {in: ``, err: io.EOF},
9541 {in: `{`, err: &jsontext.SyntacticError{ByteOffset: len64(`{`), Err: io.ErrUnexpectedEOF}},
9542 {in: `{"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"`), Err: io.ErrUnexpectedEOF}},
9543 {in: `{"k"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9544 {in: `{"k":`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k":`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9545 {in: `{"k",`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError(",", "after object name (expecting ':')")}},
9546 {in: `{"k"}`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError("}", "after object name (expecting ':')")}},
9547 {in: `[`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), Err: io.ErrUnexpectedEOF}},
9548 {in: `[0`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: io.ErrUnexpectedEOF}},
9549 {in: ` [0`, err: &jsontext.SyntacticError{ByteOffset: len64(` [0`), Err: io.ErrUnexpectedEOF}},
9550 {in: `[0.`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), JSONPointer: "/0", Err: io.ErrUnexpectedEOF}},
9551 {in: `[0. `, err: &jsontext.SyntacticError{ByteOffset: len64(`[0.`), JSONPointer: "/0", Err: jsonwire.NewInvalidCharacterError(" ", "in number (expecting digit)")}},
9552 {in: `[0,`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0,`), Err: io.ErrUnexpectedEOF}},
9553 {in: `[0:`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: jsonwire.NewInvalidCharacterError(":", "after array element (expecting ',' or ']')")}},
9554 {in: `n`, err: &jsontext.SyntacticError{ByteOffset: len64(`n`), Err: io.ErrUnexpectedEOF}},
9555 {in: `nul`, err: &jsontext.SyntacticError{ByteOffset: len64(`nul`), Err: io.ErrUnexpectedEOF}},
9556 {in: `fal `, err: &jsontext.SyntacticError{ByteOffset: len64(`fal`), Err: jsonwire.NewInvalidCharacterError(" ", "in literal false (expecting 's')")}},
9557 {in: `false`, want: []any{false}, err: io.EOF},
9558 {in: `false0.0[]null`, want: []any{false, 0.0, []any{}, nil}, err: io.EOF},
9559 }
9560 for _, tt := range tests {
9561 d := jsontext.NewDecoder(strings.NewReader(tt.in))
9562 var got []any
9563 for {
9564 var v any
9565 if err := UnmarshalDecode(d, &v); err != nil {
9566 if !reflect.DeepEqual(err, tt.err) {
9567 t.Errorf("`%s`: UnmarshalDecode error = %v, want %v", tt.in, err, tt.err)
9568 }
9569 break
9570 }
9571 got = append(got, v)
9572 }
9573 if !reflect.DeepEqual(got, tt.want) {
9574 t.Errorf("`%s`: UnmarshalDecode = %v, want %v", tt.in, got, tt.want)
9575 }
9576 }
9577 }
9578
9579
9580
9581 func BenchmarkUnmarshalDecodeOptions(b *testing.B) {
9582 var i int
9583 in := new(bytes.Buffer)
9584 dec := jsontext.NewDecoder(in)
9585 makeBench := func(opts ...Options) func(*testing.B) {
9586 return func(b *testing.B) {
9587 for range b.N {
9588 in.WriteString("0 ")
9589 }
9590 dec.Reset(in)
9591 b.ResetTimer()
9592 for range b.N {
9593 UnmarshalDecode(dec, &i, opts...)
9594 }
9595 }
9596 }
9597 b.Run("None", makeBench())
9598 b.Run("Same", makeBench(&export.Decoder(dec).Struct))
9599 b.Run("New", makeBench(DefaultOptionsV2()))
9600 }
9601
9602 func TestMarshalEncodeOptions(t *testing.T) {
9603 var calledFuncs int
9604 var calledOptions Options
9605 out := new(bytes.Buffer)
9606 enc := jsontext.NewEncoder(
9607 out,
9608 jsontext.AllowInvalidUTF8(true),
9609 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9610 opts := enc.Options()
9611 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9612 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9613 }
9614 calledFuncs++
9615 calledOptions = opts
9616 return errors.ErrUnsupported
9617 })),
9618 )
9619
9620 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9621 t.Fatalf("MarshalEncode: %v", err)
9622 }
9623 if calledFuncs != 1 {
9624 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9625 }
9626 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", calledOptions); err != nil {
9627 t.Fatalf("MarshalEncode: %v", err)
9628 }
9629 if calledFuncs != 2 {
9630 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9631 }
9632 if err := MarshalEncode(enc, "\xde\xad\xbe\xef",
9633 jsontext.AllowInvalidUTF8(false),
9634 WithMarshalers(nil),
9635 ); err != nil {
9636 t.Fatalf("MarshalEncode: %v", err)
9637 }
9638 if calledFuncs != 2 {
9639 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9640 }
9641 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9642 t.Fatalf("MarshalEncode: %v", err)
9643 }
9644 if calledFuncs != 3 {
9645 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9646 }
9647 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", JoinOptions(
9648 jsontext.AllowInvalidUTF8(false),
9649 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9650 opts := enc.Options()
9651 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9652 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9653 }
9654 calledFuncs = math.MaxInt
9655 return errors.ErrUnsupported
9656 })),
9657 )); err != nil {
9658 t.Fatalf("MarshalEncode: %v", err)
9659 }
9660 if calledFuncs != math.MaxInt {
9661 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9662 }
9663 if out.String() != strings.Repeat("\"\xde\xad\ufffd\ufffd\"\n", 5) {
9664 t.Fatalf("output mismatch:\n\tgot: %s\n\twant: %s", out.String(), strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9665 }
9666
9667
9668
9669 opts := enc.Options()
9670 enc.Reset(out, jsontext.AllowInvalidUTF8(false), opts)
9671 if v, _ := GetOption(enc.Options(), jsontext.AllowInvalidUTF8); v == false {
9672 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9673 }
9674 }
9675
9676
9677
9678 func BenchmarkMarshalEncodeOptions(b *testing.B) {
9679 var i int
9680 out := new(bytes.Buffer)
9681 enc := jsontext.NewEncoder(out)
9682 makeBench := func(opts ...Options) func(*testing.B) {
9683 return func(b *testing.B) {
9684 out.Reset()
9685 enc.Reset(out)
9686 b.ResetTimer()
9687 for range b.N {
9688 MarshalEncode(enc, &i, opts...)
9689 }
9690 }
9691 }
9692 b.Run("None", makeBench())
9693 b.Run("Same", makeBench(&export.Encoder(enc).Struct))
9694 b.Run("New", makeBench(DefaultOptionsV2()))
9695 }
9696
View as plain text