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 "internal/race"
18 "internal/testenv"
19 "io"
20 "math"
21 "net"
22 "net/netip"
23 "reflect"
24 "strconv"
25 "strings"
26 "testing"
27 "time"
28
29 "encoding/json/internal"
30 "encoding/json/internal/jsonflags"
31 "encoding/json/internal/jsonopts"
32 "encoding/json/internal/jsontest"
33 "encoding/json/internal/jsonwire"
34 "encoding/json/jsontext"
35 )
36
37 func newNonStringNameError(offset int64, pointer jsontext.Pointer) error {
38 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsontext.ErrNonStringName}
39 }
40
41 func newInvalidCharacterError(prefix, where string, offset int64, pointer jsontext.Pointer) error {
42 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.NewInvalidCharacterError(prefix, where)}
43 }
44
45 func newInvalidUTF8Error(offset int64, pointer jsontext.Pointer) error {
46 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.ErrInvalidUTF8}
47 }
48
49 func newParseTimeError(layout, value, layoutElem, valueElem, message string) error {
50 return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message}
51 }
52
53 func EM(err error) *SemanticError {
54 return &SemanticError{action: "marshal", Err: err}
55 }
56
57 func EU(err error) *SemanticError {
58 return &SemanticError{action: "unmarshal", Err: err}
59 }
60
61 func (e *SemanticError) withVal(val string) *SemanticError {
62 e.JSONValue = jsontext.Value(val)
63 return e
64 }
65
66 func (e *SemanticError) withPos(prefix string, pointer jsontext.Pointer) *SemanticError {
67 e.ByteOffset = int64(len(prefix))
68 e.JSONPointer = pointer
69 return e
70 }
71
72 func (e *SemanticError) withType(k jsontext.Kind, t reflect.Type) *SemanticError {
73 e.JSONKind = k
74 e.GoType = t
75 return e
76 }
77
78 var (
79 errInvalidFormatFlag = errors.New(`invalid format flag "invalid"`)
80 errSomeError = errors.New("some error")
81 errMustNotCall = errors.New("must not call")
82 )
83
84 func T[T any]() reflect.Type { return reflect.TypeFor[T]() }
85
86 type (
87 jsonObject = map[string]any
88 jsonArray = []any
89
90 namedAny any
91 namedBool bool
92 namedString string
93 NamedString string
94 namedBytes []byte
95 namedInt64 int64
96 namedUint64 uint64
97 namedFloat64 float64
98 namedByte byte
99 netipAddr = netip.Addr
100
101 recursiveMap map[string]recursiveMap
102 recursiveSlice []recursiveSlice
103 recursivePointer struct{ P *recursivePointer }
104
105 structEmpty struct{}
106 structConflicting struct {
107 A string `json:"conflict"`
108 B string `json:"conflict"`
109 }
110 structNoneExported struct {
111 unexported string
112 }
113 structUnexportedIgnored struct {
114 ignored string `json:"-"`
115 }
116 structMalformedTag struct {
117 Malformed string `json:"\""`
118 }
119 structUnexportedTag struct {
120 unexported string `json:"name"`
121 }
122 structExportedEmbedded struct {
123 NamedString
124 }
125 structExportedEmbeddedTag struct {
126 NamedString `json:"name"`
127 }
128 structUnexportedEmbedded struct {
129 namedString
130 }
131 structUnexportedEmbeddedTag struct {
132 namedString `json:"name"`
133 }
134 structUnexportedEmbeddedMethodTag struct {
135
136
137 netipAddr `json:"name"`
138
139
140
141
142 }
143 structUnexportedEmbeddedStruct struct {
144 structOmitZeroAll
145 FizzBuzz int
146 structNestedAddr
147 }
148 structUnexportedEmbeddedStructPointer struct {
149 *structOmitZeroAll
150 FizzBuzz int
151 *structNestedAddr
152 }
153 structUnexportedEmbeddedPointerMapStringInt struct {
154 A int `json:",omitzero"`
155 *structEmbedMapStringInt
156 }
157 structUnexportedEmbeddedPointerTextValue struct {
158 A int `json:",omitzero"`
159 *structEmbedEmbedPointerTextValue
160 }
161 structNestedAddr struct {
162 Addr netip.Addr
163 }
164 structIgnoredUnexportedEmbedded struct {
165 namedString `json:"-"`
166 }
167 structNoCase struct {
168 Aaa string `json:",case:strict"`
169 AA_A string
170 AaA string `json:",case:ignore"`
171 AAa string `json:",case:ignore"`
172 AAA string
173 }
174 structScalars struct {
175 unexported bool
176 Ignored bool `json:"-"`
177
178 Bool bool
179 String string
180 Bytes []byte
181 Int int64
182 Uint uint64
183 Float float64
184 }
185 structSlices struct {
186 unexported bool
187 Ignored bool `json:"-"`
188
189 SliceBool []bool
190 SliceString []string
191 SliceBytes [][]byte
192 SliceInt []int64
193 SliceUint []uint64
194 SliceFloat []float64
195 }
196 structMaps struct {
197 unexported bool
198 Ignored bool `json:"-"`
199
200 MapBool map[string]bool
201 MapString map[string]string
202 MapBytes map[string][]byte
203 MapInt map[string]int64
204 MapUint map[string]uint64
205 MapFloat map[string]float64
206 }
207 structAll struct {
208 Bool bool
209 String string
210 Bytes []byte
211 Int int64
212 Uint uint64
213 Float float64
214 Map map[string]string
215 StructScalars structScalars
216 StructMaps structMaps
217 StructSlices structSlices
218 Slice []string
219 Array [1]string
220 Pointer *structAll
221 Interface any
222 }
223 structOmitZeroAll struct {
224 Bool bool `json:",omitzero"`
225 String string `json:",omitzero"`
226 Bytes []byte `json:",omitzero"`
227 Int int64 `json:",omitzero"`
228 Uint uint64 `json:",omitzero"`
229 Float float64 `json:",omitzero"`
230 Map map[string]string `json:",omitzero"`
231 StructScalars structScalars `json:",omitzero"`
232 StructMaps structMaps `json:",omitzero"`
233 StructSlices structSlices `json:",omitzero"`
234 Slice []string `json:",omitzero"`
235 Array [1]string `json:",omitzero"`
236 Pointer *structOmitZeroAll `json:",omitzero"`
237 Interface any `json:",omitzero"`
238 }
239 structOmitZeroMethodAll struct {
240 ValueAlwaysZero valueAlwaysZero `json:",omitzero"`
241 ValueNeverZero valueNeverZero `json:",omitzero"`
242 PointerAlwaysZero pointerAlwaysZero `json:",omitzero"`
243 PointerNeverZero pointerNeverZero `json:",omitzero"`
244 PointerValueAlwaysZero *valueAlwaysZero `json:",omitzero"`
245 PointerValueNeverZero *valueNeverZero `json:",omitzero"`
246 PointerPointerAlwaysZero *pointerAlwaysZero `json:",omitzero"`
247 PointerPointerNeverZero *pointerNeverZero `json:",omitzero"`
248 PointerPointerValueAlwaysZero **valueAlwaysZero `json:",omitzero"`
249 PointerPointerValueNeverZero **valueNeverZero `json:",omitzero"`
250 PointerPointerPointerAlwaysZero **pointerAlwaysZero `json:",omitzero"`
251 PointerPointerPointerNeverZero **pointerNeverZero `json:",omitzero"`
252 }
253 structOmitZeroMethodInterfaceAll struct {
254 ValueAlwaysZero isZeroer `json:",omitzero"`
255 ValueNeverZero isZeroer `json:",omitzero"`
256 PointerValueAlwaysZero isZeroer `json:",omitzero"`
257 PointerValueNeverZero isZeroer `json:",omitzero"`
258 PointerPointerAlwaysZero isZeroer `json:",omitzero"`
259 PointerPointerNeverZero isZeroer `json:",omitzero"`
260 }
261 structOmitEmptyAll struct {
262 Bool bool `json:",omitempty"`
263 PointerBool *bool `json:",omitempty"`
264 String string `json:",omitempty"`
265 StringEmpty stringMarshalEmpty `json:",omitempty"`
266 StringNonEmpty stringMarshalNonEmpty `json:",omitempty"`
267 PointerString *string `json:",omitempty"`
268 PointerStringEmpty *stringMarshalEmpty `json:",omitempty"`
269 PointerStringNonEmpty *stringMarshalNonEmpty `json:",omitempty"`
270 Bytes []byte `json:",omitempty"`
271 BytesEmpty bytesMarshalEmpty `json:",omitempty"`
272 BytesNonEmpty bytesMarshalNonEmpty `json:",omitempty"`
273 PointerBytes *[]byte `json:",omitempty"`
274 PointerBytesEmpty *bytesMarshalEmpty `json:",omitempty"`
275 PointerBytesNonEmpty *bytesMarshalNonEmpty `json:",omitempty"`
276 Float float64 `json:",omitempty"`
277 PointerFloat *float64 `json:",omitempty"`
278 Map map[string]string `json:",omitempty"`
279 MapEmpty mapMarshalEmpty `json:",omitempty"`
280 MapNonEmpty mapMarshalNonEmpty `json:",omitempty"`
281 PointerMap *map[string]string `json:",omitempty"`
282 PointerMapEmpty *mapMarshalEmpty `json:",omitempty"`
283 PointerMapNonEmpty *mapMarshalNonEmpty `json:",omitempty"`
284 Slice []string `json:",omitempty"`
285 SliceEmpty sliceMarshalEmpty `json:",omitempty"`
286 SliceNonEmpty sliceMarshalNonEmpty `json:",omitempty"`
287 PointerSlice *[]string `json:",omitempty"`
288 PointerSliceEmpty *sliceMarshalEmpty `json:",omitempty"`
289 PointerSliceNonEmpty *sliceMarshalNonEmpty `json:",omitempty"`
290 Pointer *structOmitZeroEmptyAll `json:",omitempty"`
291 Interface any `json:",omitempty"`
292 }
293 structOmitZeroEmptyAll struct {
294 Bool bool `json:",omitzero,omitempty"`
295 String string `json:",omitzero,omitempty"`
296 Bytes []byte `json:",omitzero,omitempty"`
297 Int int64 `json:",omitzero,omitempty"`
298 Uint uint64 `json:",omitzero,omitempty"`
299 Float float64 `json:",omitzero,omitempty"`
300 Map map[string]string `json:",omitzero,omitempty"`
301 Slice []string `json:",omitzero,omitempty"`
302 Array [1]string `json:",omitzero,omitempty"`
303 Pointer *structOmitZeroEmptyAll `json:",omitzero,omitempty"`
304 Interface any `json:",omitzero,omitempty"`
305 }
306 structStringifiedLegacy struct {
307 Bool bool `json:",string"`
308 String string `json:",string"`
309 Int int64 `json:",string"`
310 Uint uint64 `json:",string"`
311 Float float64 `json:",string"`
312 PointerBool *bool `json:",string"`
313 PointerString *string `json:",string"`
314 PointerInt *int64 `json:",string"`
315 PointerUint *uint64 `json:",string"`
316 PointerFloat *float64 `json:",string"`
317 }
318 structStringified struct {
319 Int int64 `json:",string"`
320 Uint uint64 `json:",string"`
321 Float float64 `json:",string"`
322 PointerInt *int64 `json:",string"`
323 PointerUint *uint64 `json:",string"`
324 PointerFloat *float64 `json:",string"`
325 }
326 structStringifiedBool struct {
327 Bool bool `json:",string"`
328 }
329 structStringifiedString struct {
330 String string `json:",string"`
331 }
332 structStringifiedBytes struct {
333 Bytes []byte `json:",string"`
334 }
335 structStringifiedMap struct {
336 Map map[string]string `json:",string"`
337 }
338 structStringifiedSlice struct {
339 Slice []string `json:",string"`
340 }
341 structStringifiedArray struct {
342 Array [1]string `json:",string"`
343 }
344 structStringifiedStruct struct {
345 Struct structAll `json:",string"`
346 }
347 structStringifiedPointer struct {
348 Pointer *structAll `json:",string"`
349 }
350 structStringifiedPointerPointerInt struct {
351 Pointer **int `json:",string"`
352 }
353 structStringifiedInterface struct {
354 Interface any `json:",string"`
355 }
356 structFormatBytes struct {
357 Base16 []byte `json:",format:base16"`
358 Base32 []byte `json:",format:base32"`
359 Base32Hex []byte `json:",format:base32hex"`
360 Base64 []byte `json:",format:base64"`
361 Base64URL []byte `json:",format:base64url"`
362 Array []byte `json:",format:array"`
363 }
364 structFormatArrayBytes struct {
365 Base16 [4]byte `json:",format:base16"`
366 Base32 [4]byte `json:",format:base32"`
367 Base32Hex [4]byte `json:",format:base32hex"`
368 Base64 [4]byte `json:",format:base64"`
369 Base64URL [4]byte `json:",format:base64url"`
370 Array [4]byte `json:",format:array"`
371 Default [4]byte
372 }
373 structFormatFloats struct {
374 NonFinite float64 `json:",format:nonfinite"`
375 PointerNonFinite *float64 `json:",format:nonfinite"`
376 }
377 structFormatMaps struct {
378 EmitNull map[string]string `json:",format:emitnull"`
379 PointerEmitNull *map[string]string `json:",format:emitnull"`
380 EmitEmpty map[string]string `json:",format:emitempty"`
381 PointerEmitEmpty *map[string]string `json:",format:emitempty"`
382 EmitDefault map[string]string
383 PointerEmitDefault *map[string]string
384 }
385 structFormatSlices struct {
386 EmitNull []string `json:",format:emitnull"`
387 PointerEmitNull *[]string `json:",format:emitnull"`
388 EmitEmpty []string `json:",format:emitempty"`
389 PointerEmitEmpty *[]string `json:",format:emitempty"`
390 EmitDefault []string
391 PointerEmitDefault *[]string
392 }
393 structFormatInvalid struct {
394 Bool bool `json:",omitzero,format:invalid"`
395 String string `json:",omitzero,format:invalid"`
396 Bytes []byte `json:",omitzero,format:invalid"`
397 Int int64 `json:",omitzero,format:invalid"`
398 Uint uint64 `json:",omitzero,format:invalid"`
399 Float float64 `json:",omitzero,format:invalid"`
400 Map map[string]string `json:",omitzero,format:invalid"`
401 Struct structAll `json:",omitzero,format:invalid"`
402 Slice []string `json:",omitzero,format:invalid"`
403 Array [1]string `json:",omitzero,format:invalid"`
404 Interface any `json:",omitzero,format:invalid"`
405 }
406 structDurationFormat struct {
407 D1 time.Duration `json:",format:units"`
408 D2 time.Duration `json:",format:units"`
409 D3 time.Duration `json:",format:sec"`
410 D4 time.Duration `json:",string,format:sec"`
411 D5 time.Duration `json:",format:milli"`
412 D6 time.Duration `json:",string,format:milli"`
413 D7 time.Duration `json:",format:micro"`
414 D8 time.Duration `json:",string,format:micro"`
415 D9 time.Duration `json:",format:nano"`
416 D10 time.Duration `json:",string,format:nano"`
417 D11 time.Duration `json:",format:iso8601"`
418 }
419 structTimeFormat struct {
420 T1 time.Time
421 T2 time.Time `json:",format:ANSIC"`
422 T3 time.Time `json:",format:UnixDate"`
423 T4 time.Time `json:",format:RubyDate"`
424 T5 time.Time `json:",format:RFC822"`
425 T6 time.Time `json:",format:RFC822Z"`
426 T7 time.Time `json:",format:RFC850"`
427 T8 time.Time `json:",format:RFC1123"`
428 T9 time.Time `json:",format:RFC1123Z"`
429 T10 time.Time `json:",format:RFC3339"`
430 T11 time.Time `json:",format:RFC3339Nano"`
431 T12 time.Time `json:",format:Kitchen"`
432 T13 time.Time `json:",format:Stamp"`
433 T14 time.Time `json:",format:StampMilli"`
434 T15 time.Time `json:",format:StampMicro"`
435 T16 time.Time `json:",format:StampNano"`
436 T17 time.Time `json:",format:DateTime"`
437 T18 time.Time `json:",format:DateOnly"`
438 T19 time.Time `json:",format:TimeOnly"`
439 T20 time.Time `json:",format:'2006-01-02'"`
440 T21 time.Time `json:",format:'\"weird\"2006'"`
441 T22 time.Time `json:",format:unix"`
442 T23 time.Time `json:",string,format:unix"`
443 T24 time.Time `json:",format:unixmilli"`
444 T25 time.Time `json:",string,format:unixmilli"`
445 T26 time.Time `json:",format:unixmicro"`
446 T27 time.Time `json:",string,format:unixmicro"`
447 T28 time.Time `json:",format:unixnano"`
448 T29 time.Time `json:",string,format:unixnano"`
449 }
450 structTimeFormatStringInvalid struct {
451 T time.Time `json:",string,format:RFC3339"`
452 }
453 structEmbedded struct {
454 X structEmbeddedL1 `json:",embed"`
455 *StructEmbed2
456 }
457 structEmbeddedL1 struct {
458 X *structEmbeddedL2 `json:",embed"`
459 StructEmbed1 `json:",embed"`
460 }
461 structEmbeddedL2 struct{ A, B, C string }
462 StructEmbed1 struct{ C, D, E string }
463 StructEmbed2 struct{ E, F, G string }
464 structEmbedTextValue struct {
465 A int `json:",omitzero"`
466 X jsontext.Value `json:",embed"`
467 B int `json:",omitzero"`
468 }
469 structEmbedPointerTextValue struct {
470 A int `json:",omitzero"`
471 X *jsontext.Value `json:",embed"`
472 B int `json:",omitzero"`
473 }
474 structEmbedPointerEmbedTextValue struct {
475 X *struct {
476 A int
477 X jsontext.Value `json:",embed"`
478 } `json:",embed"`
479 }
480 structEmbedEmbedPointerTextValue struct {
481 X struct {
482 X *jsontext.Value `json:",embed"`
483 } `json:",embed"`
484 }
485 structEmbedMapStringAny struct {
486 A int `json:",omitzero"`
487 X jsonObject `json:",embed"`
488 B int `json:",omitzero"`
489 }
490 structEmbedPointerMapStringAny struct {
491 A int `json:",omitzero"`
492 X *jsonObject `json:",embed"`
493 B int `json:",omitzero"`
494 }
495 structEmbedPointerEmbedMapStringAny struct {
496 X *struct {
497 A int
498 X jsonObject `json:",embed"`
499 } `json:",embed"`
500 }
501 structEmbedEmbedPointerMapStringAny struct {
502 X struct {
503 X *jsonObject `json:",embed"`
504 } `json:",embed"`
505 }
506 structEmbedMapStringInt struct {
507 X map[string]int `json:",embed"`
508 }
509 structEmbedMapNamedStringInt struct {
510 X map[namedString]int `json:",embed"`
511 }
512 structEmbedMapNamedStringAny struct {
513 A int `json:",omitzero"`
514 X map[namedString]any `json:",embed"`
515 B int `json:",omitzero"`
516 }
517 structNoCaseEmbedTextValue struct {
518 AAA string `json:",omitempty,case:strict"`
519 AA_b string `json:",omitempty"`
520 AaA string `json:",omitempty,case:ignore"`
521 AAa string `json:",omitempty,case:ignore"`
522 Aaa string `json:",omitempty"`
523 X jsontext.Value `json:",embed"`
524 }
525 structNoCaseEmbedMapStringAny struct {
526 AAA string `json:",omitempty"`
527 AaA string `json:",omitempty,case:ignore"`
528 AAa string `json:",omitempty,case:ignore"`
529 Aaa string `json:",omitempty"`
530 X jsonObject `json:",embed"`
531 }
532
533 allMethods struct {
534 method string
535 value []byte
536 }
537 allMethodsExceptJSONv2 struct {
538 allMethods
539 MarshalJSONTo struct{}
540 UnmarshalJSONFrom struct{}
541 }
542 allMethodsExceptJSONv1 struct {
543 allMethods
544 MarshalJSON struct{}
545 UnmarshalJSON struct{}
546 }
547 allMethodsExceptText struct {
548 allMethods
549 MarshalText struct{}
550 UnmarshalText struct{}
551 }
552 onlyMethodJSONv2 struct {
553 allMethods
554 MarshalJSON struct{}
555 UnmarshalJSON struct{}
556 MarshalText struct{}
557 UnmarshalText struct{}
558 }
559 onlyMethodJSONv1 struct {
560 allMethods
561 MarshalJSONTo struct{}
562 UnmarshalJSONFrom struct{}
563 MarshalText struct{}
564 UnmarshalText struct{}
565 }
566 onlyMethodText struct {
567 allMethods
568 MarshalJSONTo struct{}
569 UnmarshalJSONFrom struct{}
570 MarshalJSON struct{}
571 UnmarshalJSON struct{}
572 }
573
574 unsupportedMethodJSONv2 map[string]int
575
576 structMethodJSONv2 struct{ value string }
577 structMethodJSONv1 struct{ value string }
578 structMethodText struct{ value string }
579
580 marshalJSONv2Func func(*jsontext.Encoder) error
581 marshalJSONv1Func func() ([]byte, error)
582 appendTextFunc func([]byte) ([]byte, error)
583 marshalTextFunc func() ([]byte, error)
584 unmarshalJSONv2Func func(*jsontext.Decoder) error
585 unmarshalJSONv1Func func([]byte) error
586 unmarshalTextFunc func([]byte) error
587
588 nocaseString string
589
590 stringMarshalEmpty string
591 stringMarshalNonEmpty string
592 bytesMarshalEmpty []byte
593 bytesMarshalNonEmpty []byte
594 mapMarshalEmpty map[string]string
595 mapMarshalNonEmpty map[string]string
596 sliceMarshalEmpty []string
597 sliceMarshalNonEmpty []string
598
599 valueAlwaysZero string
600 valueNeverZero string
601 pointerAlwaysZero string
602 pointerNeverZero string
603
604 valueStringer struct{}
605 pointerStringer struct{}
606
607 cyclicA struct {
608 B1 cyclicB `json:",embed"`
609 B2 cyclicB `json:",embed"`
610 }
611 cyclicB struct {
612 F int
613 A *cyclicA `json:",embed"`
614 }
615 )
616
617 func (structUnexportedEmbeddedMethodTag) MarshalText() {}
618 func (structUnexportedEmbeddedMethodTag) AppendText() {}
619
620 func (p *allMethods) MarshalJSONTo(enc *jsontext.Encoder) error {
621 if got, want := "MarshalJSONTo", p.method; got != want {
622 return fmt.Errorf("called wrong method: got %v, want %v", got, want)
623 }
624 return enc.WriteValue(p.value)
625 }
626 func (p *allMethods) MarshalJSON() ([]byte, error) {
627 if got, want := "MarshalJSON", p.method; got != want {
628 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
629 }
630 return p.value, nil
631 }
632 func (p *allMethods) MarshalText() ([]byte, error) {
633 if got, want := "MarshalText", p.method; got != want {
634 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
635 }
636 return p.value, nil
637 }
638
639 func (p *allMethods) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
640 p.method = "UnmarshalJSONFrom"
641 val, err := dec.ReadValue()
642 p.value = val
643 return err
644 }
645 func (p *allMethods) UnmarshalJSON(val []byte) error {
646 p.method = "UnmarshalJSON"
647 p.value = val
648 return nil
649 }
650 func (p *allMethods) UnmarshalText(val []byte) error {
651 p.method = "UnmarshalText"
652 p.value = val
653 return nil
654 }
655
656 func (s *unsupportedMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
657 (*s)["called"] += 1
658 return errors.ErrUnsupported
659 }
660 func (s *unsupportedMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
661 (*s)["called"] += 1
662 return errors.ErrUnsupported
663 }
664
665 func (s structMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
666 return enc.WriteToken(jsontext.String(s.value))
667 }
668 func (s *structMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
669 tok, err := dec.ReadToken()
670 if err != nil {
671 return err
672 }
673 if k := tok.Kind(); k != '"' {
674 return EU(nil).withType(k, T[structMethodJSONv2]())
675 }
676 s.value = tok.String()
677 return nil
678 }
679
680 func (s structMethodJSONv1) MarshalJSON() ([]byte, error) {
681 return jsontext.AppendQuote(nil, s.value)
682 }
683 func (s *structMethodJSONv1) UnmarshalJSON(b []byte) error {
684 if k := jsontext.Value(b).Kind(); k != '"' {
685 return EU(nil).withType(k, T[structMethodJSONv1]())
686 }
687 b, _ = jsontext.AppendUnquote(nil, b)
688 s.value = string(b)
689 return nil
690 }
691
692 func (s structMethodText) MarshalText() ([]byte, error) {
693 return []byte(s.value), nil
694 }
695 func (s *structMethodText) UnmarshalText(b []byte) error {
696 s.value = string(b)
697 return nil
698 }
699
700 func (f marshalJSONv2Func) MarshalJSONTo(enc *jsontext.Encoder) error {
701 return f(enc)
702 }
703 func (f marshalJSONv1Func) MarshalJSON() ([]byte, error) {
704 return f()
705 }
706 func (f appendTextFunc) AppendText(b []byte) ([]byte, error) {
707 return f(b)
708 }
709 func (f marshalTextFunc) MarshalText() ([]byte, error) {
710 return f()
711 }
712 func (f unmarshalJSONv2Func) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
713 return f(dec)
714 }
715 func (f unmarshalJSONv1Func) UnmarshalJSON(b []byte) error {
716 return f(b)
717 }
718 func (f unmarshalTextFunc) UnmarshalText(b []byte) error {
719 return f(b)
720 }
721
722 func (k nocaseString) MarshalText() ([]byte, error) {
723 return []byte(strings.ToLower(string(k))), nil
724 }
725 func (k *nocaseString) UnmarshalText(b []byte) error {
726 *k = nocaseString(strings.ToLower(string(b)))
727 return nil
728 }
729
730 func (stringMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`""`), nil }
731 func (stringMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`"value"`), nil }
732 func (bytesMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
733 func (bytesMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
734 func (mapMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`{}`), nil }
735 func (mapMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`{"key":"value"}`), nil }
736 func (sliceMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
737 func (sliceMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
738
739 func (valueAlwaysZero) IsZero() bool { return true }
740 func (valueNeverZero) IsZero() bool { return false }
741 func (*pointerAlwaysZero) IsZero() bool { return true }
742 func (*pointerNeverZero) IsZero() bool { return false }
743
744 func (valueStringer) String() string { return "" }
745 func (*pointerStringer) String() string { return "" }
746
747 func mustParseTime(layout, value string) time.Time {
748 t, err := time.Parse(layout, value)
749 if err != nil {
750 panic(err)
751 }
752 return t
753 }
754
755
756
757
758 var invalidFormatOption = &jsonopts.Struct{
759 ArshalValues: jsonopts.ArshalValues{Format: "invalid"},
760 }
761
762 func TestMarshalAppendTextNewSameCapacity(t *testing.T) {
763 var dst bytes.Buffer
764 dst.Grow(64)
765 enc := jsontext.NewEncoder(&dst)
766 err := MarshalEncode(enc, appendTextFunc(func(b []byte) ([]byte, error) {
767 out := make([]byte, len(b), cap(b))
768 copy(out, b)
769 return append(out, "hello"...), nil
770 }))
771 if err != nil {
772 t.Fatal(err)
773 }
774 if want := "\"hello\"\n"; dst.String() != want {
775 t.Fatalf("MarshalEncode = %q, want %q", dst.String(), want)
776 }
777 }
778
779
780
781 func TestMarshalInterfaceNoCopy(t *testing.T) {
782 testenv.SkipIfOptimizationOff(t)
783 if race.Enabled {
784 t.Skip("skipping malloc count under race detector")
785 }
786 type namedAny any
787 for _, in := range [][2]any{
788 {[]any{"a"}, []any{"a", "b", "c", "d", "e", "f", "g", "h"}},
789 {[]any{1}, []any{1, 2, 3, 4, 5, 6, 7, 8}},
790 {[]namedAny{1}, []namedAny{1, 2, 3, 4, 5, 6, 7, 8}},
791 } {
792 n1 := testing.AllocsPerRun(100, func() { MarshalWrite(io.Discard, in[0]) })
793 n8 := testing.AllocsPerRun(100, func() { MarshalWrite(io.Discard, in[1]) })
794 if n8 > n1 {
795 t.Errorf("MarshalWrite(%T): %v allocs for 8 elements, want at most %v (1 element)", in[0], n8, n1)
796 }
797 }
798 }
799
800 func TestMarshal(t *testing.T) {
801 tests := []struct {
802 name jsontest.CaseName
803 opts []Options
804 in any
805 want string
806 wantErr error
807
808 canonicalize bool
809 useWriter bool
810 }{{
811 name: jsontest.Name("Nil"),
812 in: nil,
813 want: `null`,
814 }, {
815 name: jsontest.Name("Bools"),
816 in: []bool{false, true},
817 want: `[false,true]`,
818 }, {
819 name: jsontest.Name("Bools/Named"),
820 in: []namedBool{false, true},
821 want: `[false,true]`,
822 }, {
823 name: jsontest.Name("Bools/NotStringified"),
824 opts: []Options{StringifyNumbers(true)},
825 in: []bool{false, true},
826 want: `[false,true]`,
827 }, {
828 name: jsontest.Name("Bools/StringifiedBool/False"),
829 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
830 in: false,
831 want: `"false"`,
832 }, {
833 name: jsontest.Name("Bools/StringifiedBool/True"),
834 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
835 in: true,
836 want: `"true"`,
837 }, {
838 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
839 opts: []Options{invalidFormatOption},
840 in: true,
841 want: `true`,
842 }, {
843 name: jsontest.Name("Strings"),
844 in: []string{"", "hello", "世界"},
845 want: `["","hello","世界"]`,
846 }, {
847 name: jsontest.Name("Strings/Named"),
848 in: []namedString{"", "hello", "世界"},
849 want: `["","hello","世界"]`,
850 }, {
851 name: jsontest.Name("Strings/StringifiedString"),
852 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
853 in: "hello",
854 want: `"\"hello\""`,
855 }, {
856 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
857 opts: []Options{invalidFormatOption},
858 in: "string",
859 want: `"string"`,
860 }, {
861 name: jsontest.Name("Bytes"),
862 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
863 want: `["","","AQ==","AQI=","AQID"]`,
864 }, {
865 name: jsontest.Name("Bytes/FormatNilSliceAsNull"),
866 opts: []Options{FormatNilSliceAsNull(true)},
867 in: [][]byte{nil, {}},
868 want: `[null,""]`,
869 }, {
870 name: jsontest.Name("Bytes/Large"),
871 in: []byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on."),
872 want: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
873 }, {
874 name: jsontest.Name("Bytes/Named"),
875 in: []namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}},
876 want: `["","","AQ==","AQI=","AQID"]`,
877 }, {
878 name: jsontest.Name("Bytes/NotStringified"),
879 opts: []Options{StringifyNumbers(true)},
880 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
881 want: `["","","AQ==","AQI=","AQID"]`,
882 }, {
883
884
885 name: jsontest.Name("Bytes/Invariant"),
886 in: [][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
887 want: `[[],[],[1],[1,2],[1,2,3]]`,
888 }, {
889
890
891 name: jsontest.Name("Bytes/ByteArray"),
892 in: [5]byte{'h', 'e', 'l', 'l', 'o'},
893 want: `"aGVsbG8="`,
894 }, {
895
896
897 name: jsontest.Name("Bytes/NamedByteArray"),
898 in: [5]namedByte{'h', 'e', 'l', 'l', 'o'},
899 want: `[104,101,108,108,111]`,
900 }, {
901 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
902 opts: []Options{invalidFormatOption},
903 in: []byte("hello"),
904 want: `"aGVsbG8="`,
905 }, {
906 name: jsontest.Name("Ints"),
907 in: []any{
908 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
909 },
910 want: `[0,-128,-32768,-2147483648,-9223372036854775808,-6464]`,
911 }, {
912 name: jsontest.Name("Ints/Stringified"),
913 opts: []Options{StringifyNumbers(true)},
914 in: []any{
915 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
916 },
917 want: `["0","-128","-32768","-2147483648","-9223372036854775808","-6464"]`,
918 }, {
919 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
920 opts: []Options{invalidFormatOption},
921 in: int(0),
922 want: `0`,
923 }, {
924 name: jsontest.Name("Uints"),
925 in: []any{
926 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464), uintptr(1234),
927 },
928 want: `[0,255,65535,4294967295,18446744073709551615,6464,1234]`,
929 }, {
930 name: jsontest.Name("Uints/Stringified"),
931 opts: []Options{StringifyNumbers(true)},
932 in: []any{
933 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464),
934 },
935 want: `["0","255","65535","4294967295","18446744073709551615","6464"]`,
936 }, {
937 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
938 opts: []Options{invalidFormatOption},
939 in: uint(0),
940 want: `0`,
941 }, {
942 name: jsontest.Name("Floats"),
943 in: []any{
944 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
945 },
946 want: `[3.4028235e+38,1.7976931348623157e+308,64.64]`,
947 }, {
948 name: jsontest.Name("Floats/Stringified"),
949 opts: []Options{StringifyNumbers(true)},
950 in: []any{
951 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
952 },
953 want: `["3.4028235e+38","1.7976931348623157e+308","64.64"]`,
954 }, {
955 name: jsontest.Name("Floats/Invalid/NaN"),
956 opts: []Options{StringifyNumbers(true)},
957 in: math.NaN(),
958 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, float64Type),
959 }, {
960 name: jsontest.Name("Floats/Invalid/PositiveInfinity"),
961 in: math.Inf(+1),
962 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(+1))).withType(0, float64Type),
963 }, {
964 name: jsontest.Name("Floats/Invalid/NegativeInfinity"),
965 in: math.Inf(-1),
966 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(-1))).withType(0, float64Type),
967 }, {
968 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
969 opts: []Options{invalidFormatOption},
970 in: float64(0),
971 want: `0`,
972 }, {
973 name: jsontest.Name("Maps/InvalidKey/Bool"),
974 in: map[bool]string{false: "value"},
975 want: `{`,
976 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, boolType),
977 }, {
978 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
979 in: map[namedBool]string{false: "value"},
980 want: `{`,
981 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[namedBool]()),
982 }, {
983 name: jsontest.Name("Maps/InvalidKey/Array"),
984 in: map[[1]string]string{{"key"}: "value"},
985 want: `{`,
986 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[[1]string]()),
987 }, {
988 name: jsontest.Name("Maps/InvalidKey/Channel"),
989 in: map[chan string]string{make(chan string): "value"},
990 want: `{`,
991 wantErr: EM(nil).withPos(`{`, "").withType(0, T[chan string]()),
992 }, {
993 name: jsontest.Name("Maps/ValidKey/Int"),
994 in: map[int64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
995 canonicalize: true,
996 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
997 }, {
998 name: jsontest.Name("Maps/ValidKey/PointerInt"),
999 in: map[*int64]string{new(int64(math.MinInt64)): "MinInt64", new(int64(0)): "Zero", new(int64(math.MaxInt64)): "MaxInt64"},
1000 canonicalize: true,
1001 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
1002 }, {
1003 name: jsontest.Name("Maps/DuplicateName/PointerInt"),
1004 in: map[*int64]string{new(int64(0)): "0", new(int64(0)): "0"},
1005 canonicalize: true,
1006 want: `{"0":"0"`,
1007 wantErr: newDuplicateNameError("", []byte(`"0"`), len64(`{"0":"0",`)),
1008 }, {
1009 name: jsontest.Name("Maps/ValidKey/NamedInt"),
1010 in: map[namedInt64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
1011 canonicalize: true,
1012 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
1013 }, {
1014 name: jsontest.Name("Maps/ValidKey/Uint"),
1015 in: map[uint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
1016 canonicalize: true,
1017 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
1018 }, {
1019 name: jsontest.Name("Maps/ValidKey/NamedUint"),
1020 in: map[namedUint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
1021 canonicalize: true,
1022 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
1023 }, {
1024 name: jsontest.Name("Maps/ValidKey/Float"),
1025 in: map[float64]string{3.14159: "value"},
1026 want: `{"3.14159":"value"}`,
1027 }, {
1028 name: jsontest.Name("Maps/InvalidKey/Float/NaN"),
1029 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
1030 want: `{`,
1031 wantErr: EM(errors.New("unsupported value: NaN")).withPos(`{`, "").withType(0, float64Type),
1032 }, {
1033 name: jsontest.Name("Maps/ValidKey/Interface"),
1034 in: map[any]any{
1035 "key": "key",
1036 namedInt64(-64): int32(-32),
1037 namedUint64(+64): uint32(+32),
1038 namedFloat64(64.64): float32(32.32),
1039 },
1040 canonicalize: true,
1041 want: `{"-64":-32,"64":32,"64.64":32.32,"key":"key"}`,
1042 }, {
1043 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8+AllowDuplicateNames"),
1044 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
1045 in: map[string]string{"\x80": "", "\x81": ""},
1046 want: `{"�":"","�":""}`,
1047 }, {
1048 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8"),
1049 opts: []Options{jsontext.AllowInvalidUTF8(true)},
1050 in: map[string]string{"\x80": "", "\x81": ""},
1051 want: `{"�":""`,
1052 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":"",`)),
1053 }, {
1054 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
1055 opts: []Options{jsontext.AllowDuplicateNames(true)},
1056 in: map[nocaseString]string{"hello": "", "HELLO": ""},
1057 want: `{"hello":"","hello":""}`,
1058 }, {
1059 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
1060 in: map[nocaseString]string{"hello": "", "HELLO": ""},
1061 want: `{"hello":""`,
1062 wantErr: EM(newDuplicateNameError("", []byte(`"hello"`), len64(`{"hello":"",`))).withPos(`{"hello":"",`, "").withType(0, T[nocaseString]()),
1063 }, {
1064 name: jsontest.Name("Maps/DuplicateName/NaNs/Deterministic+AllowDuplicateNames"),
1065 opts: []Options{
1066 WithMarshalers(
1067 MarshalFunc(func(v float64) ([]byte, error) { return []byte(`"NaN"`), nil }),
1068 ),
1069 Deterministic(true),
1070 jsontext.AllowDuplicateNames(true),
1071 },
1072 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
1073 want: `{"NaN":"NaN","NaN":"NaN"}`,
1074 }, {
1075 name: jsontest.Name("Maps/InvalidValue/Channel"),
1076 in: map[string]chan string{
1077 "key": nil,
1078 },
1079 want: `{"key"`,
1080 wantErr: EM(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
1081 }, {
1082 name: jsontest.Name("Maps/String/Deterministic"),
1083 opts: []Options{Deterministic(true)},
1084 in: map[string]int{"a": 0, "b": 1, "c": 2},
1085 want: `{"a":0,"b":1,"c":2}`,
1086 }, {
1087 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
1088 opts: []Options{
1089 Deterministic(true),
1090 jsontext.AllowInvalidUTF8(true),
1091 jsontext.AllowDuplicateNames(false),
1092 },
1093 in: map[string]int{"\xff": 0, "\xfe": 1},
1094 want: `{"�":1`,
1095 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1,`)),
1096 }, {
1097 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
1098 opts: []Options{
1099 Deterministic(true),
1100 jsontext.AllowInvalidUTF8(true),
1101 jsontext.AllowDuplicateNames(true),
1102 },
1103 in: map[string]int{"\xff": 0, "\xfe": 1},
1104 want: `{"�":1,"�":0}`,
1105 }, {
1106 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs"),
1107 opts: []Options{
1108 Deterministic(true),
1109 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1110 if p := enc.StackPointer(); p != "/X" {
1111 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1112 }
1113 switch v {
1114 case "a":
1115 return enc.WriteToken(jsontext.String("b"))
1116 case "b":
1117 return enc.WriteToken(jsontext.String("a"))
1118 default:
1119 return fmt.Errorf("invalid value: %q", v)
1120 }
1121 })),
1122 },
1123 in: map[namedString]map[string]int{"X": {"a": -1, "b": 1}},
1124 want: `{"X":{"a":1,"b":-1}}`,
1125 }, {
1126 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+RejectDuplicateNames"),
1127 opts: []Options{
1128 Deterministic(true),
1129 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1130 if p := enc.StackPointer(); p != "/X" {
1131 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1132 }
1133 switch v {
1134 case "a", "b":
1135 return enc.WriteToken(jsontext.String("x"))
1136 default:
1137 return fmt.Errorf("invalid value: %q", v)
1138 }
1139 })),
1140 jsontext.AllowDuplicateNames(false),
1141 },
1142 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1143 want: `{"X":{"x":1`,
1144 wantErr: newDuplicateNameError("/X/x", nil, len64(`{"X":{"x":1,`)),
1145 }, {
1146 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+AllowDuplicateNames"),
1147 opts: []Options{
1148 Deterministic(true),
1149 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1150 if p := enc.StackPointer(); p != "/X" {
1151 return fmt.Errorf("invalid stack pointer: got %s, want /0", p)
1152 }
1153 switch v {
1154 case "a", "b":
1155 return enc.WriteToken(jsontext.String("x"))
1156 default:
1157 return fmt.Errorf("invalid value: %q", v)
1158 }
1159 })),
1160 jsontext.AllowDuplicateNames(true),
1161 },
1162 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1163
1164
1165 want: `{"X":{"x":1,"x":1}}`,
1166 }, {
1167 name: jsontest.Name("Maps/RecursiveMap"),
1168 in: recursiveMap{
1169 "fizz": {
1170 "foo": {},
1171 "bar": nil,
1172 },
1173 "buzz": nil,
1174 },
1175 canonicalize: true,
1176 want: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
1177 }, {
1178 name: jsontest.Name("Maps/CyclicMap"),
1179 in: func() recursiveMap {
1180 m := recursiveMap{"k": nil}
1181 m["k"] = m
1182 return m
1183 }(),
1184 want: strings.Repeat(`{"k":`, startDetectingCyclesAfter) + `{"k"`,
1185 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"k":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/k", startDetectingCyclesAfter+1))).withType(0, T[recursiveMap]()),
1186 }, {
1187 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
1188 opts: []Options{invalidFormatOption},
1189 in: map[string]string{},
1190 want: `{}`,
1191 }, {
1192 name: jsontest.Name("Structs/Empty"),
1193 in: structEmpty{},
1194 want: `{}`,
1195 }, {
1196 name: jsontest.Name("Structs/UnexportedIgnored"),
1197 in: structUnexportedIgnored{ignored: "ignored"},
1198 want: `{}`,
1199 }, {
1200 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
1201 in: structIgnoredUnexportedEmbedded{namedString: "ignored"},
1202 want: `{}`,
1203 }, {
1204 name: jsontest.Name("Structs/NoCase"),
1205 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1206 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1207 }, {
1208 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames"),
1209 opts: []Options{MatchCaseInsensitiveNames(true)},
1210 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1211 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1212 }, {
1213 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
1214 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
1215 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1216 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1217 }, {
1218 name: jsontest.Name("Structs/Normal"),
1219 opts: []Options{jsontext.Multiline(true)},
1220 in: structAll{
1221 Bool: true,
1222 String: "hello",
1223 Bytes: []byte{1, 2, 3},
1224 Int: -64,
1225 Uint: +64,
1226 Float: 3.14159,
1227 Map: map[string]string{"key": "value"},
1228 StructScalars: structScalars{
1229 Bool: true,
1230 String: "hello",
1231 Bytes: []byte{1, 2, 3},
1232 Int: -64,
1233 Uint: +64,
1234 Float: 3.14159,
1235 },
1236 StructMaps: structMaps{
1237 MapBool: map[string]bool{"": true},
1238 MapString: map[string]string{"": "hello"},
1239 MapBytes: map[string][]byte{"": {1, 2, 3}},
1240 MapInt: map[string]int64{"": -64},
1241 MapUint: map[string]uint64{"": +64},
1242 MapFloat: map[string]float64{"": 3.14159},
1243 },
1244 StructSlices: structSlices{
1245 SliceBool: []bool{true},
1246 SliceString: []string{"hello"},
1247 SliceBytes: [][]byte{{1, 2, 3}},
1248 SliceInt: []int64{-64},
1249 SliceUint: []uint64{+64},
1250 SliceFloat: []float64{3.14159},
1251 },
1252 Slice: []string{"fizz", "buzz"},
1253 Array: [1]string{"goodbye"},
1254 Pointer: new(structAll),
1255 Interface: (*structAll)(nil),
1256 },
1257 want: `{
1258 "Bool": true,
1259 "String": "hello",
1260 "Bytes": "AQID",
1261 "Int": -64,
1262 "Uint": 64,
1263 "Float": 3.14159,
1264 "Map": {
1265 "key": "value"
1266 },
1267 "StructScalars": {
1268 "Bool": true,
1269 "String": "hello",
1270 "Bytes": "AQID",
1271 "Int": -64,
1272 "Uint": 64,
1273 "Float": 3.14159
1274 },
1275 "StructMaps": {
1276 "MapBool": {
1277 "": true
1278 },
1279 "MapString": {
1280 "": "hello"
1281 },
1282 "MapBytes": {
1283 "": "AQID"
1284 },
1285 "MapInt": {
1286 "": -64
1287 },
1288 "MapUint": {
1289 "": 64
1290 },
1291 "MapFloat": {
1292 "": 3.14159
1293 }
1294 },
1295 "StructSlices": {
1296 "SliceBool": [
1297 true
1298 ],
1299 "SliceString": [
1300 "hello"
1301 ],
1302 "SliceBytes": [
1303 "AQID"
1304 ],
1305 "SliceInt": [
1306 -64
1307 ],
1308 "SliceUint": [
1309 64
1310 ],
1311 "SliceFloat": [
1312 3.14159
1313 ]
1314 },
1315 "Slice": [
1316 "fizz",
1317 "buzz"
1318 ],
1319 "Array": [
1320 "goodbye"
1321 ],
1322 "Pointer": {
1323 "Bool": false,
1324 "String": "",
1325 "Bytes": "",
1326 "Int": 0,
1327 "Uint": 0,
1328 "Float": 0,
1329 "Map": {},
1330 "StructScalars": {
1331 "Bool": false,
1332 "String": "",
1333 "Bytes": "",
1334 "Int": 0,
1335 "Uint": 0,
1336 "Float": 0
1337 },
1338 "StructMaps": {
1339 "MapBool": {},
1340 "MapString": {},
1341 "MapBytes": {},
1342 "MapInt": {},
1343 "MapUint": {},
1344 "MapFloat": {}
1345 },
1346 "StructSlices": {
1347 "SliceBool": [],
1348 "SliceString": [],
1349 "SliceBytes": [],
1350 "SliceInt": [],
1351 "SliceUint": [],
1352 "SliceFloat": []
1353 },
1354 "Slice": [],
1355 "Array": [
1356 ""
1357 ],
1358 "Pointer": null,
1359 "Interface": null
1360 },
1361 "Interface": null
1362 }`,
1363 }, {
1364 name: jsontest.Name("Structs/SpaceAfterColonAndComma"),
1365 opts: []Options{jsontext.SpaceAfterColon(true), jsontext.SpaceAfterComma(true)},
1366 in: structOmitZeroAll{Int: 1, Uint: 1},
1367 want: `{"Int": 1, "Uint": 1}`,
1368 }, {
1369 name: jsontest.Name("Structs/SpaceAfterColon"),
1370 opts: []Options{jsontext.SpaceAfterColon(true)},
1371 in: structOmitZeroAll{Int: 1, Uint: 1},
1372 want: `{"Int": 1,"Uint": 1}`,
1373 }, {
1374 name: jsontest.Name("Structs/SpaceAfterComma"),
1375 opts: []Options{jsontext.SpaceAfterComma(true)},
1376 in: structOmitZeroAll{Int: 1, Uint: 1, Slice: []string{"a", "b"}},
1377 want: `{"Int":1, "Uint":1, "Slice":["a", "b"]}`,
1378 }, {
1379 name: jsontest.Name("Structs/Stringified"),
1380 opts: []Options{jsontext.Multiline(true)},
1381 in: structStringified{
1382 Int: -64,
1383 Uint: +64,
1384 Float: 3.14159,
1385 PointerInt: new(int64(-64)),
1386 PointerUint: new(uint64(+64)),
1387 PointerFloat: new(float64(3.14159)),
1388 },
1389 want: `{
1390 "Int": "-64",
1391 "Uint": "64",
1392 "Float": "3.14159",
1393 "PointerInt": "-64",
1394 "PointerUint": "64",
1395 "PointerFloat": "3.14159"
1396 }`,
1397 }, {
1398 name: jsontest.Name("Structs/LegacyStringified"),
1399 opts: []Options{jsontext.Multiline(true), jsonflags.StringifyWithLegacySemantics | 1},
1400 in: structStringifiedLegacy{
1401 Bool: true,
1402 String: "hello",
1403 Int: -64,
1404 Uint: +64,
1405 Float: 3.14159,
1406 PointerBool: new(true),
1407 PointerString: new("hello"),
1408 PointerInt: new(int64(-64)),
1409 PointerUint: new(uint64(+64)),
1410 PointerFloat: new(float64(3.14159)),
1411 },
1412 want: `{
1413 "Bool": "true",
1414 "String": "\"hello\"",
1415 "Int": "-64",
1416 "Uint": "64",
1417 "Float": "3.14159",
1418 "PointerBool": "true",
1419 "PointerString": "\"hello\"",
1420 "PointerInt": "-64",
1421 "PointerUint": "64",
1422 "PointerFloat": "3.14159"
1423 }`,
1424 }, {
1425 name: jsontest.Name("Structs/Stringified/Invalid/Bool"),
1426 in: structStringifiedBool{},
1427 want: `{"Bool"`,
1428 wantErr: EM(errInvalidStringTag).withPos(`{"Bool":`, "/Bool").withType(0, boolType),
1429 }, {
1430 name: jsontest.Name("Structs/Stringified/Ignored/Bool"),
1431 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1432 in: structStringifiedBool{},
1433 want: `{"Bool":false}`,
1434 }, {
1435 name: jsontest.Name("Structs/Stringified/Invalid/String"),
1436 in: structStringifiedString{},
1437 want: `{"String"`,
1438 wantErr: EM(errInvalidStringTag).withPos(`{"String":`, "/String").withType(0, stringType),
1439 }, {
1440 name: jsontest.Name("Structs/Stringified/Ignored/String"),
1441 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1442 in: structStringifiedString{},
1443 want: `{"String":""}`,
1444 }, {
1445 name: jsontest.Name("Structs/Stringified/Invalid/Bytes"),
1446 in: structStringifiedBytes{},
1447 want: `{"Bytes"`,
1448 wantErr: EM(errInvalidStringTag).withPos(`{"Bytes":`, "/Bytes").withType(0, bytesType),
1449 }, {
1450 name: jsontest.Name("Structs/Stringified/Ignored/Bytes"),
1451 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1452 in: structStringifiedBytes{},
1453 want: `{"Bytes":""}`,
1454 }, {
1455 name: jsontest.Name("Structs/Stringified/Invalid/Map"),
1456 in: structStringifiedMap{},
1457 want: `{"Map"`,
1458 wantErr: EM(errInvalidStringTag).withPos(`{"Map":`, "/Map").withType(0, reflect.TypeFor[map[string]string]()),
1459 }, {
1460 name: jsontest.Name("Structs/Stringified/Ignored/Map"),
1461 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1462 in: structStringifiedMap{},
1463 want: `{"Map":{}}`,
1464 }, {
1465 name: jsontest.Name("Structs/Stringified/Invalid/Slice"),
1466 in: structStringifiedSlice{},
1467 want: `{"Slice"`,
1468 wantErr: EM(errInvalidStringTag).withPos(`{"Slice":`, "/Slice").withType(0, reflect.TypeFor[[]string]()),
1469 }, {
1470 name: jsontest.Name("Structs/Stringified/Ignored/Slice"),
1471 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1472 in: structStringifiedSlice{},
1473 want: `{"Slice":[]}`,
1474 }, {
1475 name: jsontest.Name("Structs/Stringified/Invalid/Array"),
1476 in: structStringifiedArray{},
1477 want: `{"Array"`,
1478 wantErr: EM(errInvalidStringTag).withPos(`{"Array":`, "/Array").withType(0, reflect.TypeFor[[1]string]()),
1479 }, {
1480 name: jsontest.Name("Structs/Stringified/Ignored/Array"),
1481 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1482 in: structStringifiedArray{},
1483 want: `{"Array":[""]}`,
1484 }, {
1485 name: jsontest.Name("Structs/Stringified/Invalid/Struct"),
1486 in: structStringifiedStruct{},
1487 want: `{"Struct"`,
1488 wantErr: EM(errInvalidStringTag).withPos(`{"Struct":`, "/Struct").withType(0, reflect.TypeFor[structAll]()),
1489 }, {
1490 name: jsontest.Name("Structs/Stringified/Ignored/Struct"),
1491 opts: []Options{jsontext.Multiline(true), jsonflags.ReportErrorsWithLegacySemantics | 1},
1492 in: structStringifiedStruct{},
1493 want: `{
1494 "Struct": {
1495 "Bool": false,
1496 "String": "",
1497 "Bytes": "",
1498 "Int": 0,
1499 "Uint": 0,
1500 "Float": 0,
1501 "Map": {},
1502 "StructScalars": {
1503 "Bool": false,
1504 "String": "",
1505 "Bytes": "",
1506 "Int": 0,
1507 "Uint": 0,
1508 "Float": 0
1509 },
1510 "StructMaps": {
1511 "MapBool": {},
1512 "MapString": {},
1513 "MapBytes": {},
1514 "MapInt": {},
1515 "MapUint": {},
1516 "MapFloat": {}
1517 },
1518 "StructSlices": {
1519 "SliceBool": [],
1520 "SliceString": [],
1521 "SliceBytes": [],
1522 "SliceInt": [],
1523 "SliceUint": [],
1524 "SliceFloat": []
1525 },
1526 "Slice": [],
1527 "Array": [
1528 ""
1529 ],
1530 "Pointer": null,
1531 "Interface": null
1532 }
1533 }`,
1534 }, {
1535 name: jsontest.Name("Structs/Stringified/Invalid/Pointer"),
1536 in: structStringifiedPointer{},
1537 want: `{"Pointer":null}`,
1538 }, {
1539 name: jsontest.Name("Structs/Stringified/Ignored/Pointer"),
1540 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1541 in: structStringifiedPointer{},
1542 want: `{"Pointer":null}`,
1543 }, {
1544 name: jsontest.Name("Structs/Stringified/PointerPointerInt"),
1545 in: structStringifiedPointerPointerInt{Pointer: new(new(5))},
1546 want: `{"Pointer":"5"}`,
1547 }, {
1548 name: jsontest.Name("Structs/Stringified/Invalid/Interface"),
1549 in: structStringifiedInterface{Interface: 1000},
1550 want: `{"Interface"`,
1551 wantErr: EM(errInvalidStringTag).withPos(`{"Interface":`, "/Interface").withType(0, anyType),
1552 }, {
1553 name: jsontest.Name("Structs/Stringified/Ignored/Interface"),
1554 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
1555 in: structStringifiedInterface{Interface: 1000},
1556 want: `{"Interface":"1000"}`,
1557 }, {
1558 name: jsontest.Name("Structs/LegacyStringified/Invalid/Bytes"),
1559 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1560 want: `{"Bytes"`,
1561 wantErr: EM(errInvalidStringTag).withPos(`{"Bytes":`, "/Bytes").withType(0, bytesType),
1562 in: structStringifiedBytes{},
1563 }, {
1564 name: jsontest.Name("Structs/LegacyStringified/Ignored/Bytes"),
1565 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
1566 in: structStringifiedBytes{},
1567 want: `{"Bytes":""}`,
1568 }, {
1569 name: jsontest.Name("Structs/LegacyStringified/Invalid/Map"),
1570 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1571 in: structStringifiedMap{},
1572 want: `{"Map"`,
1573 wantErr: EM(errInvalidStringTag).withPos(`{"Map":`, "/Map").withType(0, reflect.TypeFor[map[string]string]()),
1574 }, {
1575 name: jsontest.Name("Structs/LegacyStringified/Ignored/Map"),
1576 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
1577 in: structStringifiedMap{},
1578 want: `{"Map":{}}`,
1579 }, {
1580 name: jsontest.Name("Structs/LegacyStringified/Invalid/Slice"),
1581 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1582 in: structStringifiedSlice{},
1583 want: `{"Slice"`,
1584 wantErr: EM(errInvalidStringTag).withPos(`{"Slice":`, "/Slice").withType(0, reflect.TypeFor[[]string]()),
1585 }, {
1586 name: jsontest.Name("Structs/LegacyStringified/Ignored/Slice"),
1587 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
1588 in: structStringifiedSlice{},
1589 want: `{"Slice":[]}`,
1590 }, {
1591 name: jsontest.Name("Structs/LegacyStringified/Invalid/Array"),
1592 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1593 in: structStringifiedArray{},
1594 want: `{"Array"`,
1595 wantErr: EM(errInvalidStringTag).withPos(`{"Array":`, "/Array").withType(0, reflect.TypeFor[[1]string]()),
1596 }, {
1597 name: jsontest.Name("Structs/LegacyStringified/Ignored/Array"),
1598 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
1599 in: structStringifiedArray{},
1600 want: `{"Array":[""]}`,
1601 }, {
1602 name: jsontest.Name("Structs/LegacyStringified/Invalid/Struct"),
1603 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1604 in: structStringifiedStruct{},
1605 want: `{"Struct"`,
1606 wantErr: EM(errInvalidStringTag).withPos(`{"Struct":`, "/Struct").withType(0, reflect.TypeFor[structAll]()),
1607 }, {
1608 name: jsontest.Name("Structs/LegacyStringified/Ignored/Struct"),
1609 opts: []Options{jsontext.Multiline(true), jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
1610 in: structStringifiedStruct{},
1611 want: `{
1612 "Struct": {
1613 "Bool": false,
1614 "String": "",
1615 "Bytes": "",
1616 "Int": 0,
1617 "Uint": 0,
1618 "Float": 0,
1619 "Map": {},
1620 "StructScalars": {
1621 "Bool": false,
1622 "String": "",
1623 "Bytes": "",
1624 "Int": 0,
1625 "Uint": 0,
1626 "Float": 0
1627 },
1628 "StructMaps": {
1629 "MapBool": {},
1630 "MapString": {},
1631 "MapBytes": {},
1632 "MapInt": {},
1633 "MapUint": {},
1634 "MapFloat": {}
1635 },
1636 "StructSlices": {
1637 "SliceBool": [],
1638 "SliceString": [],
1639 "SliceBytes": [],
1640 "SliceInt": [],
1641 "SliceUint": [],
1642 "SliceFloat": []
1643 },
1644 "Slice": [],
1645 "Array": [
1646 ""
1647 ],
1648 "Pointer": null,
1649 "Interface": null
1650 }
1651 }`,
1652 }, {
1653 name: jsontest.Name("Structs/LegacyStringified/Invalid/Pointer"),
1654 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1655 in: structStringifiedPointer{Pointer: new(structAll)},
1656 want: `{"Pointer"`,
1657 wantErr: EM(errInvalidStringTag).withPos(`{"Pointer":`, "/Pointer").withType(0, reflect.TypeFor[structAll]()),
1658 }, {
1659 name: jsontest.Name("Structs/LegacyStringified/Ignored/Pointer"),
1660 opts: []Options{jsontext.Multiline(true), jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
1661 in: structStringifiedPointer{Pointer: new(structAll)},
1662 want: `{
1663 "Pointer": {
1664 "Bool": false,
1665 "String": "",
1666 "Bytes": "",
1667 "Int": 0,
1668 "Uint": 0,
1669 "Float": 0,
1670 "Map": {},
1671 "StructScalars": {
1672 "Bool": false,
1673 "String": "",
1674 "Bytes": "",
1675 "Int": 0,
1676 "Uint": 0,
1677 "Float": 0
1678 },
1679 "StructMaps": {
1680 "MapBool": {},
1681 "MapString": {},
1682 "MapBytes": {},
1683 "MapInt": {},
1684 "MapUint": {},
1685 "MapFloat": {}
1686 },
1687 "StructSlices": {
1688 "SliceBool": [],
1689 "SliceString": [],
1690 "SliceBytes": [],
1691 "SliceInt": [],
1692 "SliceUint": [],
1693 "SliceFloat": []
1694 },
1695 "Slice": [],
1696 "Array": [
1697 ""
1698 ],
1699 "Pointer": null,
1700 "Interface": null
1701 }
1702 }`,
1703 }, {
1704 name: jsontest.Name("Structs/LegacyStringified/Invalid/PointerPointerInt"),
1705 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1706 in: structStringifiedPointerPointerInt{Pointer: new(new(5))},
1707 want: `{"Pointer"`,
1708 wantErr: EM(errInvalidStringTag).withPos(`{"Pointer":`, "/Pointer").withType(0, reflect.TypeFor[**int]()),
1709 }, {
1710 name: jsontest.Name("Structs/LegacyStringified/Ignored/PointerPointerInt"),
1711 opts: []Options{jsonflags.StringifyWithLegacySemantics | jsonflags.ReportErrorsWithLegacySemantics | 1},
1712 in: structStringifiedPointerPointerInt{Pointer: new(new(5))},
1713 want: `{"Pointer":5}`,
1714 }, {
1715 name: jsontest.Name("Structs/LegacyStringified/Invalid/Interface"),
1716 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
1717 in: structStringifiedInterface{},
1718 want: `{"Interface"`,
1719 wantErr: EM(errInvalidStringTag).withPos(`{"Interface":`, "/Interface").withType(0, anyType),
1720 }, {
1721 name: jsontest.Name("Structs/LegacyStringified/Ignored/Interface"),
1722 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
1723 in: structStringifiedInterface{Interface: 1000},
1724 want: `{"Interface":1000}`,
1725 }, {
1726 name: jsontest.Name("Structs/OmitZero/Zero"),
1727 in: structOmitZeroAll{},
1728 want: `{}`,
1729 }, {
1730 name: jsontest.Name("Structs/OmitZeroOption/Zero"),
1731 opts: []Options{OmitZeroStructFields(true)},
1732 in: structAll{},
1733 want: `{}`,
1734 }, {
1735 name: jsontest.Name("Structs/OmitZero/NonZero"),
1736 opts: []Options{jsontext.Multiline(true)},
1737 in: structOmitZeroAll{
1738 Bool: true,
1739 String: " ",
1740 Bytes: []byte{},
1741 Int: 1,
1742 Uint: 1,
1743 Float: math.SmallestNonzeroFloat64,
1744 Map: map[string]string{},
1745 StructScalars: structScalars{unexported: true},
1746 StructSlices: structSlices{Ignored: true},
1747 StructMaps: structMaps{MapBool: map[string]bool{}},
1748 Slice: []string{},
1749 Array: [1]string{" "},
1750 Pointer: new(structOmitZeroAll),
1751 Interface: (*structOmitZeroAll)(nil),
1752 },
1753 want: `{
1754 "Bool": true,
1755 "String": " ",
1756 "Bytes": "",
1757 "Int": 1,
1758 "Uint": 1,
1759 "Float": 5e-324,
1760 "Map": {},
1761 "StructScalars": {
1762 "Bool": false,
1763 "String": "",
1764 "Bytes": "",
1765 "Int": 0,
1766 "Uint": 0,
1767 "Float": 0
1768 },
1769 "StructMaps": {
1770 "MapBool": {},
1771 "MapString": {},
1772 "MapBytes": {},
1773 "MapInt": {},
1774 "MapUint": {},
1775 "MapFloat": {}
1776 },
1777 "StructSlices": {
1778 "SliceBool": [],
1779 "SliceString": [],
1780 "SliceBytes": [],
1781 "SliceInt": [],
1782 "SliceUint": [],
1783 "SliceFloat": []
1784 },
1785 "Slice": [],
1786 "Array": [
1787 " "
1788 ],
1789 "Pointer": {},
1790 "Interface": null
1791 }`,
1792 }, {
1793 name: jsontest.Name("Structs/OmitZeroOption/NonZero"),
1794 opts: []Options{OmitZeroStructFields(true), jsontext.Multiline(true)},
1795 in: structAll{
1796 Bool: true,
1797 String: " ",
1798 Bytes: []byte{},
1799 Int: 1,
1800 Uint: 1,
1801 Float: math.SmallestNonzeroFloat64,
1802 Map: map[string]string{},
1803 StructScalars: structScalars{unexported: true},
1804 StructSlices: structSlices{Ignored: true},
1805 StructMaps: structMaps{MapBool: map[string]bool{}},
1806 Slice: []string{},
1807 Array: [1]string{" "},
1808 Pointer: new(structAll),
1809 Interface: (*structAll)(nil),
1810 },
1811 want: `{
1812 "Bool": true,
1813 "String": " ",
1814 "Bytes": "",
1815 "Int": 1,
1816 "Uint": 1,
1817 "Float": 5e-324,
1818 "Map": {},
1819 "StructScalars": {},
1820 "StructMaps": {
1821 "MapBool": {}
1822 },
1823 "StructSlices": {},
1824 "Slice": [],
1825 "Array": [
1826 " "
1827 ],
1828 "Pointer": {},
1829 "Interface": null
1830 }`,
1831 }, {
1832 name: jsontest.Name("Structs/OmitZeroMethod/Zero"),
1833 in: structOmitZeroMethodAll{},
1834 want: `{"ValueNeverZero":"","PointerNeverZero":""}`,
1835 }, {
1836 name: jsontest.Name("Structs/OmitZeroMethod/NonZero"),
1837 opts: []Options{jsontext.Multiline(true)},
1838 in: structOmitZeroMethodAll{
1839 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1840 ValueNeverZero: valueNeverZero("nonzero"),
1841 PointerAlwaysZero: pointerAlwaysZero("nonzero"),
1842 PointerNeverZero: pointerNeverZero("nonzero"),
1843 PointerValueAlwaysZero: new(valueAlwaysZero("nonzero")),
1844 PointerValueNeverZero: new(valueNeverZero("nonzero")),
1845 PointerPointerAlwaysZero: new(pointerAlwaysZero("nonzero")),
1846 PointerPointerNeverZero: new(pointerNeverZero("nonzero")),
1847 PointerPointerValueAlwaysZero: new(new(valueAlwaysZero("nonzero"))),
1848 PointerPointerValueNeverZero: new(new(valueNeverZero("nonzero"))),
1849 PointerPointerPointerAlwaysZero: new(new(pointerAlwaysZero("nonzero"))),
1850 PointerPointerPointerNeverZero: new(new(pointerNeverZero("nonzero"))),
1851 },
1852 want: `{
1853 "ValueNeverZero": "nonzero",
1854 "PointerNeverZero": "nonzero",
1855 "PointerValueNeverZero": "nonzero",
1856 "PointerPointerNeverZero": "nonzero",
1857 "PointerPointerValueAlwaysZero": "nonzero",
1858 "PointerPointerValueNeverZero": "nonzero",
1859 "PointerPointerPointerAlwaysZero": "nonzero",
1860 "PointerPointerPointerNeverZero": "nonzero"
1861 }`,
1862 }, {
1863 name: jsontest.Name("Structs/OmitZeroMethod/Interface/Zero"),
1864 opts: []Options{jsontext.Multiline(true)},
1865 in: structOmitZeroMethodInterfaceAll{},
1866 want: `{}`,
1867 }, {
1868 name: jsontest.Name("Structs/OmitZeroMethod/Interface/PartialZero"),
1869 opts: []Options{jsontext.Multiline(true)},
1870 in: structOmitZeroMethodInterfaceAll{
1871 ValueAlwaysZero: valueAlwaysZero(""),
1872 ValueNeverZero: valueNeverZero(""),
1873 PointerValueAlwaysZero: (*valueAlwaysZero)(nil),
1874 PointerValueNeverZero: (*valueNeverZero)(nil),
1875 PointerPointerAlwaysZero: (*pointerAlwaysZero)(nil),
1876 PointerPointerNeverZero: (*pointerNeverZero)(nil),
1877 },
1878 want: `{
1879 "ValueNeverZero": ""
1880 }`,
1881 }, {
1882 name: jsontest.Name("Structs/OmitZeroMethod/Interface/NonZero"),
1883 opts: []Options{jsontext.Multiline(true)},
1884 in: structOmitZeroMethodInterfaceAll{
1885 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1886 ValueNeverZero: valueNeverZero("nonzero"),
1887 PointerValueAlwaysZero: new(valueAlwaysZero("nonzero")),
1888 PointerValueNeverZero: new(valueNeverZero("nonzero")),
1889 PointerPointerAlwaysZero: new(pointerAlwaysZero("nonzero")),
1890 PointerPointerNeverZero: new(pointerNeverZero("nonzero")),
1891 },
1892 want: `{
1893 "ValueNeverZero": "nonzero",
1894 "PointerValueNeverZero": "nonzero",
1895 "PointerPointerNeverZero": "nonzero"
1896 }`,
1897 }, {
1898 name: jsontest.Name("Structs/OmitEmpty/Zero"),
1899 opts: []Options{jsontext.Multiline(true)},
1900 in: structOmitEmptyAll{},
1901 want: `{
1902 "Bool": false,
1903 "StringNonEmpty": "value",
1904 "BytesNonEmpty": [
1905 "value"
1906 ],
1907 "Float": 0,
1908 "MapNonEmpty": {
1909 "key": "value"
1910 },
1911 "SliceNonEmpty": [
1912 "value"
1913 ]
1914 }`,
1915 }, {
1916 name: jsontest.Name("Structs/OmitEmpty/EmptyNonZero"),
1917 opts: []Options{jsontext.Multiline(true)},
1918 in: structOmitEmptyAll{
1919 String: string(""),
1920 StringEmpty: stringMarshalEmpty(""),
1921 StringNonEmpty: stringMarshalNonEmpty(""),
1922 PointerString: new(string("")),
1923 PointerStringEmpty: new(stringMarshalEmpty("")),
1924 PointerStringNonEmpty: new(stringMarshalNonEmpty("")),
1925 Bytes: []byte(""),
1926 BytesEmpty: bytesMarshalEmpty([]byte("")),
1927 BytesNonEmpty: bytesMarshalNonEmpty([]byte("")),
1928 PointerBytes: new([]byte("")),
1929 PointerBytesEmpty: new(bytesMarshalEmpty([]byte(""))),
1930 PointerBytesNonEmpty: new(bytesMarshalNonEmpty([]byte(""))),
1931 Map: map[string]string{},
1932 MapEmpty: mapMarshalEmpty{},
1933 MapNonEmpty: mapMarshalNonEmpty{},
1934 PointerMap: new(map[string]string{}),
1935 PointerMapEmpty: new(mapMarshalEmpty{}),
1936 PointerMapNonEmpty: new(mapMarshalNonEmpty{}),
1937 Slice: []string{},
1938 SliceEmpty: sliceMarshalEmpty{},
1939 SliceNonEmpty: sliceMarshalNonEmpty{},
1940 PointerSlice: new([]string{}),
1941 PointerSliceEmpty: new(sliceMarshalEmpty{}),
1942 PointerSliceNonEmpty: new(sliceMarshalNonEmpty{}),
1943 Pointer: &structOmitZeroEmptyAll{},
1944 Interface: []string{},
1945 },
1946 want: `{
1947 "Bool": false,
1948 "StringNonEmpty": "value",
1949 "PointerStringNonEmpty": "value",
1950 "BytesNonEmpty": [
1951 "value"
1952 ],
1953 "PointerBytesNonEmpty": [
1954 "value"
1955 ],
1956 "Float": 0,
1957 "MapNonEmpty": {
1958 "key": "value"
1959 },
1960 "PointerMapNonEmpty": {
1961 "key": "value"
1962 },
1963 "SliceNonEmpty": [
1964 "value"
1965 ],
1966 "PointerSliceNonEmpty": [
1967 "value"
1968 ]
1969 }`,
1970 }, {
1971 name: jsontest.Name("Structs/OmitEmpty/NonEmpty"),
1972 opts: []Options{jsontext.Multiline(true)},
1973 in: structOmitEmptyAll{
1974 Bool: true,
1975 PointerBool: new(true),
1976 String: string("value"),
1977 StringEmpty: stringMarshalEmpty("value"),
1978 StringNonEmpty: stringMarshalNonEmpty("value"),
1979 PointerString: new(string("value")),
1980 PointerStringEmpty: new(stringMarshalEmpty("value")),
1981 PointerStringNonEmpty: new(stringMarshalNonEmpty("value")),
1982 Bytes: []byte("value"),
1983 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1984 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1985 PointerBytes: new([]byte("value")),
1986 PointerBytesEmpty: new(bytesMarshalEmpty([]byte("value"))),
1987 PointerBytesNonEmpty: new(bytesMarshalNonEmpty([]byte("value"))),
1988 Float: math.Copysign(0, -1),
1989 PointerFloat: new(math.Copysign(0, -1)),
1990 Map: map[string]string{"": ""},
1991 MapEmpty: mapMarshalEmpty{"key": "value"},
1992 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1993 PointerMap: new(map[string]string{"": ""}),
1994 PointerMapEmpty: new(mapMarshalEmpty{"key": "value"}),
1995 PointerMapNonEmpty: new(mapMarshalNonEmpty{"key": "value"}),
1996 Slice: []string{""},
1997 SliceEmpty: sliceMarshalEmpty{"value"},
1998 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1999 PointerSlice: new([]string{""}),
2000 PointerSliceEmpty: new(sliceMarshalEmpty{"value"}),
2001 PointerSliceNonEmpty: new(sliceMarshalNonEmpty{"value"}),
2002 Pointer: &structOmitZeroEmptyAll{Float: math.SmallestNonzeroFloat64},
2003 Interface: []string{""},
2004 },
2005 want: `{
2006 "Bool": true,
2007 "PointerBool": true,
2008 "String": "value",
2009 "StringNonEmpty": "value",
2010 "PointerString": "value",
2011 "PointerStringNonEmpty": "value",
2012 "Bytes": "dmFsdWU=",
2013 "BytesNonEmpty": [
2014 "value"
2015 ],
2016 "PointerBytes": "dmFsdWU=",
2017 "PointerBytesNonEmpty": [
2018 "value"
2019 ],
2020 "Float": -0,
2021 "PointerFloat": -0,
2022 "Map": {
2023 "": ""
2024 },
2025 "MapNonEmpty": {
2026 "key": "value"
2027 },
2028 "PointerMap": {
2029 "": ""
2030 },
2031 "PointerMapNonEmpty": {
2032 "key": "value"
2033 },
2034 "Slice": [
2035 ""
2036 ],
2037 "SliceNonEmpty": [
2038 "value"
2039 ],
2040 "PointerSlice": [
2041 ""
2042 ],
2043 "PointerSliceNonEmpty": [
2044 "value"
2045 ],
2046 "Pointer": {
2047 "Float": 5e-324
2048 },
2049 "Interface": [
2050 ""
2051 ]
2052 }`,
2053 }, {
2054 name: jsontest.Name("Structs/OmitEmpty/Legacy/Zero"),
2055 opts: []Options{jsonflags.OmitEmptyWithLegacySemantics | 1},
2056 in: structOmitEmptyAll{},
2057 want: `{}`,
2058 }, {
2059 name: jsontest.Name("Structs/OmitEmpty/Legacy/NonEmpty"),
2060 opts: []Options{jsontext.Multiline(true), jsonflags.OmitEmptyWithLegacySemantics | 1},
2061 in: structOmitEmptyAll{
2062 Bool: true,
2063 PointerBool: new(true),
2064 String: string("value"),
2065 StringEmpty: stringMarshalEmpty("value"),
2066 StringNonEmpty: stringMarshalNonEmpty("value"),
2067 PointerString: new(string("value")),
2068 PointerStringEmpty: new(stringMarshalEmpty("value")),
2069 PointerStringNonEmpty: new(stringMarshalNonEmpty("value")),
2070 Bytes: []byte("value"),
2071 BytesEmpty: bytesMarshalEmpty([]byte("value")),
2072 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
2073 PointerBytes: new([]byte("value")),
2074 PointerBytesEmpty: new(bytesMarshalEmpty([]byte("value"))),
2075 PointerBytesNonEmpty: new(bytesMarshalNonEmpty([]byte("value"))),
2076 Float: math.Copysign(0, -1),
2077 PointerFloat: new(math.Copysign(0, -1)),
2078 Map: map[string]string{"": ""},
2079 MapEmpty: mapMarshalEmpty{"key": "value"},
2080 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
2081 PointerMap: new(map[string]string{"": ""}),
2082 PointerMapEmpty: new(mapMarshalEmpty{"key": "value"}),
2083 PointerMapNonEmpty: new(mapMarshalNonEmpty{"key": "value"}),
2084 Slice: []string{""},
2085 SliceEmpty: sliceMarshalEmpty{"value"},
2086 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
2087 PointerSlice: new([]string{""}),
2088 PointerSliceEmpty: new(sliceMarshalEmpty{"value"}),
2089 PointerSliceNonEmpty: new(sliceMarshalNonEmpty{"value"}),
2090 Pointer: &structOmitZeroEmptyAll{Float: math.Copysign(0, -1)},
2091 Interface: []string{""},
2092 },
2093 want: `{
2094 "Bool": true,
2095 "PointerBool": true,
2096 "String": "value",
2097 "StringEmpty": "",
2098 "StringNonEmpty": "value",
2099 "PointerString": "value",
2100 "PointerStringEmpty": "",
2101 "PointerStringNonEmpty": "value",
2102 "Bytes": "dmFsdWU=",
2103 "BytesEmpty": [],
2104 "BytesNonEmpty": [
2105 "value"
2106 ],
2107 "PointerBytes": "dmFsdWU=",
2108 "PointerBytesEmpty": [],
2109 "PointerBytesNonEmpty": [
2110 "value"
2111 ],
2112 "PointerFloat": -0,
2113 "Map": {
2114 "": ""
2115 },
2116 "MapEmpty": {},
2117 "MapNonEmpty": {
2118 "key": "value"
2119 },
2120 "PointerMap": {
2121 "": ""
2122 },
2123 "PointerMapEmpty": {},
2124 "PointerMapNonEmpty": {
2125 "key": "value"
2126 },
2127 "Slice": [
2128 ""
2129 ],
2130 "SliceEmpty": [],
2131 "SliceNonEmpty": [
2132 "value"
2133 ],
2134 "PointerSlice": [
2135 ""
2136 ],
2137 "PointerSliceEmpty": [],
2138 "PointerSliceNonEmpty": [
2139 "value"
2140 ],
2141 "Pointer": {},
2142 "Interface": [
2143 ""
2144 ]
2145 }`,
2146 }, {
2147 name: jsontest.Name("Structs/OmitEmpty/NonEmptyString"),
2148 in: struct {
2149 X string `json:",omitempty"`
2150 }{`"`},
2151 want: `{"X":"\""}`,
2152 }, {
2153 name: jsontest.Name("Structs/OmitZeroEmpty/Zero"),
2154 in: structOmitZeroEmptyAll{},
2155 want: `{}`,
2156 }, {
2157 name: jsontest.Name("Structs/OmitZeroEmpty/Empty"),
2158 in: structOmitZeroEmptyAll{
2159 Bytes: []byte{},
2160 Map: map[string]string{},
2161 Slice: []string{},
2162 Pointer: &structOmitZeroEmptyAll{},
2163 Interface: []string{},
2164 },
2165 want: `{}`,
2166 }, {
2167 name: jsontest.Name("Structs/OmitEmpty/PathologicalDepth"),
2168 in: func() any {
2169 type X struct {
2170 X *X `json:",omitempty"`
2171 }
2172 var make func(int) *X
2173 make = func(n int) *X {
2174 if n == 0 {
2175 return nil
2176 }
2177 return &X{make(n - 1)}
2178 }
2179 return make(100)
2180 }(),
2181 want: `{}`,
2182 useWriter: true,
2183 }, {
2184 name: jsontest.Name("Structs/OmitEmpty/PathologicalBreadth"),
2185 in: func() any {
2186 var fields []reflect.StructField
2187 for i := range 100 {
2188 fields = append(fields, reflect.StructField{
2189 Name: fmt.Sprintf("X%d", i),
2190 Type: T[stringMarshalEmpty](),
2191 Tag: `json:",omitempty"`,
2192 })
2193 }
2194 return reflect.New(reflect.StructOf(fields)).Interface()
2195 }(),
2196 want: `{}`,
2197 useWriter: true,
2198 }, {
2199 name: jsontest.Name("Structs/OmitEmpty/PathologicalTree"),
2200 in: func() any {
2201 type X struct {
2202 XL, XR *X `json:",omitempty"`
2203 }
2204 var make func(int) *X
2205 make = func(n int) *X {
2206 if n == 0 {
2207 return nil
2208 }
2209 return &X{make(n - 1), make(n - 1)}
2210 }
2211 return make(8)
2212 }(),
2213 want: `{}`,
2214 useWriter: true,
2215 }, {
2216 name: jsontest.Name("Structs/OmitZeroEmpty/NonEmpty"),
2217 in: structOmitZeroEmptyAll{
2218 Bytes: []byte("value"),
2219 Map: map[string]string{"": ""},
2220 Slice: []string{""},
2221 Pointer: &structOmitZeroEmptyAll{Bool: true},
2222 Interface: []string{""},
2223 },
2224 want: `{"Bytes":"dmFsdWU=","Map":{"":""},"Slice":[""],"Pointer":{"Bool":true},"Interface":[""]}`,
2225 }, {
2226 name: jsontest.Name("Structs/Format/Bytes/Unsupported"),
2227 opts: []Options{jsontext.Multiline(true)},
2228 in: structFormatBytes{},
2229 wantErr: EM(errors.New("Go struct field Base16 has unsupported `format` tag option")).withType(0, T[structFormatBytes]()),
2230 }, {
2231 name: jsontest.Name("Structs/Format/Bytes"),
2232 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true)},
2233 in: structFormatBytes{
2234 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
2235 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2236 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2237 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߿"),
2238 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߿"),
2239 Array: []byte{1, 2, 3, 4},
2240 },
2241 want: `{
2242 "Base16": "0123456789abcdef",
2243 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
2244 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
2245 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
2246 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
2247 "Array": [
2248 1,
2249 2,
2250 3,
2251 4
2252 ]
2253 }`,
2254 }, {
2255 name: jsontest.Name("Structs/Format/ArrayBytes"),
2256 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true)},
2257 in: structFormatArrayBytes{
2258 Base16: [4]byte{1, 2, 3, 4},
2259 Base32: [4]byte{1, 2, 3, 4},
2260 Base32Hex: [4]byte{1, 2, 3, 4},
2261 Base64: [4]byte{1, 2, 3, 4},
2262 Base64URL: [4]byte{1, 2, 3, 4},
2263 Array: [4]byte{1, 2, 3, 4},
2264 Default: [4]byte{1, 2, 3, 4},
2265 },
2266 want: `{
2267 "Base16": "01020304",
2268 "Base32": "AEBAGBA=",
2269 "Base32Hex": "0410610=",
2270 "Base64": "AQIDBA==",
2271 "Base64URL": "AQIDBA==",
2272 "Array": [
2273 1,
2274 2,
2275 3,
2276 4
2277 ],
2278 "Default": "AQIDBA=="
2279 }`,
2280 }, {
2281 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
2282 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true), jsonflags.FormatByteArrayAsArray | jsonflags.FormatBytesWithLegacySemantics | 1},
2283 in: structFormatArrayBytes{
2284 Base16: [4]byte{1, 2, 3, 4},
2285 Base32: [4]byte{1, 2, 3, 4},
2286 Base32Hex: [4]byte{1, 2, 3, 4},
2287 Base64: [4]byte{1, 2, 3, 4},
2288 Base64URL: [4]byte{1, 2, 3, 4},
2289 Array: [4]byte{1, 2, 3, 4},
2290 Default: [4]byte{1, 2, 3, 4},
2291 },
2292 want: `{
2293 "Base16": "01020304",
2294 "Base32": "AEBAGBA=",
2295 "Base32Hex": "0410610=",
2296 "Base64": "AQIDBA==",
2297 "Base64URL": "AQIDBA==",
2298 "Array": [
2299 1,
2300 2,
2301 3,
2302 4
2303 ],
2304 "Default": [
2305 1,
2306 2,
2307 3,
2308 4
2309 ]
2310 }`,
2311 }, {
2312 name: jsontest.Name("Structs/Format/Bytes/Array"),
2313 opts: []Options{
2314 jsonopts.ExperimentalSupportFormatTag(true),
2315 WithMarshalers(MarshalFunc(func(in byte) ([]byte, error) {
2316 if in > 3 {
2317 return []byte("true"), nil
2318 } else {
2319 return []byte("false"), nil
2320 }
2321 })),
2322 },
2323 in: struct {
2324 Array []byte `json:",format:array"`
2325 }{
2326 Array: []byte{1, 6, 2, 5, 3, 4},
2327 },
2328 want: `{"Array":[false,true,false,true,false,true]}`,
2329 }, {
2330 name: jsontest.Name("Structs/Format/Floats"),
2331 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true)},
2332 in: []structFormatFloats{
2333 {NonFinite: math.Pi, PointerNonFinite: new(math.Pi)},
2334 {NonFinite: math.NaN(), PointerNonFinite: new(math.NaN())},
2335 {NonFinite: math.Inf(-1), PointerNonFinite: new(math.Inf(-1))},
2336 {NonFinite: math.Inf(+1), PointerNonFinite: new(math.Inf(+1))},
2337 },
2338 want: `[
2339 {
2340 "NonFinite": 3.141592653589793,
2341 "PointerNonFinite": 3.141592653589793
2342 },
2343 {
2344 "NonFinite": "NaN",
2345 "PointerNonFinite": "NaN"
2346 },
2347 {
2348 "NonFinite": "-Infinity",
2349 "PointerNonFinite": "-Infinity"
2350 },
2351 {
2352 "NonFinite": "Infinity",
2353 "PointerNonFinite": "Infinity"
2354 }
2355 ]`,
2356 }, {
2357 name: jsontest.Name("Structs/Format/Maps"),
2358 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true)},
2359 in: []structFormatMaps{{
2360 EmitNull: map[string]string(nil), PointerEmitNull: new(map[string]string(nil)),
2361 EmitEmpty: map[string]string(nil), PointerEmitEmpty: new(map[string]string(nil)),
2362 EmitDefault: map[string]string(nil), PointerEmitDefault: new(map[string]string(nil)),
2363 }, {
2364 EmitNull: map[string]string{}, PointerEmitNull: new(map[string]string{}),
2365 EmitEmpty: map[string]string{}, PointerEmitEmpty: new(map[string]string{}),
2366 EmitDefault: map[string]string{}, PointerEmitDefault: new(map[string]string{}),
2367 }, {
2368 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: new(map[string]string{"k": "v"}),
2369 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: new(map[string]string{"k": "v"}),
2370 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: new(map[string]string{"k": "v"}),
2371 }},
2372 want: `[
2373 {
2374 "EmitNull": null,
2375 "PointerEmitNull": null,
2376 "EmitEmpty": {},
2377 "PointerEmitEmpty": {},
2378 "EmitDefault": {},
2379 "PointerEmitDefault": {}
2380 },
2381 {
2382 "EmitNull": {},
2383 "PointerEmitNull": {},
2384 "EmitEmpty": {},
2385 "PointerEmitEmpty": {},
2386 "EmitDefault": {},
2387 "PointerEmitDefault": {}
2388 },
2389 {
2390 "EmitNull": {
2391 "k": "v"
2392 },
2393 "PointerEmitNull": {
2394 "k": "v"
2395 },
2396 "EmitEmpty": {
2397 "k": "v"
2398 },
2399 "PointerEmitEmpty": {
2400 "k": "v"
2401 },
2402 "EmitDefault": {
2403 "k": "v"
2404 },
2405 "PointerEmitDefault": {
2406 "k": "v"
2407 }
2408 }
2409 ]`,
2410 }, {
2411 name: jsontest.Name("Structs/Format/Maps/FormatNilMapAsNull"),
2412 opts: []Options{
2413 jsonopts.ExperimentalSupportFormatTag(true),
2414 FormatNilMapAsNull(true),
2415 jsontext.Multiline(true),
2416 },
2417 in: []structFormatMaps{{
2418 EmitNull: map[string]string(nil), PointerEmitNull: new(map[string]string(nil)),
2419 EmitEmpty: map[string]string(nil), PointerEmitEmpty: new(map[string]string(nil)),
2420 EmitDefault: map[string]string(nil), PointerEmitDefault: new(map[string]string(nil)),
2421 }, {
2422 EmitNull: map[string]string{}, PointerEmitNull: new(map[string]string{}),
2423 EmitEmpty: map[string]string{}, PointerEmitEmpty: new(map[string]string{}),
2424 EmitDefault: map[string]string{}, PointerEmitDefault: new(map[string]string{}),
2425 }, {
2426 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: new(map[string]string{"k": "v"}),
2427 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: new(map[string]string{"k": "v"}),
2428 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: new(map[string]string{"k": "v"}),
2429 }},
2430 want: `[
2431 {
2432 "EmitNull": null,
2433 "PointerEmitNull": null,
2434 "EmitEmpty": {},
2435 "PointerEmitEmpty": {},
2436 "EmitDefault": null,
2437 "PointerEmitDefault": null
2438 },
2439 {
2440 "EmitNull": {},
2441 "PointerEmitNull": {},
2442 "EmitEmpty": {},
2443 "PointerEmitEmpty": {},
2444 "EmitDefault": {},
2445 "PointerEmitDefault": {}
2446 },
2447 {
2448 "EmitNull": {
2449 "k": "v"
2450 },
2451 "PointerEmitNull": {
2452 "k": "v"
2453 },
2454 "EmitEmpty": {
2455 "k": "v"
2456 },
2457 "PointerEmitEmpty": {
2458 "k": "v"
2459 },
2460 "EmitDefault": {
2461 "k": "v"
2462 },
2463 "PointerEmitDefault": {
2464 "k": "v"
2465 }
2466 }
2467 ]`,
2468 }, {
2469 name: jsontest.Name("Structs/Format/Slices"),
2470 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true)},
2471 in: []structFormatSlices{{
2472 EmitNull: []string(nil), PointerEmitNull: new([]string(nil)),
2473 EmitEmpty: []string(nil), PointerEmitEmpty: new([]string(nil)),
2474 EmitDefault: []string(nil), PointerEmitDefault: new([]string(nil)),
2475 }, {
2476 EmitNull: []string{}, PointerEmitNull: new([]string{}),
2477 EmitEmpty: []string{}, PointerEmitEmpty: new([]string{}),
2478 EmitDefault: []string{}, PointerEmitDefault: new([]string{}),
2479 }, {
2480 EmitNull: []string{"v"}, PointerEmitNull: new([]string{"v"}),
2481 EmitEmpty: []string{"v"}, PointerEmitEmpty: new([]string{"v"}),
2482 EmitDefault: []string{"v"}, PointerEmitDefault: new([]string{"v"}),
2483 }},
2484 want: `[
2485 {
2486 "EmitNull": null,
2487 "PointerEmitNull": null,
2488 "EmitEmpty": [],
2489 "PointerEmitEmpty": [],
2490 "EmitDefault": [],
2491 "PointerEmitDefault": []
2492 },
2493 {
2494 "EmitNull": [],
2495 "PointerEmitNull": [],
2496 "EmitEmpty": [],
2497 "PointerEmitEmpty": [],
2498 "EmitDefault": [],
2499 "PointerEmitDefault": []
2500 },
2501 {
2502 "EmitNull": [
2503 "v"
2504 ],
2505 "PointerEmitNull": [
2506 "v"
2507 ],
2508 "EmitEmpty": [
2509 "v"
2510 ],
2511 "PointerEmitEmpty": [
2512 "v"
2513 ],
2514 "EmitDefault": [
2515 "v"
2516 ],
2517 "PointerEmitDefault": [
2518 "v"
2519 ]
2520 }
2521 ]`,
2522 }, {
2523 name: jsontest.Name("Structs/Format/Invalid/Bool"),
2524 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2525 in: structFormatInvalid{Bool: true},
2526 want: `{"Bool"`,
2527 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, boolType),
2528 }, {
2529 name: jsontest.Name("Structs/Format/Invalid/String"),
2530 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2531 in: structFormatInvalid{String: "string"},
2532 want: `{"String"`,
2533 wantErr: EM(errInvalidFormatFlag).withPos(`{"String":`, "/String").withType(0, stringType),
2534 }, {
2535 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
2536 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2537 in: structFormatInvalid{Bytes: []byte("bytes")},
2538 want: `{"Bytes"`,
2539 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bytes":`, "/Bytes").withType(0, bytesType),
2540 }, {
2541 name: jsontest.Name("Structs/Format/Invalid/Int"),
2542 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2543 in: structFormatInvalid{Int: 1},
2544 want: `{"Int"`,
2545 wantErr: EM(errInvalidFormatFlag).withPos(`{"Int":`, "/Int").withType(0, T[int64]()),
2546 }, {
2547 name: jsontest.Name("Structs/Format/Invalid/Uint"),
2548 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2549 in: structFormatInvalid{Uint: 1},
2550 want: `{"Uint"`,
2551 wantErr: EM(errInvalidFormatFlag).withPos(`{"Uint":`, "/Uint").withType(0, T[uint64]()),
2552 }, {
2553 name: jsontest.Name("Structs/Format/Invalid/Float"),
2554 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2555 in: structFormatInvalid{Float: 1},
2556 want: `{"Float"`,
2557 wantErr: EM(errInvalidFormatFlag).withPos(`{"Float":`, "/Float").withType(0, T[float64]()),
2558 }, {
2559 name: jsontest.Name("Structs/Format/Invalid/Map"),
2560 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2561 in: structFormatInvalid{Map: map[string]string{}},
2562 want: `{"Map"`,
2563 wantErr: EM(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
2564 }, {
2565 name: jsontest.Name("Structs/Format/Invalid/Struct"),
2566 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2567 in: structFormatInvalid{Struct: structAll{Bool: true}},
2568 want: `{"Struct"`,
2569 wantErr: EM(errInvalidFormatFlag).withPos(`{"Struct":`, "/Struct").withType(0, T[structAll]()),
2570 }, {
2571 name: jsontest.Name("Structs/Format/Invalid/Slice"),
2572 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2573 in: structFormatInvalid{Slice: []string{}},
2574 want: `{"Slice"`,
2575 wantErr: EM(errInvalidFormatFlag).withPos(`{"Slice":`, "/Slice").withType(0, T[[]string]()),
2576 }, {
2577 name: jsontest.Name("Structs/Format/Invalid/Array"),
2578 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2579 in: structFormatInvalid{Array: [1]string{"string"}},
2580 want: `{"Array"`,
2581 wantErr: EM(errInvalidFormatFlag).withPos(`{"Array":`, "/Array").withType(0, T[[1]string]()),
2582 }, {
2583 name: jsontest.Name("Structs/Format/Invalid/Interface"),
2584 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
2585 in: structFormatInvalid{Interface: "anything"},
2586 want: `{"Interface"`,
2587 wantErr: EM(errInvalidFormatFlag).withPos(`{"Interface":`, "/Interface").withType(0, T[any]()),
2588 }, {
2589 name: jsontest.Name("Structs/Embed/Zero"),
2590 in: structEmbedded{},
2591 want: `{"D":""}`,
2592 }, {
2593 name: jsontest.Name("Structs/Embed/Alloc"),
2594 in: structEmbedded{
2595 X: structEmbeddedL1{
2596 X: &structEmbeddedL2{},
2597 StructEmbed1: StructEmbed1{},
2598 },
2599 StructEmbed2: &StructEmbed2{},
2600 },
2601 want: `{"A":"","B":"","D":"","E":"","F":"","G":""}`,
2602 }, {
2603 name: jsontest.Name("Structs/Embed/NonZero"),
2604 in: structEmbedded{
2605 X: structEmbeddedL1{
2606 X: &structEmbeddedL2{A: "A1", B: "B1", C: "C1"},
2607 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
2608 },
2609 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
2610 },
2611 want: `{"A":"A1","B":"B1","D":"D2","E":"E3","F":"F3","G":"G3"}`,
2612 }, {
2613 name: jsontest.Name("Structs/Embed/DualCycle"),
2614 in: cyclicA{
2615 B1: cyclicB{F: 1},
2616 B2: cyclicB{F: 2},
2617 },
2618 want: `{}`,
2619 }, {
2620 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Nil"),
2621 in: structEmbedTextValue{X: jsontext.Value(nil)},
2622 want: `{}`,
2623 }, {
2624 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Empty"),
2625 in: structEmbedTextValue{X: jsontext.Value("")},
2626 want: `{}`,
2627 }, {
2628 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/NonEmptyN1"),
2629 in: structEmbedTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)},
2630 want: `{"fizz":"buzz"}`,
2631 }, {
2632 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/NonEmptyN2"),
2633 in: structEmbedTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `)},
2634 want: `{"fizz":"buzz","foo":"bar"}`,
2635 }, {
2636 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/NonEmptyWithOthers"),
2637 in: structEmbedTextValue{
2638 A: 1,
2639 X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `),
2640 B: 2,
2641 },
2642
2643 want: `{"A":1,"B":2,"fizz":"buzz","foo":"bar"}`,
2644 }, {
2645 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/RejectDuplicateNames"),
2646 opts: []Options{jsontext.AllowDuplicateNames(false)},
2647 in: structEmbedTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2648 want: `{"fizz":"buzz"`,
2649 wantErr: newDuplicateNameError("/fizz", nil, len64(`{"fizz":"buzz"`)),
2650 }, {
2651 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/AllowDuplicateNames"),
2652 opts: []Options{jsontext.AllowDuplicateNames(true)},
2653 in: structEmbedTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2654 want: `{"fizz":"buzz","fizz":"buzz"}`,
2655 }, {
2656 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/RejectInvalidUTF8"),
2657 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2658 in: structEmbedTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2659 want: `{`,
2660 wantErr: newInvalidUTF8Error(len64(`{"`+"\xde\xad"), ""),
2661 }, {
2662 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/AllowInvalidUTF8"),
2663 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2664 in: structEmbedTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2665 want: `{"ޭ��":"value"}`,
2666 }, {
2667 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/InvalidWhitespace"),
2668 in: structEmbedTextValue{X: jsontext.Value("\n\r\t ")},
2669 want: `{`,
2670 wantErr: EM(io.ErrUnexpectedEOF).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2671 }, {
2672 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/InvalidObject"),
2673 in: structEmbedTextValue{X: jsontext.Value(` true `)},
2674 want: `{`,
2675 wantErr: EM(errRawEmbedNotObject).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2676 }, {
2677 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/InvalidObjectName"),
2678 in: structEmbedTextValue{X: jsontext.Value(` { true : false } `)},
2679 want: `{`,
2680 wantErr: EM(newNonStringNameError(len64(" { "), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2681 }, {
2682 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/InvalidEndObject"),
2683 in: structEmbedTextValue{X: jsontext.Value(` { "name" : false , } `)},
2684 want: `{"name":false`,
2685 wantErr: EM(newInvalidCharacterError(",", "at start of value", len64(` { "name" : false `), "")).withPos(`{"name":false,`, "").withType(0, T[jsontext.Value]()),
2686 }, {
2687 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/InvalidDualObject"),
2688 in: structEmbedTextValue{X: jsontext.Value(`{}{}`)},
2689 want: `{`,
2690 wantErr: EM(newInvalidCharacterError("{", "after top-level value", len64(`{}`), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2691 }, {
2692 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Nested/Nil"),
2693 in: structEmbedPointerEmbedTextValue{},
2694 want: `{}`,
2695 }, {
2696 name: jsontest.Name("Structs/EmbeddedFallback/PointerTextValue/Nil"),
2697 in: structEmbedPointerTextValue{},
2698 want: `{}`,
2699 }, {
2700 name: jsontest.Name("Structs/EmbeddedFallback/PointerTextValue/NonEmpty"),
2701 in: structEmbedPointerTextValue{X: new(jsontext.Value(` { "fizz" : "buzz" } `))},
2702 want: `{"fizz":"buzz"}`,
2703 }, {
2704 name: jsontest.Name("Structs/EmbeddedFallback/PointerTextValue/Nested/Nil"),
2705 in: structEmbedEmbedPointerTextValue{},
2706 want: `{}`,
2707 }, {
2708 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/Nil"),
2709 in: structEmbedMapStringAny{X: nil},
2710 want: `{}`,
2711 }, {
2712 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/Empty"),
2713 in: structEmbedMapStringAny{X: make(jsonObject)},
2714 want: `{}`,
2715 }, {
2716 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/NonEmptyN1"),
2717 in: structEmbedMapStringAny{X: jsonObject{"fizz": nil}},
2718 want: `{"fizz":null}`,
2719 }, {
2720 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/NonEmptyN2"),
2721 in: structEmbedMapStringAny{X: jsonObject{"fizz": time.Time{}, "buzz": math.Pi}},
2722 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2723 canonicalize: true,
2724 }, {
2725 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/NonEmptyWithOthers"),
2726 in: structEmbedMapStringAny{
2727 A: 1,
2728 X: jsonObject{"fizz": nil},
2729 B: 2,
2730 },
2731
2732 want: `{"A":1,"B":2,"fizz":null}`,
2733 }, {
2734 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/RejectInvalidUTF8"),
2735 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2736 in: structEmbedMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2737 want: `{`,
2738 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, stringType),
2739 }, {
2740 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/AllowInvalidUTF8"),
2741 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2742 in: structEmbedMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2743 want: `{"ޭ��":null}`,
2744 }, {
2745 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/InvalidValue"),
2746 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2747 in: structEmbedMapStringAny{X: jsonObject{"name": make(chan string)}},
2748 want: `{"name"`,
2749 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2750 }, {
2751 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/Nested/Nil"),
2752 in: structEmbedPointerEmbedMapStringAny{},
2753 want: `{}`,
2754 }, {
2755 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/MarshalFunc"),
2756 opts: []Options{
2757 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2758 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2759 })),
2760 },
2761 in: structEmbedMapStringAny{X: jsonObject{"fizz": 3.14159}},
2762 want: `{"fizz":"3.14159"}`,
2763 }, {
2764 name: jsontest.Name("Structs/EmbeddedFallback/PointerMapStringAny/Nil"),
2765 in: structEmbedPointerMapStringAny{X: nil},
2766 want: `{}`,
2767 }, {
2768 name: jsontest.Name("Structs/EmbeddedFallback/PointerMapStringAny/NonEmpty"),
2769 in: structEmbedPointerMapStringAny{X: new(jsonObject{"name": "value"})},
2770 want: `{"name":"value"}`,
2771 }, {
2772 name: jsontest.Name("Structs/EmbeddedFallback/PointerMapStringAny/Nested/Nil"),
2773 in: structEmbedEmbedPointerMapStringAny{},
2774 want: `{}`,
2775 }, {
2776 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt"),
2777 in: structEmbedMapStringInt{
2778 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2779 },
2780 want: `{"one":1,"two":2,"zero":0}`,
2781 canonicalize: true,
2782 }, {
2783 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/Deterministic"),
2784 opts: []Options{Deterministic(true)},
2785 in: structEmbedMapStringInt{
2786 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2787 },
2788 want: `{"one":1,"two":2,"zero":0}`,
2789 }, {
2790 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
2791 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
2792 in: structEmbedMapStringInt{
2793 X: map[string]int{"\xff": 0, "\xfe": 1},
2794 },
2795 want: `{"�":1`,
2796 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1`)),
2797 }, {
2798 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
2799 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
2800 in: structEmbedMapStringInt{
2801 X: map[string]int{"\xff": 0, "\xfe": 1},
2802 },
2803 want: `{"�":1,"�":0}`,
2804 }, {
2805 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/StringifiedNumbers"),
2806 opts: []Options{StringifyNumbers(true)},
2807 in: structEmbedMapStringInt{
2808 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2809 },
2810 want: `{"one":"1","two":"2","zero":"0"}`,
2811 canonicalize: true,
2812 }, {
2813 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/MarshalFunc"),
2814 opts: []Options{
2815 WithMarshalers(JoinMarshalers(
2816
2817 MarshalFunc(func(v string) ([]byte, error) {
2818 return []byte(fmt.Sprintf(`"%q"`, strings.ToUpper(v))), nil
2819 }),
2820 MarshalFunc(func(v int) ([]byte, error) {
2821 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2822 }),
2823 )),
2824 },
2825 in: structEmbedMapStringInt{
2826 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2827 },
2828 want: `{"one":"1","two":"2","zero":"0"}`,
2829 canonicalize: true,
2830 }, {
2831 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringInt"),
2832 in: structEmbedMapNamedStringInt{
2833 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2834 },
2835 want: `{"one":1,"two":2,"zero":0}`,
2836 canonicalize: true,
2837 }, {
2838 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringInt/Deterministic"),
2839 opts: []Options{Deterministic(true)},
2840 in: structEmbedMapNamedStringInt{
2841 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2842 },
2843 want: `{"one":1,"two":2,"zero":0}`,
2844 }, {
2845 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/Nil"),
2846 in: structEmbedMapNamedStringAny{X: nil},
2847 want: `{}`,
2848 }, {
2849 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/Empty"),
2850 in: structEmbedMapNamedStringAny{X: make(map[namedString]any)},
2851 want: `{}`,
2852 }, {
2853 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/NonEmptyN1"),
2854 in: structEmbedMapNamedStringAny{X: map[namedString]any{"fizz": nil}},
2855 want: `{"fizz":null}`,
2856 }, {
2857 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/NonEmptyN2"),
2858 in: structEmbedMapNamedStringAny{X: map[namedString]any{"fizz": time.Time{}, "buzz": math.Pi}},
2859 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2860 canonicalize: true,
2861 }, {
2862 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/NonEmptyWithOthers"),
2863 in: structEmbedMapNamedStringAny{
2864 A: 1,
2865 X: map[namedString]any{"fizz": nil},
2866 B: 2,
2867 },
2868
2869 want: `{"A":1,"B":2,"fizz":null}`,
2870 }, {
2871 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/RejectInvalidUTF8"),
2872 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2873 in: structEmbedMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2874 want: `{`,
2875 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, T[namedString]()),
2876 }, {
2877 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/AllowInvalidUTF8"),
2878 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2879 in: structEmbedMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2880 want: `{"ޭ��":null}`,
2881 }, {
2882 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/InvalidValue"),
2883 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2884 in: structEmbedMapNamedStringAny{X: map[namedString]any{"name": make(chan string)}},
2885 want: `{"name"`,
2886 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2887 }, {
2888 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/MarshalFunc"),
2889 opts: []Options{
2890 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2891 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2892 })),
2893 },
2894 in: structEmbedMapNamedStringAny{X: map[namedString]any{"fizz": 3.14159}},
2895 want: `{"fizz":"3.14159"}`,
2896 }, {
2897 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/Other"),
2898 in: structNoCaseEmbedTextValue{
2899 X: jsontext.Value(`{"dupe":"","dupe":""}`),
2900 },
2901 want: `{"dupe":""`,
2902 wantErr: newDuplicateNameError("", []byte(`"dupe"`), len64(`{"dupe":""`)),
2903 }, {
2904 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/Other/AllowDuplicateNames"),
2905 opts: []Options{jsontext.AllowDuplicateNames(true)},
2906 in: structNoCaseEmbedTextValue{
2907 X: jsontext.Value(`{"dupe": "", "dupe": ""}`),
2908 },
2909 want: `{"dupe":"","dupe":""}`,
2910 }, {
2911 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/ExactDifferent"),
2912 in: structNoCaseEmbedTextValue{
2913 X: jsontext.Value(`{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""}`),
2914 },
2915 want: `{"Aaa":"","AaA":"","AAa":"","AAA":""}`,
2916 }, {
2917 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/ExactConflict"),
2918 in: structNoCaseEmbedTextValue{
2919 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2920 },
2921 want: `{"Aaa":""`,
2922 wantErr: newDuplicateNameError("", []byte(`"Aaa"`), len64(`{"Aaa":""`)),
2923 }, {
2924 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/ExactConflict/AllowDuplicateNames"),
2925 opts: []Options{jsontext.AllowDuplicateNames(true)},
2926 in: structNoCaseEmbedTextValue{
2927 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2928 },
2929 want: `{"Aaa":"","Aaa":""}`,
2930 }, {
2931 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/NoCaseConflict"),
2932 in: structNoCaseEmbedTextValue{
2933 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2934 },
2935 want: `{"Aaa":"","AaA":""`,
2936 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"Aaa":"","AaA":""`)),
2937 }, {
2938 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/NoCaseConflict/AllowDuplicateNames"),
2939 opts: []Options{jsontext.AllowDuplicateNames(true)},
2940 in: structNoCaseEmbedTextValue{
2941 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2942 },
2943 want: `{"Aaa":"","AaA":"","aaa":""}`,
2944 }, {
2945 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/ExactDifferentWithField"),
2946 in: structNoCaseEmbedTextValue{
2947 AAA: "x",
2948 AaA: "x",
2949 X: jsontext.Value(`{"Aaa": ""}`),
2950 },
2951 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2952 }, {
2953 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/ExactConflictWithField"),
2954 in: structNoCaseEmbedTextValue{
2955 AAA: "x",
2956 AaA: "x",
2957 X: jsontext.Value(`{"AAA": ""}`),
2958 },
2959 want: `{"AAA":"x","AaA":"x"`,
2960 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2961 }, {
2962 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedTextValue/NoCaseConflictWithField"),
2963 in: structNoCaseEmbedTextValue{
2964 AAA: "x",
2965 AaA: "x",
2966 X: jsontext.Value(`{"aaa": ""}`),
2967 },
2968 want: `{"AAA":"x","AaA":"x"`,
2969 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2970 }, {
2971 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveDelimiter"),
2972 in: structNoCaseEmbedTextValue{
2973 AaA: "x",
2974 X: jsontext.Value(`{"aa_a": ""}`),
2975 },
2976 want: `{"AaA":"x"`,
2977 wantErr: newDuplicateNameError("", []byte(`"aa_a"`), len64(`{"AaA":"x"`)),
2978 }, {
2979 name: jsontest.Name("Structs/DuplicateName/MatchCaseSensitiveDelimiter"),
2980 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
2981 in: structNoCaseEmbedTextValue{
2982 AaA: "x",
2983 X: jsontext.Value(`{"aa_a": ""}`),
2984 },
2985 want: `{"AaA":"x","aa_a":""}`,
2986 }, {
2987 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2988 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2989 in: structNoCaseEmbedTextValue{
2990 AaA: "x",
2991 X: jsontext.Value(`{"aa_a": ""}`),
2992 },
2993 want: `{"AaA":"x","aa_a":""}`,
2994 }, {
2995 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2996 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2997 in: structNoCaseEmbedTextValue{
2998 AA_b: "x",
2999 X: jsontext.Value(`{"aa_b": ""}`),
3000 },
3001 want: `{"AA_b":"x"`,
3002 wantErr: newDuplicateNameError("", []byte(`"aa_b"`), len64(`{"AA_b":"x"`)),
3003 }, {
3004 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedMapStringAny/ExactDifferent"),
3005 in: structNoCaseEmbedMapStringAny{
3006 X: jsonObject{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""},
3007 },
3008 want: `{"AAA":"","AAa":"","AaA":"","Aaa":""}`,
3009 canonicalize: true,
3010 }, {
3011 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedMapStringAny/ExactDifferentWithField"),
3012 in: structNoCaseEmbedMapStringAny{
3013 AAA: "x",
3014 AaA: "x",
3015 X: jsonObject{"Aaa": ""},
3016 },
3017 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
3018 }, {
3019 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedMapStringAny/ExactConflictWithField"),
3020 in: structNoCaseEmbedMapStringAny{
3021 AAA: "x",
3022 AaA: "x",
3023 X: jsonObject{"AAA": ""},
3024 },
3025 want: `{"AAA":"x","AaA":"x"`,
3026 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
3027 }, {
3028 name: jsontest.Name("Structs/DuplicateName/NoCaseEmbedMapStringAny/NoCaseConflictWithField"),
3029 in: structNoCaseEmbedMapStringAny{
3030 AAA: "x",
3031 AaA: "x",
3032 X: jsonObject{"aaa": ""},
3033 },
3034 want: `{"AAA":"x","AaA":"x"`,
3035 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
3036 }, {
3037 name: jsontest.Name("Structs/Invalid/Conflicting"),
3038 in: structConflicting{},
3039 want: ``,
3040 wantErr: EM(errors.New("Go struct fields A and B conflict over JSON object name \"conflict\"")).withType(0, T[structConflicting]()),
3041 }, {
3042 name: jsontest.Name("Structs/Invalid/NoneExported"),
3043 in: structNoneExported{},
3044 want: ``,
3045 wantErr: EM(errNoExportedFields).withType(0, T[structNoneExported]()),
3046 }, {
3047 name: jsontest.Name("Structs/Invalid/MalformedTag"),
3048 in: structMalformedTag{},
3049 want: ``,
3050 wantErr: EM(errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter)")).withType(0, T[structMalformedTag]()),
3051 }, {
3052 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
3053 in: structUnexportedTag{},
3054 want: ``,
3055 wantErr: EM(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType(0, T[structUnexportedTag]()),
3056 }, {
3057 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
3058 in: structExportedEmbedded{"hello"},
3059 want: ``,
3060 wantErr: EM(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structExportedEmbedded]()),
3061 }, {
3062 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
3063 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
3064 in: structExportedEmbedded{"hello"},
3065 want: `{"NamedString":"hello"}`,
3066 }, {
3067 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
3068 in: structExportedEmbeddedTag{"hello"},
3069 want: `{"name":"hello"}`,
3070 }, {
3071 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
3072 in: structUnexportedEmbedded{},
3073 want: ``,
3074 wantErr: EM(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structUnexportedEmbedded]()),
3075 }, {
3076 name: jsontest.Name("Structs/Valid/UnexportedEmbedded"),
3077 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
3078 in: structUnexportedEmbedded{},
3079 want: `{}`,
3080 }, {
3081 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedTag"),
3082 in: structUnexportedEmbeddedTag{},
3083 wantErr: EM(errors.New("Go struct field namedString is not exported")).withType(0, T[structUnexportedEmbeddedTag]()),
3084 }, {
3085 name: jsontest.Name("Structs/Valid/UnexportedEmbeddedTag"),
3086 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
3087 in: structUnexportedEmbeddedTag{},
3088 want: `{}`,
3089 }, {
3090 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedMethodTag"),
3091 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
3092 in: structUnexportedEmbeddedMethodTag{},
3093 want: `{}`,
3094 }, {
3095 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/Zero"),
3096 in: structUnexportedEmbeddedStruct{},
3097 want: `{"FizzBuzz":0,"Addr":""}`,
3098 }, {
3099 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/NonZero"),
3100 in: structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
3101 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
3102 }, {
3103 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
3104 in: structUnexportedEmbeddedStructPointer{},
3105 want: `{"FizzBuzz":0}`,
3106 }, {
3107 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Zero"),
3108 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{}, 0, &structNestedAddr{}},
3109 want: `{"FizzBuzz":0,"Addr":""}`,
3110 }, {
3111 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/NonZero"),
3112 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
3113 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
3114 }, {
3115 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
3116 opts: []Options{invalidFormatOption},
3117 in: struct{}{},
3118 want: `{}`,
3119 }, {
3120 name: jsontest.Name("Slices/Interface"),
3121 in: []any{
3122 false, true,
3123 "hello", []byte("world"),
3124 int32(-32), namedInt64(-64),
3125 uint32(+32), namedUint64(+64),
3126 float32(32.32), namedFloat64(64.64),
3127 },
3128 want: `[false,true,"hello","d29ybGQ=",-32,-64,32,64,32.32,64.64]`,
3129 }, {
3130 name: jsontest.Name("Slices/Invalid/Channel"),
3131 in: [](chan string){nil},
3132 want: `[`,
3133 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3134 }, {
3135 name: jsontest.Name("Slices/RecursiveSlice"),
3136 in: recursiveSlice{
3137 nil,
3138 {},
3139 {nil},
3140 {nil, {}},
3141 },
3142 want: `[[],[],[[]],[[],[]]]`,
3143 }, {
3144 name: jsontest.Name("Slices/CyclicSlice"),
3145 in: func() recursiveSlice {
3146 s := recursiveSlice{{}}
3147 s[0] = s
3148 return s
3149 }(),
3150 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[`,
3151 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat("[", startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter+1))).withType(0, T[recursiveSlice]()),
3152 }, {
3153 name: jsontest.Name("Slices/NonCyclicSlice"),
3154 in: func() []any {
3155 v := []any{nil, nil}
3156 v[1] = v[:1]
3157 for i := 1000; i > 0; i-- {
3158 v = []any{v}
3159 }
3160 return v
3161 }(),
3162 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[null,[null]]` + strings.Repeat(`]`, startDetectingCyclesAfter),
3163 }, {
3164 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
3165 opts: []Options{invalidFormatOption},
3166 in: []string{"hello", "goodbye"},
3167 want: `["hello","goodbye"]`,
3168 }, {
3169 name: jsontest.Name("Arrays/Empty"),
3170 in: [0]struct{}{},
3171 want: `[]`,
3172 }, {
3173 name: jsontest.Name("Arrays/Bool"),
3174 in: [2]bool{false, true},
3175 want: `[false,true]`,
3176 }, {
3177 name: jsontest.Name("Arrays/String"),
3178 in: [2]string{"hello", "goodbye"},
3179 want: `["hello","goodbye"]`,
3180 }, {
3181 name: jsontest.Name("Arrays/Bytes"),
3182 in: [2][]byte{[]byte("hello"), []byte("goodbye")},
3183 want: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
3184 }, {
3185 name: jsontest.Name("Arrays/Int"),
3186 in: [2]int64{math.MinInt64, math.MaxInt64},
3187 want: `[-9223372036854775808,9223372036854775807]`,
3188 }, {
3189 name: jsontest.Name("Arrays/Uint"),
3190 in: [2]uint64{0, math.MaxUint64},
3191 want: `[0,18446744073709551615]`,
3192 }, {
3193 name: jsontest.Name("Arrays/Float"),
3194 in: [2]float64{-math.MaxFloat64, +math.MaxFloat64},
3195 want: `[-1.7976931348623157e+308,1.7976931348623157e+308]`,
3196 }, {
3197 name: jsontest.Name("Arrays/Invalid/Channel"),
3198 in: new([1]chan string),
3199 want: `[`,
3200 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3201 }, {
3202 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
3203 opts: []Options{invalidFormatOption},
3204 in: [2]string{"hello", "goodbye"},
3205 want: `["hello","goodbye"]`,
3206 }, {
3207 name: jsontest.Name("Pointers/NilL0"),
3208 in: (*int)(nil),
3209 want: `null`,
3210 }, {
3211 name: jsontest.Name("Pointers/NilL1"),
3212 in: new(*int),
3213 want: `null`,
3214 }, {
3215 name: jsontest.Name("Pointers/Bool"),
3216 in: new(new(bool(true))),
3217 want: `true`,
3218 }, {
3219 name: jsontest.Name("Pointers/String"),
3220 in: new(new(string("string"))),
3221 want: `"string"`,
3222 }, {
3223 name: jsontest.Name("Pointers/Bytes"),
3224 in: new(new([]byte("bytes"))),
3225 want: `"Ynl0ZXM="`,
3226 }, {
3227 name: jsontest.Name("Pointers/Int"),
3228 in: new(new(int(-100))),
3229 want: `-100`,
3230 }, {
3231 name: jsontest.Name("Pointers/Uint"),
3232 in: new(new(uint(100))),
3233 want: `100`,
3234 }, {
3235 name: jsontest.Name("Pointers/Float"),
3236 in: new(new(float64(3.14159))),
3237 want: `3.14159`,
3238 }, {
3239 name: jsontest.Name("Pointers/CyclicPointer"),
3240 in: func() *recursivePointer {
3241 p := new(recursivePointer)
3242 p.P = p
3243 return p
3244 }(),
3245 want: strings.Repeat(`{"P":`, startDetectingCyclesAfter) + `{"P"`,
3246 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"P":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/P", startDetectingCyclesAfter+1))).withType(0, T[*recursivePointer]()),
3247 }, {
3248 name: jsontest.Name("Pointers/IgnoreInvalidFormat"),
3249 opts: []Options{invalidFormatOption},
3250 in: new(new(bool(true))),
3251 want: `true`,
3252 }, {
3253 name: jsontest.Name("Interfaces/Nil/Empty"),
3254 in: [1]any{nil},
3255 want: `[null]`,
3256 }, {
3257 name: jsontest.Name("Interfaces/Nil/NonEmpty"),
3258 in: [1]io.Reader{nil},
3259 want: `[null]`,
3260 }, {
3261 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
3262 opts: []Options{invalidFormatOption},
3263 in: [1]io.Reader{nil},
3264 want: `[null]`,
3265 }, {
3266 name: jsontest.Name("Interfaces/Any"),
3267 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}, [8]byte{}}},
3268 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3269 }, {
3270 name: jsontest.Name("Interfaces/Any/Named"),
3271 in: struct{ X namedAny }{[]namedAny{nil, false, "", 0.0, map[string]namedAny{}, []namedAny{}, [8]byte{}}},
3272 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3273 }, {
3274 name: jsontest.Name("Interfaces/Any/Stringified"),
3275 opts: []Options{StringifyNumbers(true)},
3276 in: struct{ X any }{0.0},
3277 want: `{"X":"0"}`,
3278 }, {
3279 name: jsontest.Name("Interfaces/Any/MarshalFunc/Any"),
3280 opts: []Options{
3281 WithMarshalers(MarshalFunc(func(v any) ([]byte, error) {
3282 return []byte(`"called"`), nil
3283 })),
3284 },
3285 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3286 want: `"called"`,
3287 }, {
3288 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bool"),
3289 opts: []Options{
3290 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3291 return []byte(`"called"`), nil
3292 })),
3293 },
3294 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3295 want: `{"X":[null,"called","",0,{},[]]}`,
3296 }, {
3297 name: jsontest.Name("Interfaces/Any/MarshalFunc/String"),
3298 opts: []Options{
3299 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3300 return []byte(`"called"`), nil
3301 })),
3302 },
3303 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3304 want: `{"X":[null,false,"called",0,{},[]]}`,
3305 }, {
3306 name: jsontest.Name("Interfaces/Any/MarshalFunc/Float64"),
3307 opts: []Options{
3308 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
3309 return []byte(`"called"`), nil
3310 })),
3311 },
3312 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3313 want: `{"X":[null,false,"","called",{},[]]}`,
3314 }, {
3315 name: jsontest.Name("Interfaces/Any/MarshalFunc/MapStringAny"),
3316 opts: []Options{
3317 WithMarshalers(MarshalFunc(func(v map[string]any) ([]byte, error) {
3318 return []byte(`"called"`), nil
3319 })),
3320 },
3321 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3322 want: `{"X":[null,false,"",0,"called",[]]}`,
3323 }, {
3324 name: jsontest.Name("Interfaces/Any/MarshalFunc/SliceAny"),
3325 opts: []Options{
3326 WithMarshalers(MarshalFunc(func(v []any) ([]byte, error) {
3327 return []byte(`"called"`), nil
3328 })),
3329 },
3330 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3331 want: `{"X":"called"}`,
3332 }, {
3333 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bytes"),
3334 opts: []Options{
3335 WithMarshalers(MarshalFunc(func(v [8]byte) ([]byte, error) {
3336 return []byte(`"called"`), nil
3337 })),
3338 },
3339 in: struct{ X any }{[8]byte{}},
3340 want: `{"X":"called"}`,
3341 }, {
3342 name: jsontest.Name("Interfaces/Any/Float/NaN"),
3343 in: struct{ X any }{math.NaN()},
3344 want: `{"X"`,
3345 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, reflect.TypeFor[float64]()).withPos(`{"X":`, "/X"),
3346 }, {
3347 name: jsontest.Name("Interfaces/Any/Maps/Nil"),
3348 in: struct{ X any }{map[string]any(nil)},
3349 want: `{"X":{}}`,
3350 }, {
3351 name: jsontest.Name("Interfaces/Any/Maps/Nil/FormatNilMapAsNull"),
3352 opts: []Options{FormatNilMapAsNull(true)},
3353 in: struct{ X any }{map[string]any(nil)},
3354 want: `{"X":null}`,
3355 }, {
3356 name: jsontest.Name("Interfaces/Any/Maps/Empty"),
3357 in: struct{ X any }{map[string]any{}},
3358 want: `{"X":{}}`,
3359 }, {
3360 name: jsontest.Name("Interfaces/Any/Maps/Empty/Multiline"),
3361 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3362 in: struct{ X any }{map[string]any{}},
3363 want: "{\n\"X\": {}\n}",
3364 }, {
3365 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
3366 in: struct{ X any }{map[string]any{"fizz": "buzz"}},
3367 want: `{"X":{"fizz":"buzz"}}`,
3368 }, {
3369 name: jsontest.Name("Interfaces/Any/Maps/Deterministic"),
3370 opts: []Options{Deterministic(true)},
3371 in: struct{ X any }{map[string]any{"alpha": "", "bravo": ""}},
3372 want: `{"X":{"alpha":"","bravo":""}}`,
3373 }, {
3374 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
3375 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
3376 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3377 want: `{"X":{"�":""`,
3378 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3379 }, {
3380 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
3381 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3382 in: struct{ X any }{map[string]any{"\xff": "alpha", "\xfe": "bravo"}},
3383 want: `{"X":{"�":"bravo","�":"alpha"}}`,
3384 }, {
3385 name: jsontest.Name("Interfaces/Any/Maps/RejectInvalidUTF8"),
3386 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3387 want: `{"X":{`,
3388 wantErr: newInvalidUTF8Error(len64(`{"X":{`), "/X"),
3389 }, {
3390 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+RejectDuplicateNames"),
3391 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3392 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3393 want: `{"X":{"�":""`,
3394 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3395 }, {
3396 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+AllowDuplicateNames"),
3397 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3398 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3399 want: `{"X":{"�":"","�":""}}`,
3400 }, {
3401 name: jsontest.Name("Interfaces/Any/Maps/Cyclic"),
3402 in: func() any {
3403 m := map[string]any{}
3404 m[""] = m
3405 return struct{ X any }{m}
3406 }(),
3407 want: `{"X"` + strings.Repeat(`:{""`, startDetectingCyclesAfter),
3408 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`{"":`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/", startDetectingCyclesAfter))).withType(0, T[map[string]any]()),
3409 }, {
3410 name: jsontest.Name("Interfaces/Any/Slices/Nil"),
3411 in: struct{ X any }{[]any(nil)},
3412 want: `{"X":[]}`,
3413 }, {
3414 name: jsontest.Name("Interfaces/Any/Slices/Nil/FormatNilSliceAsNull"),
3415 opts: []Options{FormatNilSliceAsNull(true)},
3416 in: struct{ X any }{[]any(nil)},
3417 want: `{"X":null}`,
3418 }, {
3419 name: jsontest.Name("Interfaces/Any/Slices/Empty"),
3420 in: struct{ X any }{[]any{}},
3421 want: `{"X":[]}`,
3422 }, {
3423 name: jsontest.Name("Interfaces/Any/Slices/Empty/Multiline"),
3424 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3425 in: struct{ X any }{[]any{}},
3426 want: "{\n\"X\": []\n}",
3427 }, {
3428 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
3429 in: struct{ X any }{[]any{"fizz", "buzz"}},
3430 want: `{"X":["fizz","buzz"]}`,
3431 }, {
3432 name: jsontest.Name("Interfaces/Any/Slices/Cyclic"),
3433 in: func() any {
3434 s := make([]any, 1)
3435 s[0] = s
3436 return struct{ X any }{s}
3437 }(),
3438 want: `{"X":` + strings.Repeat(`[`, startDetectingCyclesAfter),
3439 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`[`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter))).withType(0, T[[]any]()),
3440 }, {
3441 name: jsontest.Name("Methods/NilPointer"),
3442 in: struct{ X *allMethods }{X: (*allMethods)(nil)},
3443 want: `{"X":null}`,
3444 }, {
3445
3446 name: jsontest.Name("Methods/NilInterface"),
3447 in: struct{ X MarshalerTo }{X: (*allMethods)(nil)},
3448 want: `{"X":null}`,
3449 }, {
3450 name: jsontest.Name("Methods/AllMethods"),
3451 in: struct{ X *allMethods }{X: &allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3452 want: `{"X":"hello"}`,
3453 }, {
3454 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
3455 in: struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3456 want: `{"X":"hello"}`,
3457 }, {
3458 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
3459 in: struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3460 want: `{"X":"hello"}`,
3461 }, {
3462 name: jsontest.Name("Methods/AllMethodsExceptText"),
3463 in: struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3464 want: `{"X":"hello"}`,
3465 }, {
3466 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
3467 in: struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3468 want: `{"X":"hello"}`,
3469 }, {
3470 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
3471 in: struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3472 want: `{"X":"hello"}`,
3473 }, {
3474 name: jsontest.Name("Methods/OnlyMethodText"),
3475 in: struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "MarshalText", value: []byte(`hello`)}}},
3476 want: `{"X":"hello"}`,
3477 }, {
3478 name: jsontest.Name("Methods/IP"),
3479 in: net.IPv4(192, 168, 0, 100),
3480 want: `"192.168.0.100"`,
3481 }, {
3482 name: jsontest.Name("Methods/NetIP"),
3483 in: struct {
3484 Addr netip.Addr
3485 AddrPort netip.AddrPort
3486 Prefix netip.Prefix
3487 }{
3488 Addr: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
3489 AddrPort: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 1234),
3490 Prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
3491 },
3492 want: `{"Addr":"1.2.3.4","AddrPort":"1.2.3.4:1234","Prefix":"1.2.3.4/24"}`,
3493 }, {
3494
3495 name: jsontest.Name("Methods/Anonymous"),
3496 in: struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3497 want: `{"X":"hello"}`,
3498 }, {
3499
3500 name: jsontest.Name("Methods/Addressable"),
3501 in: struct {
3502 V allMethods
3503 M map[string]allMethods
3504 I any
3505 }{
3506 V: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3507 M: map[string]allMethods{"K": {method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3508 I: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3509 },
3510 want: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
3511 }, {
3512
3513 name: jsontest.Name("Methods/MapKey/JSONv2"),
3514 in: map[structMethodJSONv2]string{{"k1"}: "v1", {"k2"}: "v2"},
3515 want: `{"k1":"v1","k2":"v2"}`,
3516 canonicalize: true,
3517 }, {
3518
3519 name: jsontest.Name("Methods/MapKey/JSONv1"),
3520 in: map[structMethodJSONv1]string{{"k1"}: "v1", {"k2"}: "v2"},
3521 want: `{"k1":"v1","k2":"v2"}`,
3522 canonicalize: true,
3523 }, {
3524 name: jsontest.Name("Methods/MapKey/Text"),
3525 in: map[structMethodText]string{{"k1"}: "v1", {"k2"}: "v2"},
3526 want: `{"k1":"v1","k2":"v2"}`,
3527 canonicalize: true,
3528 }, {
3529 name: jsontest.Name("Methods/JSONv2/ErrUnsupported"),
3530 opts: []Options{Deterministic(true)},
3531 in: unsupportedMethodJSONv2{"fizz": 123},
3532 want: `{"called":1,"fizz":123}`,
3533 }, {
3534 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
3535 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3536 return errSomeError
3537 }),
3538 wantErr: EM(errSomeError).withType(0, T[marshalJSONv2Func]()),
3539 }, {
3540 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
3541 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3542 return nil
3543 }),
3544 wantErr: EM(errNonSingularValue).withType(0, T[marshalJSONv2Func]()),
3545 }, {
3546 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
3547 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3548 enc.WriteToken(jsontext.Null)
3549 enc.WriteToken(jsontext.Null)
3550 return nil
3551 }),
3552 want: `nullnull`,
3553 wantErr: EM(errNonSingularValue).withPos(`nullnull`, "").withType(0, T[marshalJSONv2Func]()),
3554 }, {
3555 name: jsontest.Name("Methods/Invalid/JSONv2/ErrUnsupported"),
3556 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3557 return errors.ErrUnsupported
3558 }),
3559 wantErr: EM(nil).withType(0, T[marshalJSONv2Func]()),
3560 }, {
3561 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
3562 in: marshalJSONv1Func(func() ([]byte, error) {
3563 return nil, errSomeError
3564 }),
3565 wantErr: EM(errSomeError).withType(0, T[marshalJSONv1Func]()),
3566 }, {
3567 name: jsontest.Name("Methods/Invalid/JSONv1/Syntax"),
3568 in: marshalJSONv1Func(func() ([]byte, error) {
3569 return []byte("invalid"), nil
3570 }),
3571 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[marshalJSONv1Func]()),
3572 }, {
3573 name: jsontest.Name("Methods/Invalid/JSONv1/ErrUnsupported"),
3574 in: marshalJSONv1Func(func() ([]byte, error) {
3575 return nil, errors.ErrUnsupported
3576 }),
3577 wantErr: EM(errors.New("MarshalJSON method may not return errors.ErrUnsupported")).withType(0, T[marshalJSONv1Func]()),
3578 }, {
3579 name: jsontest.Name("Methods/AppendText"),
3580 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), nil }),
3581 want: `"hello"`,
3582 }, {
3583 name: jsontest.Name("Methods/AppendText/Error"),
3584 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), errSomeError }),
3585 wantErr: EM(errSomeError).withType(0, T[appendTextFunc]()),
3586 }, {
3587 name: jsontest.Name("Methods/AppendText/NeedEscape"),
3588 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, `"`...), nil }),
3589 want: `"\""`,
3590 }, {
3591 name: jsontest.Name("Methods/AppendText/RejectInvalidUTF8"),
3592 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3593 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[appendTextFunc]()),
3594 }, {
3595 name: jsontest.Name("Methods/AppendText/AllowInvalidUTF8"),
3596 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3597 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3598 want: "\"\xde\xad\ufffd\ufffd\"",
3599 }, {
3600 name: jsontest.Name("Methods/Invalid/Text/Error"),
3601 in: marshalTextFunc(func() ([]byte, error) {
3602 return nil, errSomeError
3603 }),
3604 wantErr: EM(errSomeError).withType(0, T[marshalTextFunc]()),
3605 }, {
3606 name: jsontest.Name("Methods/Text/RejectInvalidUTF8"),
3607 in: marshalTextFunc(func() ([]byte, error) {
3608 return []byte("\xde\xad\xbe\xef"), nil
3609 }),
3610 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[marshalTextFunc]()),
3611 }, {
3612 name: jsontest.Name("Methods/Text/AllowInvalidUTF8"),
3613 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3614 in: marshalTextFunc(func() ([]byte, error) {
3615 return []byte("\xde\xad\xbe\xef"), nil
3616 }),
3617 want: "\"\xde\xad\ufffd\ufffd\"",
3618 }, {
3619 name: jsontest.Name("Methods/Invalid/Text/ErrUnsupported"),
3620 in: marshalTextFunc(func() ([]byte, error) {
3621 return nil, errors.ErrUnsupported
3622 }),
3623 wantErr: EM(wrapErrUnsupported(errors.ErrUnsupported, "MarshalText method")).withType(0, T[marshalTextFunc]()),
3624 }, {
3625 name: jsontest.Name("Methods/Invalid/MapKey/JSONv2/Syntax"),
3626 in: map[any]string{
3627 new(marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3628 return enc.WriteToken(jsontext.Null)
3629 })): "invalid",
3630 },
3631 want: `{`,
3632 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv2Func]()),
3633 }, {
3634 name: jsontest.Name("Methods/Invalid/MapKey/JSONv1/Syntax"),
3635 in: map[any]string{
3636 new(marshalJSONv1Func(func() ([]byte, error) {
3637 return []byte(`null`), nil
3638 })): "invalid",
3639 },
3640 want: `{`,
3641 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv1Func]()),
3642 }, {
3643 name: jsontest.Name("Functions/Bool/V1"),
3644 opts: []Options{
3645 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3646 return []byte(`"called"`), nil
3647 })),
3648 },
3649 in: true,
3650 want: `"called"`,
3651 }, {
3652 name: jsontest.Name("Functions/Bool/Empty"),
3653 opts: []Options{WithMarshalers(nil)},
3654 in: true,
3655 want: `true`,
3656 }, {
3657 name: jsontest.Name("Functions/NamedBool/V1/NoMatch"),
3658 opts: []Options{
3659 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3660 return nil, errMustNotCall
3661 })),
3662 },
3663 in: true,
3664 want: `true`,
3665 }, {
3666 name: jsontest.Name("Functions/NamedBool/V1/Match"),
3667 opts: []Options{
3668 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3669 return []byte(`"called"`), nil
3670 })),
3671 },
3672 in: namedBool(true),
3673 want: `"called"`,
3674 }, {
3675 name: jsontest.Name("Functions/PointerBool/V1/Match"),
3676 opts: []Options{
3677 WithMarshalers(MarshalFunc(func(v *bool) ([]byte, error) {
3678 _ = *v
3679 return []byte(`"called"`), nil
3680 })),
3681 },
3682 in: true,
3683 want: `"called"`,
3684 }, {
3685 name: jsontest.Name("Functions/Bool/V2"),
3686 opts: []Options{
3687 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3688 return enc.WriteToken(jsontext.String("called"))
3689 })),
3690 },
3691 in: true,
3692 want: `"called"`,
3693 }, {
3694 name: jsontest.Name("Functions/NamedBool/V2/NoMatch"),
3695 opts: []Options{
3696 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3697 return errMustNotCall
3698 })),
3699 },
3700 in: true,
3701 want: `true`,
3702 }, {
3703 name: jsontest.Name("Functions/NamedBool/V2/Match"),
3704 opts: []Options{
3705 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3706 return enc.WriteToken(jsontext.String("called"))
3707 })),
3708 },
3709 in: namedBool(true),
3710 want: `"called"`,
3711 }, {
3712 name: jsontest.Name("Functions/PointerBool/V2/Match"),
3713 opts: []Options{
3714 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3715 _ = *v
3716 return enc.WriteToken(jsontext.String("called"))
3717 })),
3718 },
3719 in: true,
3720 want: `"called"`,
3721 }, {
3722 name: jsontest.Name("Functions/Bool/Empty1/NoMatch"),
3723 opts: []Options{
3724 WithMarshalers(new(Marshalers)),
3725 },
3726 in: true,
3727 want: `true`,
3728 }, {
3729 name: jsontest.Name("Functions/Bool/Empty2/NoMatch"),
3730 opts: []Options{
3731 WithMarshalers(JoinMarshalers()),
3732 },
3733 in: true,
3734 want: `true`,
3735 }, {
3736 name: jsontest.Name("Functions/Bool/V1/DirectError"),
3737 opts: []Options{
3738 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3739 return nil, errSomeError
3740 })),
3741 },
3742 in: true,
3743 wantErr: EM(errSomeError).withType(0, T[bool]()),
3744 }, {
3745 name: jsontest.Name("Functions/Bool/V1/SkipError"),
3746 opts: []Options{
3747 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3748 return nil, errors.ErrUnsupported
3749 })),
3750 },
3751 in: true,
3752 wantErr: EM(wrapErrUnsupported(errors.ErrUnsupported, "marshal function of type func(T) ([]byte, error)")).withType(0, T[bool]()),
3753 }, {
3754 name: jsontest.Name("Functions/Bool/V1/InvalidValue"),
3755 opts: []Options{
3756 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3757 return []byte("invalid"), nil
3758 })),
3759 },
3760 in: true,
3761 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[bool]()),
3762 }, {
3763 name: jsontest.Name("Functions/Bool/V2/DirectError"),
3764 opts: []Options{
3765 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3766 return errSomeError
3767 })),
3768 },
3769 in: true,
3770 wantErr: EM(errSomeError).withType(0, T[bool]()),
3771 }, {
3772 name: jsontest.Name("Functions/Bool/V2/TooFew"),
3773 opts: []Options{
3774 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3775 return nil
3776 })),
3777 },
3778 in: true,
3779 wantErr: EM(errNonSingularValue).withType(0, T[bool]()),
3780 }, {
3781 name: jsontest.Name("Functions/Bool/V2/TooMany"),
3782 opts: []Options{
3783 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3784 enc.WriteValue([]byte(`"hello"`))
3785 enc.WriteValue([]byte(`"world"`))
3786 return nil
3787 })),
3788 },
3789 in: true,
3790 want: `"hello""world"`,
3791 wantErr: EM(errNonSingularValue).withPos(`"hello""world"`, "").withType(0, T[bool]()),
3792 }, {
3793 name: jsontest.Name("Functions/Bool/V2/Skipped"),
3794 opts: []Options{
3795 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3796 return errors.ErrUnsupported
3797 })),
3798 },
3799 in: true,
3800 want: `true`,
3801 }, {
3802 name: jsontest.Name("Functions/Bool/V2/ProcessBeforeSkip"),
3803 opts: []Options{
3804 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3805 enc.WriteValue([]byte(`"hello"`))
3806 return errors.ErrUnsupported
3807 })),
3808 },
3809 in: true,
3810 want: `"hello"`,
3811 wantErr: EM(errUnsupportedMutation).withPos(`"hello"`, "").withType(0, T[bool]()),
3812 }, {
3813 name: jsontest.Name("Functions/Bool/V2/WrappedUnsupportedError"),
3814 opts: []Options{
3815 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3816 return fmt.Errorf("wrap: %w", errors.ErrUnsupported)
3817 })),
3818 },
3819 in: true,
3820 want: `true`,
3821 }, {
3822 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
3823 opts: []Options{
3824 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3825 return []byte(`"called"`), nil
3826 })),
3827 },
3828 in: map[nocaseString]string{"hello": "world"},
3829 want: `{"called":"world"}`,
3830 }, {
3831 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V1"),
3832 opts: []Options{
3833 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3834 _ = *v
3835 return []byte(`"called"`), nil
3836 })),
3837 },
3838 in: map[nocaseString]string{"hello": "world"},
3839 want: `{"called":"world"}`,
3840 }, {
3841 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
3842 opts: []Options{
3843 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3844 _ = *v.(*nocaseString)
3845 return []byte(`"called"`), nil
3846 })),
3847 },
3848 in: map[nocaseString]string{"hello": "world"},
3849 want: `{"called":"world"}`,
3850 }, {
3851 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1/InvalidValue"),
3852 opts: []Options{
3853 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3854 return []byte(`null`), nil
3855 })),
3856 },
3857 in: map[nocaseString]string{"hello": "world"},
3858 want: `{`,
3859 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3860 }, {
3861 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidKind"),
3862 opts: []Options{
3863 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3864 return []byte(`null`), nil
3865 })),
3866 },
3867 in: map[nocaseString]string{"hello": "world"},
3868 want: `{`,
3869 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3870 }, {
3871 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
3872 opts: []Options{
3873 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3874 return []byte(`"name"`), nil
3875 })),
3876 },
3877 in: map[string]string{"name1": "value", "name2": "value"},
3878 want: `{"name":"name"`,
3879 wantErr: EM(newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"name",`))).
3880 withPos(`{"name":"name",`, "").withType(0, T[string]()),
3881 }, {
3882 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
3883 opts: []Options{
3884 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3885 return enc.WriteValue([]byte(`"called"`))
3886 })),
3887 },
3888 in: map[nocaseString]string{"hello": "world"},
3889 want: `{"called":"world"}`,
3890 }, {
3891 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V2"),
3892 opts: []Options{
3893 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3894 _ = *v
3895 return enc.WriteValue([]byte(`"called"`))
3896 })),
3897 },
3898 in: map[nocaseString]string{"hello": "world"},
3899 want: `{"called":"world"}`,
3900 }, {
3901 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
3902 opts: []Options{
3903 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3904 _ = *v.(*nocaseString)
3905 return enc.WriteValue([]byte(`"called"`))
3906 })),
3907 },
3908 in: map[nocaseString]string{"hello": "world"},
3909 want: `{"called":"world"}`,
3910 }, {
3911 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidToken"),
3912 opts: []Options{
3913 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3914 return enc.WriteToken(jsontext.Null)
3915 })),
3916 },
3917 in: map[nocaseString]string{"hello": "world"},
3918 want: `{`,
3919 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3920 }, {
3921 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidValue"),
3922 opts: []Options{
3923 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3924 return enc.WriteValue([]byte(`null`))
3925 })),
3926 },
3927 in: map[nocaseString]string{"hello": "world"},
3928 want: `{`,
3929 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3930 }, {
3931 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
3932 opts: []Options{
3933 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3934 return []byte(`"called"`), nil
3935 })),
3936 },
3937 in: map[string]nocaseString{"hello": "world"},
3938 want: `{"hello":"called"}`,
3939 }, {
3940 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V1"),
3941 opts: []Options{
3942 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3943 _ = *v
3944 return []byte(`"called"`), nil
3945 })),
3946 },
3947 in: map[string]nocaseString{"hello": "world"},
3948 want: `{"hello":"called"}`,
3949 }, {
3950 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
3951 opts: []Options{
3952 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3953 _ = *v.(*nocaseString)
3954 return []byte(`"called"`), nil
3955 })),
3956 },
3957 in: map[string]nocaseString{"hello": "world"},
3958 want: `{"hello":"called"}`,
3959 }, {
3960 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
3961 opts: []Options{
3962 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3963 return enc.WriteValue([]byte(`"called"`))
3964 })),
3965 },
3966 in: map[string]nocaseString{"hello": "world"},
3967 want: `{"hello":"called"}`,
3968 }, {
3969 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V2"),
3970 opts: []Options{
3971 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3972 _ = *v
3973 return enc.WriteValue([]byte(`"called"`))
3974 })),
3975 },
3976 in: map[string]nocaseString{"hello": "world"},
3977 want: `{"hello":"called"}`,
3978 }, {
3979 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
3980 opts: []Options{
3981 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3982 _ = *v.(*nocaseString)
3983 return enc.WriteValue([]byte(`"called"`))
3984 })),
3985 },
3986 in: map[string]nocaseString{"hello": "world"},
3987 want: `{"hello":"called"}`,
3988 }, {
3989 name: jsontest.Name("Funtions/Struct/Fields"),
3990 opts: []Options{
3991 WithMarshalers(JoinMarshalers(
3992 MarshalFunc(func(v bool) ([]byte, error) {
3993 return []byte(`"called1"`), nil
3994 }),
3995 MarshalFunc(func(v *string) ([]byte, error) {
3996 return []byte(`"called2"`), nil
3997 }),
3998 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3999 return enc.WriteValue([]byte(`"called3"`))
4000 }),
4001 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
4002 return enc.WriteValue([]byte(`"called4"`))
4003 }),
4004 )),
4005 },
4006 in: structScalars{},
4007 want: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":0,"Float":0}`,
4008 }, {
4009 name: jsontest.Name("Functions/Struct/OmitEmpty"),
4010 opts: []Options{
4011 WithMarshalers(JoinMarshalers(
4012 MarshalFunc(func(v bool) ([]byte, error) {
4013 return []byte(`null`), nil
4014 }),
4015 MarshalFunc(func(v string) ([]byte, error) {
4016 return []byte(`"called1"`), nil
4017 }),
4018 MarshalFunc(func(v *stringMarshalNonEmpty) ([]byte, error) {
4019 return []byte(`""`), nil
4020 }),
4021 MarshalToFunc(func(enc *jsontext.Encoder, v bytesMarshalNonEmpty) error {
4022 return enc.WriteValue([]byte(`{}`))
4023 }),
4024 MarshalToFunc(func(enc *jsontext.Encoder, v *float64) error {
4025 return enc.WriteValue([]byte(`[]`))
4026 }),
4027 MarshalFunc(func(v mapMarshalNonEmpty) ([]byte, error) {
4028 return []byte(`"called2"`), nil
4029 }),
4030 MarshalFunc(func(v []string) ([]byte, error) {
4031 return []byte(`"called3"`), nil
4032 }),
4033 MarshalToFunc(func(enc *jsontext.Encoder, v *sliceMarshalNonEmpty) error {
4034 return enc.WriteValue([]byte(`"called4"`))
4035 }),
4036 )),
4037 },
4038 in: structOmitEmptyAll{},
4039 want: `{"String":"called1","MapNonEmpty":"called2","Slice":"called3","SliceNonEmpty":"called4"}`,
4040 }, {
4041 name: jsontest.Name("Functions/Struct/OmitZero"),
4042 opts: []Options{
4043 WithMarshalers(JoinMarshalers(
4044 MarshalFunc(func(v bool) ([]byte, error) {
4045 panic("should not be called")
4046 }),
4047 MarshalFunc(func(v *string) ([]byte, error) {
4048 panic("should not be called")
4049 }),
4050 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
4051 panic("should not be called")
4052 }),
4053 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
4054 panic("should not be called")
4055 }),
4056 )),
4057 },
4058 in: structOmitZeroAll{},
4059 want: `{}`,
4060 }, {
4061 name: jsontest.Name("Functions/Struct/Embedded"),
4062 opts: []Options{
4063 WithMarshalers(JoinMarshalers(
4064 MarshalFunc(func(v structEmbeddedL1) ([]byte, error) {
4065 panic("should not be called")
4066 }),
4067 MarshalToFunc(func(enc *jsontext.Encoder, v *StructEmbed2) error {
4068 panic("should not be called")
4069 }),
4070 )),
4071 },
4072 in: structEmbedded{},
4073 want: `{"D":""}`,
4074 }, {
4075 name: jsontest.Name("Functions/Slice/Elem"),
4076 opts: []Options{
4077 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
4078 return []byte(`"` + strconv.FormatBool(v) + `"`), nil
4079 })),
4080 },
4081 in: []bool{true, false},
4082 want: `["true","false"]`,
4083 }, {
4084 name: jsontest.Name("Functions/Array/Elem"),
4085 opts: []Options{
4086 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
4087 return enc.WriteValue([]byte(`"` + strconv.FormatBool(*v) + `"`))
4088 })),
4089 },
4090 in: [2]bool{true, false},
4091 want: `["true","false"]`,
4092 }, {
4093 name: jsontest.Name("Functions/Pointer/Nil"),
4094 opts: []Options{
4095 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
4096 panic("should not be called")
4097 })),
4098 },
4099 in: struct{ X *bool }{nil},
4100 want: `{"X":null}`,
4101 }, {
4102 name: jsontest.Name("Functions/Pointer/NonNil"),
4103 opts: []Options{
4104 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
4105 return enc.WriteValue([]byte(`"called"`))
4106 })),
4107 },
4108 in: struct{ X *bool }{new(false)},
4109 want: `{"X":"called"}`,
4110 }, {
4111 name: jsontest.Name("Functions/Interface/Nil"),
4112 opts: []Options{
4113 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
4114 panic("should not be called")
4115 })),
4116 },
4117 in: struct{ X fmt.Stringer }{nil},
4118 want: `{"X":null}`,
4119 }, {
4120 name: jsontest.Name("Functions/Interface/NonNil/MatchInterface"),
4121 opts: []Options{
4122 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
4123 return enc.WriteValue([]byte(`"called"`))
4124 })),
4125 },
4126 in: struct{ X fmt.Stringer }{valueStringer{}},
4127 want: `{"X":"called"}`,
4128 }, {
4129 name: jsontest.Name("Functions/Interface/NonNil/MatchConcrete"),
4130 opts: []Options{
4131 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4132 return enc.WriteValue([]byte(`"called"`))
4133 })),
4134 },
4135 in: struct{ X fmt.Stringer }{valueStringer{}},
4136 want: `{"X":"called"}`,
4137 }, {
4138 name: jsontest.Name("Functions/Interface/NonNil/MatchPointer"),
4139 opts: []Options{
4140 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4141 return enc.WriteValue([]byte(`"called"`))
4142 })),
4143 },
4144 in: struct{ X fmt.Stringer }{valueStringer{}},
4145 want: `{"X":"called"}`,
4146 }, {
4147 name: jsontest.Name("Functions/Interface/Any"),
4148 opts: []Options{
4149 WithMarshalers(func() *Marshalers {
4150 type P struct {
4151 D int
4152 N int64
4153 }
4154 type PV struct {
4155 P P
4156 V any
4157 }
4158
4159 var lastChecks []func() error
4160 checkLast := func() error {
4161 for _, fn := range lastChecks {
4162 if err := fn(); err != nil {
4163 return err
4164 }
4165 }
4166 return errors.ErrUnsupported
4167 }
4168 makeValueChecker := func(name string, want []PV) func(e *jsontext.Encoder, v any) error {
4169 checkNext := func(e *jsontext.Encoder, v any) error {
4170 xe := export.Encoder(e)
4171 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4172 rv := reflect.ValueOf(v)
4173 pv := PV{p, v}
4174 switch {
4175 case len(want) == 0:
4176 return fmt.Errorf("%s: %v: got more values than expected", name, p)
4177 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
4178 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
4179 case !reflect.DeepEqual(pv, want[0]):
4180 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
4181 default:
4182 want = want[1:]
4183 return errors.ErrUnsupported
4184 }
4185 }
4186 lastChecks = append(lastChecks, func() error {
4187 if len(want) > 0 {
4188 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4189 }
4190 return nil
4191 })
4192 return checkNext
4193 }
4194 makePositionChecker := func(name string, want []P) func(e *jsontext.Encoder, v any) error {
4195 checkNext := func(e *jsontext.Encoder, v any) error {
4196 xe := export.Encoder(e)
4197 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4198 switch {
4199 case len(want) == 0:
4200 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
4201 case p != want[0]:
4202 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
4203 default:
4204 want = want[1:]
4205 return errors.ErrUnsupported
4206 }
4207 }
4208 lastChecks = append(lastChecks, func() error {
4209 if len(want) > 0 {
4210 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4211 }
4212 return nil
4213 })
4214 return checkNext
4215 }
4216
4217 wantAny := []PV{
4218 {P{0, 0}, new([]any{
4219 nil,
4220 valueStringer{},
4221 (*valueStringer)(nil),
4222 new(valueStringer{}),
4223 (**valueStringer)(nil),
4224 new((*valueStringer)(nil)),
4225 new(new(valueStringer{})),
4226 pointerStringer{},
4227 (*pointerStringer)(nil),
4228 new(pointerStringer{}),
4229 (**pointerStringer)(nil),
4230 new((*pointerStringer)(nil)),
4231 new(new(pointerStringer{})),
4232 "LAST",
4233 })},
4234 {P{1, 0}, new(any(nil))},
4235 {P{1, 1}, new(any(valueStringer{}))},
4236 {P{1, 1}, new(valueStringer{})},
4237 {P{1, 2}, new(any((*valueStringer)(nil)))},
4238 {P{1, 2}, new((*valueStringer)(nil))},
4239 {P{1, 3}, new(any(new(valueStringer{})))},
4240 {P{1, 3}, new(new(valueStringer{}))},
4241 {P{1, 3}, new(valueStringer{})},
4242 {P{1, 4}, new(any((**valueStringer)(nil)))},
4243 {P{1, 4}, new((**valueStringer)(nil))},
4244 {P{1, 5}, new(any(new((*valueStringer)(nil))))},
4245 {P{1, 5}, new(new((*valueStringer)(nil)))},
4246 {P{1, 5}, new((*valueStringer)(nil))},
4247 {P{1, 6}, new(any(new(new(valueStringer{}))))},
4248 {P{1, 6}, new(new(new(valueStringer{})))},
4249 {P{1, 6}, new(new(valueStringer{}))},
4250 {P{1, 6}, new(valueStringer{})},
4251 {P{1, 7}, new(any(pointerStringer{}))},
4252 {P{1, 7}, new(pointerStringer{})},
4253 {P{1, 8}, new(any((*pointerStringer)(nil)))},
4254 {P{1, 8}, new((*pointerStringer)(nil))},
4255 {P{1, 9}, new(any(new(pointerStringer{})))},
4256 {P{1, 9}, new(new(pointerStringer{}))},
4257 {P{1, 9}, new(pointerStringer{})},
4258 {P{1, 10}, new(any((**pointerStringer)(nil)))},
4259 {P{1, 10}, new((**pointerStringer)(nil))},
4260 {P{1, 11}, new(any(new((*pointerStringer)(nil))))},
4261 {P{1, 11}, new(new((*pointerStringer)(nil)))},
4262 {P{1, 11}, new((*pointerStringer)(nil))},
4263 {P{1, 12}, new(any(new(new(pointerStringer{}))))},
4264 {P{1, 12}, new(new(new(pointerStringer{})))},
4265 {P{1, 12}, new(new(pointerStringer{}))},
4266 {P{1, 12}, new(pointerStringer{})},
4267 {P{1, 13}, new(any("LAST"))},
4268 {P{1, 13}, new("LAST")},
4269 }
4270 checkAny := makeValueChecker("any", wantAny)
4271 anyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v any) error {
4272 return checkAny(enc, v)
4273 })
4274
4275 var wantPointerAny []PV
4276 for _, v := range wantAny {
4277 if _, ok := v.V.(*any); ok {
4278 wantPointerAny = append(wantPointerAny, v)
4279 }
4280 }
4281 checkPointerAny := makeValueChecker("*any", wantPointerAny)
4282 pointerAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *any) error {
4283 return checkPointerAny(enc, v)
4284 })
4285
4286 checkNamedAny := makeValueChecker("namedAny", wantAny)
4287 namedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v namedAny) error {
4288 return checkNamedAny(enc, v)
4289 })
4290
4291 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
4292 pointerNamedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *namedAny) error {
4293 return checkPointerNamedAny(enc, v)
4294 })
4295
4296 type stringer = fmt.Stringer
4297 var wantStringer []PV
4298 for _, v := range wantAny {
4299 if _, ok := v.V.(stringer); ok {
4300 wantStringer = append(wantStringer, v)
4301 }
4302 }
4303 checkStringer := makeValueChecker("stringer", wantStringer)
4304 stringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v stringer) error {
4305 return checkStringer(enc, v)
4306 })
4307
4308 checkPointerStringer := makeValueChecker("*stringer", nil)
4309 pointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *stringer) error {
4310 return checkPointerStringer(enc, v)
4311 })
4312
4313 wantValueStringer := []P{{1, 1}, {1, 3}, {1, 6}}
4314 checkValueValueStringer := makePositionChecker("valueStringer", wantValueStringer)
4315 valueValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4316 return checkValueValueStringer(enc, v)
4317 })
4318
4319 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
4320 pointerValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4321 return checkPointerValueStringer(enc, v)
4322 })
4323
4324 wantPointerStringer := []P{{1, 7}, {1, 9}, {1, 12}}
4325 checkValuePointerStringer := makePositionChecker("pointerStringer", wantPointerStringer)
4326 valuePointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v pointerStringer) error {
4327 return checkValuePointerStringer(enc, v)
4328 })
4329
4330 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
4331 pointerPointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *pointerStringer) error {
4332 return checkPointerPointerStringer(enc, v)
4333 })
4334
4335 lastMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
4336 return checkLast()
4337 })
4338
4339 return JoinMarshalers(
4340 anyMarshaler,
4341 pointerAnyMarshaler,
4342 namedAnyMarshaler,
4343 pointerNamedAnyMarshaler,
4344 stringerMarshaler,
4345 pointerStringerMarshaler,
4346 valueValueStringerMarshaler,
4347 pointerValueStringerMarshaler,
4348 valuePointerStringerMarshaler,
4349 pointerPointerStringerMarshaler,
4350 lastMarshaler,
4351 )
4352 }()),
4353 },
4354 in: []any{
4355 nil,
4356 valueStringer{},
4357 (*valueStringer)(nil),
4358 new(valueStringer{}),
4359 (**valueStringer)(nil),
4360 new((*valueStringer)(nil)),
4361 new(new(valueStringer{})),
4362 pointerStringer{},
4363 (*pointerStringer)(nil),
4364 new(pointerStringer{}),
4365 (**pointerStringer)(nil),
4366 new((*pointerStringer)(nil)),
4367 new(new(pointerStringer{})),
4368 "LAST",
4369 },
4370 want: `[null,{},null,{},null,null,{},{},null,{},null,null,{},"LAST"]`,
4371 }, {
4372 name: jsontest.Name("Functions/Precedence/V1First"),
4373 opts: []Options{
4374 WithMarshalers(JoinMarshalers(
4375 MarshalFunc(func(bool) ([]byte, error) {
4376 return []byte(`"called"`), nil
4377 }),
4378 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4379 panic("should not be called")
4380 }),
4381 )),
4382 },
4383 in: true,
4384 want: `"called"`,
4385 }, {
4386 name: jsontest.Name("Functions/Precedence/V2First"),
4387 opts: []Options{
4388 WithMarshalers(JoinMarshalers(
4389 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4390 return enc.WriteToken(jsontext.String("called"))
4391 }),
4392 MarshalFunc(func(bool) ([]byte, error) {
4393 panic("should not be called")
4394 }),
4395 )),
4396 },
4397 in: true,
4398 want: `"called"`,
4399 }, {
4400 name: jsontest.Name("Functions/Precedence/V2Skipped"),
4401 opts: []Options{
4402 WithMarshalers(JoinMarshalers(
4403 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4404 return errors.ErrUnsupported
4405 }),
4406 MarshalFunc(func(bool) ([]byte, error) {
4407 return []byte(`"called"`), nil
4408 }),
4409 )),
4410 },
4411 in: true,
4412 want: `"called"`,
4413 }, {
4414 name: jsontest.Name("Functions/Precedence/NestedFirst"),
4415 opts: []Options{
4416 WithMarshalers(JoinMarshalers(
4417 JoinMarshalers(
4418 MarshalFunc(func(bool) ([]byte, error) {
4419 return []byte(`"called"`), nil
4420 }),
4421 ),
4422 MarshalFunc(func(bool) ([]byte, error) {
4423 panic("should not be called")
4424 }),
4425 )),
4426 },
4427 in: true,
4428 want: `"called"`,
4429 }, {
4430 name: jsontest.Name("Functions/Precedence/NestedLast"),
4431 opts: []Options{
4432 WithMarshalers(JoinMarshalers(
4433 MarshalFunc(func(bool) ([]byte, error) {
4434 return []byte(`"called"`), nil
4435 }),
4436 JoinMarshalers(
4437 MarshalFunc(func(bool) ([]byte, error) {
4438 panic("should not be called")
4439 }),
4440 ),
4441 )),
4442 },
4443 in: true,
4444 want: `"called"`,
4445 }, {
4446 name: jsontest.Name("Duration/Zero"),
4447 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4448 in: struct {
4449 D1 time.Duration `json:",format:units"`
4450 D2 time.Duration `json:",format:nano"`
4451 }{0, 0},
4452 want: `{"D1":"0s","D2":0}`,
4453 }, {
4454 name: jsontest.Name("Duration/Positive"),
4455 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4456 in: struct {
4457 D1 time.Duration `json:",format:units"`
4458 D2 time.Duration `json:",format:nano"`
4459 }{
4460 123456789123456789,
4461 123456789123456789,
4462 },
4463 want: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
4464 }, {
4465 name: jsontest.Name("Duration/Negative"),
4466 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4467 in: struct {
4468 D1 time.Duration `json:",format:units"`
4469 D2 time.Duration `json:",format:nano"`
4470 }{
4471 -123456789123456789,
4472 -123456789123456789,
4473 },
4474 want: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
4475 }, {
4476 name: jsontest.Name("Duration/Nanos/String"),
4477 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4478 in: struct {
4479 D1 time.Duration `json:",string,format:nano"`
4480 D2 time.Duration `json:",string,format:nano"`
4481 D3 time.Duration `json:",string,format:nano"`
4482 }{
4483 math.MinInt64,
4484 0,
4485 math.MaxInt64,
4486 },
4487 want: `{"D1":"-9223372036854775808","D2":"0","D3":"9223372036854775807"}`,
4488 }, {
4489 name: jsontest.Name("Duration/Format/Invalid"),
4490 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4491 in: struct {
4492 D time.Duration `json:",format:invalid"`
4493 }{},
4494 want: `{"D"`,
4495 wantErr: EM(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, T[time.Duration]()),
4496 }, {
4497
4503 name: jsontest.Name("Duration/Format"),
4504 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true)},
4505 in: structDurationFormat{
4506 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4507 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4508 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4509 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4510 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4511 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4512 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4513 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4514 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4515 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4516 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4517 },
4518 want: `{
4519 "D1": "12h34m56.078090012s",
4520 "D2": "12h34m56.078090012s",
4521 "D3": 45296.078090012,
4522 "D4": "45296.078090012",
4523 "D5": 45296078.090012,
4524 "D6": "45296078.090012",
4525 "D7": 45296078090.012,
4526 "D8": "45296078090.012",
4527 "D9": 45296078090012,
4528 "D10": "45296078090012",
4529 "D11": "PT12H34M56.078090012S"
4530 }`,
4531 }, {
4532
4541
4546 name: jsontest.Name("Duration/MapKey/Legacy"),
4547 opts: []Options{jsonflags.FormatDurationAsNano | 1},
4548 in: map[time.Duration]string{time.Second: ""},
4549 want: `{"1000000000":""}`,
4550 }, {
4551 name: jsontest.Name("Time/Zero"),
4552 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4553 in: struct {
4554 T1 time.Time
4555 T2 time.Time `json:",format:RFC822"`
4556 T3 time.Time `json:",format:'2006-01-02'"`
4557 T4 time.Time `json:",omitzero"`
4558 T5 time.Time `json:",omitempty"`
4559 }{
4560 time.Time{},
4561 time.Time{},
4562 time.Time{},
4563
4564
4565 time.Date(1, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC", 0)),
4566 time.Time{},
4567 },
4568 want: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T5":"0001-01-01T00:00:00Z"}`,
4569 }, {
4570 name: jsontest.Name("Time/Format"),
4571 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsontext.Multiline(true)},
4572 in: structTimeFormat{
4573 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4574 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4575 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4576 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4577 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4578 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4579 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4580 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4581 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4582 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4583 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4584 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4585 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4586 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4587 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4588 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4589 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4590 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4591 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4592 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4593 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4594 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4595 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4596 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4597 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4598 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4599 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4600 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4601 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4602 },
4603 want: `{
4604 "T1": "1234-01-02T03:04:05.000000006Z",
4605 "T2": "Mon Jan 2 03:04:05 1234",
4606 "T3": "Mon Jan 2 03:04:05 UTC 1234",
4607 "T4": "Mon Jan 02 03:04:05 +0000 1234",
4608 "T5": "02 Jan 34 03:04 UTC",
4609 "T6": "02 Jan 34 03:04 +0000",
4610 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
4611 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
4612 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
4613 "T10": "1234-01-02T03:04:05Z",
4614 "T11": "1234-01-02T03:04:05.000000006Z",
4615 "T12": "3:04AM",
4616 "T13": "Jan 2 03:04:05",
4617 "T14": "Jan 2 03:04:05.000",
4618 "T15": "Jan 2 03:04:05.000000",
4619 "T16": "Jan 2 03:04:05.000000006",
4620 "T17": "1234-01-02 03:04:05",
4621 "T18": "1234-01-02",
4622 "T19": "03:04:05",
4623 "T20": "1234-01-02",
4624 "T21": "\"weird\"1234",
4625 "T22": -23225777754.999999994,
4626 "T23": "-23225777754.999999994",
4627 "T24": -23225777754999.999994,
4628 "T25": "-23225777754999.999994",
4629 "T26": -23225777754999999.994,
4630 "T27": "-23225777754999999.994",
4631 "T28": -23225777754999999994,
4632 "T29": "-23225777754999999994"
4633 }`,
4634 }, {
4635 name: jsontest.Name("Time/Format/Invalid"),
4636 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4637 in: struct {
4638 T time.Time `json:",format:UndefinedConstant"`
4639 }{},
4640 want: `{"T"`,
4641 wantErr: EM(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4642 }, {
4643 name: jsontest.Name("Time/Format/String/Invalid"),
4644 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
4645 in: structTimeFormatStringInvalid{},
4646 want: `{"T"`,
4647 wantErr: EM(errInvalidStringTag).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4648 }, {
4649 name: jsontest.Name("Time/Format/YearOverflow"),
4650 in: struct {
4651 T1 time.Time
4652 T2 time.Time
4653 }{
4654 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4655 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC),
4656 },
4657 want: `{"T1":"9999-12-31T23:59:59Z","T2"`,
4658 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"9999-12-31T23:59:59Z","T2":`, "/T2").withType(0, timeTimeType),
4659 }, {
4660 name: jsontest.Name("Time/Format/YearUnderflow"),
4661 in: struct {
4662 T1 time.Time
4663 T2 time.Time
4664 }{
4665 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
4666 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4667 },
4668 want: `{"T1":"0000-01-01T00:00:00Z","T2"`,
4669 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"0000-01-01T00:00:00Z","T2":`, "/T2").withType(0, timeTimeType),
4670 }, {
4671 name: jsontest.Name("Time/Format/YearUnderflow"),
4672 in: struct{ T time.Time }{time.Date(-998, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second)},
4673 want: `{"T"`,
4674 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4675 }, {
4676 name: jsontest.Name("Time/Format/ZoneExact"),
4677 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 23*60*60+59*60))},
4678 want: `{"T":"2020-01-01T00:00:00+23:59"}`,
4679 }, {
4680 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4681 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 24*60*60))},
4682 want: `{"T"`,
4683 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4684 }, {
4685 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4686 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 123*60*60))},
4687 want: `{"T"`,
4688 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4689 }, {
4690 name: jsontest.Name("Time/IgnoreInvalidFormat"),
4691 opts: []Options{invalidFormatOption},
4692 in: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
4693 want: `"2000-01-01T00:00:00Z"`,
4694 }}
4695
4696 for _, tt := range tests {
4697 t.Run(tt.name.Name, func(t *testing.T) {
4698 var got []byte
4699 var gotErr error
4700 if tt.useWriter {
4701 bb := new(struct{ bytes.Buffer })
4702 gotErr = MarshalWrite(bb, tt.in, tt.opts...)
4703 got = bb.Bytes()
4704 } else {
4705 got, gotErr = Marshal(tt.in, tt.opts...)
4706 }
4707 if tt.canonicalize {
4708 (*jsontext.Value)(&got).Canonicalize()
4709 }
4710 if string(got) != tt.want {
4711 t.Errorf("%s: Marshal output mismatch:\ngot %s\nwant %s", tt.name.Where, got, tt.want)
4712 }
4713 if !reflect.DeepEqual(gotErr, tt.wantErr) {
4714 t.Errorf("%s: Marshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
4715 }
4716 })
4717 }
4718 }
4719
4720 func TestUnmarshal(t *testing.T) {
4721 tests := []struct {
4722 name jsontest.CaseName
4723 opts []Options
4724 inBuf string
4725 inVal any
4726 want any
4727 wantErr error
4728 skip bool
4729 }{{
4730 name: jsontest.Name("Nil"),
4731 inBuf: `null`,
4732 wantErr: EU(internal.ErrNonNilReference),
4733 }, {
4734 name: jsontest.Name("NilPointer"),
4735 inBuf: `null`,
4736 inVal: (*string)(nil),
4737 want: (*string)(nil),
4738 wantErr: EU(internal.ErrNonNilReference).withType(0, T[*string]()),
4739 }, {
4740 name: jsontest.Name("NonPointer"),
4741 inBuf: `null`,
4742 inVal: "unchanged",
4743 want: "unchanged",
4744 wantErr: EU(internal.ErrNonNilReference).withType(0, T[string]()),
4745 }, {
4746 name: jsontest.Name("Bools/TrailingJunk"),
4747 inBuf: `falsetrue`,
4748 inVal: new(true),
4749 want: new(false),
4750 wantErr: newInvalidCharacterError("t", "after top-level value", len64(`false`), ""),
4751 }, {
4752 name: jsontest.Name("Bools/Null"),
4753 inBuf: `null`,
4754 inVal: new(true),
4755 want: new(false),
4756 }, {
4757 name: jsontest.Name("Bools"),
4758 inBuf: `[null,false,true]`,
4759 inVal: new([]bool),
4760 want: new([]bool{false, false, true}),
4761 }, {
4762 name: jsontest.Name("Bools/Named"),
4763 inBuf: `[null,false,true]`,
4764 inVal: new([]namedBool),
4765 want: new([]namedBool{false, false, true}),
4766 }, {
4767 name: jsontest.Name("Bools/Invalid/StringifiedFalse"),
4768 opts: []Options{StringifyNumbers(true)},
4769 inBuf: `"false"`,
4770 inVal: new(true),
4771 want: new(true),
4772 wantErr: EU(nil).withType('"', boolType),
4773 }, {
4774 name: jsontest.Name("Bools/Invalid/StringifiedTrue"),
4775 opts: []Options{StringifyNumbers(true)},
4776 inBuf: `"true"`,
4777 inVal: new(true),
4778 want: new(true),
4779 wantErr: EU(nil).withType('"', boolType),
4780 }, {
4781 name: jsontest.Name("Bools/StringifiedBool/True"),
4782 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
4783 inBuf: `"true"`,
4784 inVal: new(false),
4785 want: new(true),
4786 }, {
4787 name: jsontest.Name("Bools/StringifiedBool/False"),
4788 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
4789 inBuf: `"false"`,
4790 inVal: new(true),
4791 want: new(false),
4792 }, {
4793 name: jsontest.Name("Bools/StringifiedBool/InvalidWhitespace"),
4794 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
4795 inBuf: `"false "`,
4796 inVal: new(true),
4797 want: new(true),
4798 wantErr: EU(strconv.ErrSyntax).withVal(`"false "`).withType('"', boolType),
4799 }, {
4800 name: jsontest.Name("Bools/StringifiedBool/InvalidBool"),
4801 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
4802 inBuf: `false`,
4803 inVal: new(true),
4804 want: new(true),
4805 wantErr: EU(nil).withType('f', boolType),
4806 }, {
4807 name: jsontest.Name("Bools/Invalid/Number"),
4808 inBuf: `0`,
4809 inVal: new(true),
4810 want: new(true),
4811 wantErr: EU(nil).withType('0', boolType),
4812 }, {
4813 name: jsontest.Name("Bools/Invalid/String"),
4814 inBuf: `""`,
4815 inVal: new(true),
4816 want: new(true),
4817 wantErr: EU(nil).withType('"', boolType),
4818 }, {
4819 name: jsontest.Name("Bools/Invalid/Object"),
4820 inBuf: `{}`,
4821 inVal: new(true),
4822 want: new(true),
4823 wantErr: EU(nil).withType('{', boolType),
4824 }, {
4825 name: jsontest.Name("Bools/Invalid/Array"),
4826 inBuf: `[]`,
4827 inVal: new(true),
4828 want: new(true),
4829 wantErr: EU(nil).withType('[', boolType),
4830 }, {
4831 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
4832 opts: []Options{invalidFormatOption},
4833 inBuf: `false`,
4834 inVal: new(true),
4835 want: new(false),
4836 }, {
4837 name: jsontest.Name("Strings/Null"),
4838 inBuf: `null`,
4839 inVal: new("something"),
4840 want: new(""),
4841 }, {
4842 name: jsontest.Name("Strings"),
4843 inBuf: `[null,"","hello","世界"]`,
4844 inVal: new([]string),
4845 want: new([]string{"", "", "hello", "世界"}),
4846 }, {
4847 name: jsontest.Name("Strings/Escaped"),
4848 inBuf: `[null,"","\u0068\u0065\u006c\u006c\u006f","\u4e16\u754c"]`,
4849 inVal: new([]string),
4850 want: new([]string{"", "", "hello", "世界"}),
4851 }, {
4852 name: jsontest.Name("Strings/Named"),
4853 inBuf: `[null,"","hello","世界"]`,
4854 inVal: new([]namedString),
4855 want: new([]namedString{"", "", "hello", "世界"}),
4856 }, {
4857 name: jsontest.Name("Strings/Invalid/False"),
4858 inBuf: `false`,
4859 inVal: new("nochange"),
4860 want: new("nochange"),
4861 wantErr: EU(nil).withType('f', stringType),
4862 }, {
4863 name: jsontest.Name("Strings/Invalid/True"),
4864 inBuf: `true`,
4865 inVal: new("nochange"),
4866 want: new("nochange"),
4867 wantErr: EU(nil).withType('t', stringType),
4868 }, {
4869 name: jsontest.Name("Strings/Invalid/Object"),
4870 inBuf: `{}`,
4871 inVal: new("nochange"),
4872 want: new("nochange"),
4873 wantErr: EU(nil).withType('{', stringType),
4874 }, {
4875 name: jsontest.Name("Strings/Invalid/Array"),
4876 inBuf: `[]`,
4877 inVal: new("nochange"),
4878 want: new("nochange"),
4879 wantErr: EU(nil).withType('[', stringType),
4880 }, {
4881 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
4882 opts: []Options{invalidFormatOption},
4883 inBuf: `"hello"`,
4884 inVal: new("goodbye"),
4885 want: new("hello"),
4886 }, {
4887 name: jsontest.Name("Strings/StringifiedString"),
4888 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
4889 inBuf: `"\"foo\""`,
4890 inVal: new(string),
4891 want: new("foo"),
4892 }, {
4893 name: jsontest.Name("Strings/StringifiedString/InvalidWhitespace"),
4894 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
4895 inBuf: `"\"foo\" "`,
4896 inVal: new(string),
4897 want: new(string),
4898 wantErr: EU(newInvalidCharacterError(" ", "after string value", 0, "")).withType('"', stringType),
4899 }, {
4900 name: jsontest.Name("Strings/StringifiedString/InvalidString"),
4901 opts: []Options{jsonflags.StringTag | jsonflags.StringifyWithLegacySemantics | 1},
4902 inBuf: `""`,
4903 inVal: new(string),
4904 want: new(string),
4905 wantErr: EU(&jsontext.SyntacticError{Err: io.ErrUnexpectedEOF}).withType('"', stringType),
4906 }, {
4907 name: jsontest.Name("Bytes/Null"),
4908 inBuf: `null`,
4909 inVal: new([]byte("something")),
4910 want: new([]byte(nil)),
4911 }, {
4912 name: jsontest.Name("Bytes"),
4913 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4914 inVal: new([][]byte),
4915 want: new([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4916 }, {
4917 name: jsontest.Name("Bytes/Large"),
4918 inBuf: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
4919 inVal: new([]byte),
4920 want: new([]byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on.")),
4921 }, {
4922 name: jsontest.Name("Bytes/Reuse"),
4923 inBuf: `"AQID"`,
4924 inVal: new([]byte("changed")),
4925 want: new([]byte{1, 2, 3}),
4926 }, {
4927 name: jsontest.Name("Bytes/Escaped"),
4928 inBuf: `[null,"","\u0041\u0051\u003d\u003d","\u0041\u0051\u0049\u003d","\u0041\u0051\u0049\u0044"]`,
4929 inVal: new([][]byte),
4930 want: new([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4931 }, {
4932 name: jsontest.Name("Bytes/Named"),
4933 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4934 inVal: new([]namedBytes),
4935 want: new([]namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4936 }, {
4937 name: jsontest.Name("Bytes/NotStringified"),
4938 opts: []Options{StringifyNumbers(true)},
4939 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4940 inVal: new([][]byte),
4941 want: new([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4942 }, {
4943
4944
4945 name: jsontest.Name("Bytes/Invariant"),
4946 inBuf: `[null,[],[1],[1,2],[1,2,3]]`,
4947 inVal: new([][]namedByte),
4948 want: new([][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4949 }, {
4950
4951
4952 name: jsontest.Name("Bytes/ByteArray"),
4953 inBuf: `"aGVsbG8="`,
4954 inVal: new([5]byte),
4955 want: new([5]byte{'h', 'e', 'l', 'l', 'o'}),
4956 }, {
4957 name: jsontest.Name("Bytes/ByteArray0/Valid"),
4958 inBuf: `""`,
4959 inVal: new([0]byte),
4960 want: new([0]byte{}),
4961 }, {
4962 name: jsontest.Name("Bytes/ByteArray0/Invalid"),
4963 inBuf: `"A"`,
4964 inVal: new([0]byte),
4965 want: new([0]byte{}),
4966 wantErr: EU(func() error {
4967 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("A"))
4968 return err
4969 }()).withType('"', T[[0]byte]()),
4970 }, {
4971 name: jsontest.Name("Bytes/ByteArray0/Overflow"),
4972 inBuf: `"AA=="`,
4973 inVal: new([0]byte),
4974 want: new([0]byte{}),
4975 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 0")).withType('"', T[[0]byte]()),
4976 }, {
4977 name: jsontest.Name("Bytes/ByteArray1/Valid"),
4978 inBuf: `"AQ=="`,
4979 inVal: new([1]byte),
4980 want: new([1]byte{1}),
4981 }, {
4982 name: jsontest.Name("Bytes/ByteArray1/Invalid"),
4983 inBuf: `"$$=="`,
4984 inVal: new([1]byte),
4985 want: new([1]byte{}),
4986 wantErr: EU(func() error {
4987 _, err := base64.StdEncoding.Decode(make([]byte, 1), []byte("$$=="))
4988 return err
4989 }()).withType('"', T[[1]byte]()),
4990 }, {
4991 name: jsontest.Name("Bytes/ByteArray1/Underflow"),
4992 inBuf: `""`,
4993 inVal: new([1]byte),
4994 want: new([1]byte{}),
4995 wantErr: EU(errors.New("decoded length of 0 mismatches array length of 1")).withType('"', T[[1]byte]()),
4996 }, {
4997 name: jsontest.Name("Bytes/ByteArray1/Overflow"),
4998 inBuf: `"AQI="`,
4999 inVal: new([1]byte),
5000 want: new([1]byte{1}),
5001 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 1")).withType('"', T[[1]byte]()),
5002 }, {
5003 name: jsontest.Name("Bytes/ByteArray2/Valid"),
5004 inBuf: `"AQI="`,
5005 inVal: new([2]byte),
5006 want: new([2]byte{1, 2}),
5007 }, {
5008 name: jsontest.Name("Bytes/ByteArray2/Invalid"),
5009 inBuf: `"$$$="`,
5010 inVal: new([2]byte),
5011 want: new([2]byte{}),
5012 wantErr: EU(func() error {
5013 _, err := base64.StdEncoding.Decode(make([]byte, 2), []byte("$$$="))
5014 return err
5015 }()).withType('"', T[[2]byte]()),
5016 }, {
5017 name: jsontest.Name("Bytes/ByteArray2/Underflow"),
5018 inBuf: `"AQ=="`,
5019 inVal: new([2]byte),
5020 want: new([2]byte{1, 0}),
5021 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 2")).withType('"', T[[2]byte]()),
5022 }, {
5023 name: jsontest.Name("Bytes/ByteArray2/Underflow/Allowed"),
5024 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
5025 inBuf: `"AQ=="`,
5026 inVal: new([2]byte),
5027 want: new([2]byte{1, 0}),
5028 }, {
5029 name: jsontest.Name("Bytes/ByteArray2/Overflow"),
5030 inBuf: `"AQID"`,
5031 inVal: new([2]byte),
5032 want: new([2]byte{1, 2}),
5033 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 2")).withType('"', T[[2]byte]()),
5034 }, {
5035 name: jsontest.Name("Bytes/ByteArray2/Overflow/Allowed"),
5036 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
5037 inBuf: `"AQID"`,
5038 inVal: new([2]byte),
5039 want: new([2]byte{1, 2}),
5040 }, {
5041 name: jsontest.Name("Bytes/ByteArray3/Valid"),
5042 inBuf: `"AQID"`,
5043 inVal: new([3]byte),
5044 want: new([3]byte{1, 2, 3}),
5045 }, {
5046 name: jsontest.Name("Bytes/ByteArray3/Invalid"),
5047 inBuf: `"$$$$"`,
5048 inVal: new([3]byte),
5049 want: new([3]byte{}),
5050 wantErr: EU(func() error {
5051 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("$$$$"))
5052 return err
5053 }()).withType('"', T[[3]byte]()),
5054 }, {
5055 name: jsontest.Name("Bytes/ByteArray3/Underflow"),
5056 inBuf: `"AQI="`,
5057 inVal: new([3]byte{0xff, 0xff, 0xff}),
5058 want: new([3]byte{1, 2, 0}),
5059 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 3")).withType('"', T[[3]byte]()),
5060 }, {
5061 name: jsontest.Name("Bytes/ByteArray3/Overflow"),
5062 inBuf: `"AQIDAQ=="`,
5063 inVal: new([3]byte),
5064 want: new([3]byte{1, 2, 3}),
5065 wantErr: EU(errors.New("decoded length of 4 mismatches array length of 3")).withType('"', T[[3]byte]()),
5066 }, {
5067 name: jsontest.Name("Bytes/ByteArray4/Valid"),
5068 inBuf: `"AQIDBA=="`,
5069 inVal: new([4]byte),
5070 want: new([4]byte{1, 2, 3, 4}),
5071 }, {
5072 name: jsontest.Name("Bytes/ByteArray4/Invalid"),
5073 inBuf: `"$$$$$$=="`,
5074 inVal: new([4]byte),
5075 want: new([4]byte{}),
5076 wantErr: EU(func() error {
5077 _, err := base64.StdEncoding.Decode(make([]byte, 4), []byte("$$$$$$=="))
5078 return err
5079 }()).withType('"', T[[4]byte]()),
5080 }, {
5081 name: jsontest.Name("Bytes/ByteArray4/Underflow"),
5082 inBuf: `"AQID"`,
5083 inVal: new([4]byte),
5084 want: new([4]byte{1, 2, 3, 0}),
5085 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 4")).withType('"', T[[4]byte]()),
5086 }, {
5087 name: jsontest.Name("Bytes/ByteArray4/Overflow"),
5088 inBuf: `"AQIDBAU="`,
5089 inVal: new([4]byte),
5090 want: new([4]byte{1, 2, 3, 4}),
5091 wantErr: EU(errors.New("decoded length of 5 mismatches array length of 4")).withType('"', T[[4]byte]()),
5092 }, {
5093
5094
5095 name: jsontest.Name("Bytes/NamedByteArray"),
5096 inBuf: `[104,101,108,108,111]`,
5097 inVal: new([5]namedByte),
5098 want: new([5]namedByte{'h', 'e', 'l', 'l', 'o'}),
5099 }, {
5100 name: jsontest.Name("Bytes/Valid/Denormalized"),
5101 inBuf: `"AR=="`,
5102 inVal: new([]byte),
5103 want: new([]byte{1}),
5104 }, {
5105 name: jsontest.Name("Bytes/Invalid/Unpadded1"),
5106 inBuf: `"AQ="`,
5107 inVal: new([]byte("nochange")),
5108 want: new([]byte("nochange")),
5109 wantErr: EU(func() error {
5110 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ="))
5111 return err
5112 }()).withType('"', bytesType),
5113 }, {
5114 name: jsontest.Name("Bytes/Invalid/Unpadded2"),
5115 inBuf: `"AQ"`,
5116 inVal: new([]byte("nochange")),
5117 want: new([]byte("nochange")),
5118 wantErr: EU(func() error {
5119 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ"))
5120 return err
5121 }()).withType('"', bytesType),
5122 }, {
5123 name: jsontest.Name("Bytes/Invalid/Character"),
5124 inBuf: `"@@@@"`,
5125 inVal: new([]byte("nochange")),
5126 want: new([]byte("nochange")),
5127 wantErr: EU(func() error {
5128 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("@@@@"))
5129 return err
5130 }()).withType('"', bytesType),
5131 }, {
5132 name: jsontest.Name("Bytes/Invalid/Bool"),
5133 inBuf: `true`,
5134 inVal: new([]byte("nochange")),
5135 want: new([]byte("nochange")),
5136 wantErr: EU(nil).withType('t', bytesType),
5137 }, {
5138 name: jsontest.Name("Bytes/Invalid/Number"),
5139 inBuf: `0`,
5140 inVal: new([]byte("nochange")),
5141 want: new([]byte("nochange")),
5142 wantErr: EU(nil).withType('0', bytesType),
5143 }, {
5144 name: jsontest.Name("Bytes/Invalid/Object"),
5145 inBuf: `{}`,
5146 inVal: new([]byte("nochange")),
5147 want: new([]byte("nochange")),
5148 wantErr: EU(nil).withType('{', bytesType),
5149 }, {
5150 name: jsontest.Name("Bytes/Invalid/Array"),
5151 inBuf: `[]`,
5152 inVal: new([]byte("nochange")),
5153 want: new([]byte("nochange")),
5154 wantErr: EU(nil).withType('[', bytesType),
5155 }, {
5156 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
5157 opts: []Options{invalidFormatOption},
5158 inBuf: `"aGVsbG8="`,
5159 inVal: new([]byte),
5160 want: new([]byte("hello")),
5161 }, {
5162 name: jsontest.Name("Ints/Null"),
5163 inBuf: `null`,
5164 inVal: new(int(1)),
5165 want: new(int(0)),
5166 }, {
5167 name: jsontest.Name("Ints/Int"),
5168 inBuf: `1`,
5169 inVal: new(int(0)),
5170 want: new(int(1)),
5171 }, {
5172 name: jsontest.Name("Ints/Int8/MinOverflow"),
5173 inBuf: `-129`,
5174 inVal: new(int8(-1)),
5175 want: new(int8(-1)),
5176 wantErr: EU(strconv.ErrRange).withVal(`-129`).withType('0', T[int8]()),
5177 }, {
5178 name: jsontest.Name("Ints/Int8/Min"),
5179 inBuf: `-128`,
5180 inVal: new(int8(0)),
5181 want: new(int8(-128)),
5182 }, {
5183 name: jsontest.Name("Ints/Int8/Max"),
5184 inBuf: `127`,
5185 inVal: new(int8(0)),
5186 want: new(int8(127)),
5187 }, {
5188 name: jsontest.Name("Ints/Int8/MaxOverflow"),
5189 inBuf: `128`,
5190 inVal: new(int8(-1)),
5191 want: new(int8(-1)),
5192 wantErr: EU(strconv.ErrRange).withVal(`128`).withType('0', T[int8]()),
5193 }, {
5194 name: jsontest.Name("Ints/Int16/MinOverflow"),
5195 inBuf: `-32769`,
5196 inVal: new(int16(-1)),
5197 want: new(int16(-1)),
5198 wantErr: EU(strconv.ErrRange).withVal(`-32769`).withType('0', T[int16]()),
5199 }, {
5200 name: jsontest.Name("Ints/Int16/Min"),
5201 inBuf: `-32768`,
5202 inVal: new(int16(0)),
5203 want: new(int16(-32768)),
5204 }, {
5205 name: jsontest.Name("Ints/Int16/Max"),
5206 inBuf: `32767`,
5207 inVal: new(int16(0)),
5208 want: new(int16(32767)),
5209 }, {
5210 name: jsontest.Name("Ints/Int16/MaxOverflow"),
5211 inBuf: `32768`,
5212 inVal: new(int16(-1)),
5213 want: new(int16(-1)),
5214 wantErr: EU(strconv.ErrRange).withVal(`32768`).withType('0', T[int16]()),
5215 }, {
5216 name: jsontest.Name("Ints/Int32/MinOverflow"),
5217 inBuf: `-2147483649`,
5218 inVal: new(int32(-1)),
5219 want: new(int32(-1)),
5220 wantErr: EU(strconv.ErrRange).withVal(`-2147483649`).withType('0', T[int32]()),
5221 }, {
5222 name: jsontest.Name("Ints/Int32/Min"),
5223 inBuf: `-2147483648`,
5224 inVal: new(int32(0)),
5225 want: new(int32(-2147483648)),
5226 }, {
5227 name: jsontest.Name("Ints/Int32/Max"),
5228 inBuf: `2147483647`,
5229 inVal: new(int32(0)),
5230 want: new(int32(2147483647)),
5231 }, {
5232 name: jsontest.Name("Ints/Int32/MaxOverflow"),
5233 inBuf: `2147483648`,
5234 inVal: new(int32(-1)),
5235 want: new(int32(-1)),
5236 wantErr: EU(strconv.ErrRange).withVal(`2147483648`).withType('0', T[int32]()),
5237 }, {
5238 name: jsontest.Name("Ints/Int64/MinOverflow"),
5239 inBuf: `-9223372036854775809`,
5240 inVal: new(int64(-1)),
5241 want: new(int64(-1)),
5242 wantErr: EU(strconv.ErrRange).withVal(`-9223372036854775809`).withType('0', T[int64]()),
5243 }, {
5244 name: jsontest.Name("Ints/Int64/Min"),
5245 inBuf: `-9223372036854775808`,
5246 inVal: new(int64(0)),
5247 want: new(int64(-9223372036854775808)),
5248 }, {
5249 name: jsontest.Name("Ints/Int64/Max"),
5250 inBuf: `9223372036854775807`,
5251 inVal: new(int64(0)),
5252 want: new(int64(9223372036854775807)),
5253 }, {
5254 name: jsontest.Name("Ints/Int64/MaxOverflow"),
5255 inBuf: `9223372036854775808`,
5256 inVal: new(int64(-1)),
5257 want: new(int64(-1)),
5258 wantErr: EU(strconv.ErrRange).withVal(`9223372036854775808`).withType('0', T[int64]()),
5259 }, {
5260 name: jsontest.Name("Ints/Named"),
5261 inBuf: `-6464`,
5262 inVal: new(namedInt64(0)),
5263 want: new(namedInt64(-6464)),
5264 }, {
5265 name: jsontest.Name("Ints/Stringified"),
5266 opts: []Options{StringifyNumbers(true)},
5267 inBuf: `"-6464"`,
5268 inVal: new(int),
5269 want: new(int(-6464)),
5270 }, {
5271 name: jsontest.Name("Ints/Stringified/Invalid"),
5272 opts: []Options{StringifyNumbers(true)},
5273 inBuf: `-6464`,
5274 inVal: new(int),
5275 want: new(int),
5276 wantErr: EU(nil).withType('0', T[int]()),
5277 }, {
5278 name: jsontest.Name("Ints/Stringified/LeadingZero"),
5279 opts: []Options{StringifyNumbers(true)},
5280 inBuf: `"00"`,
5281 inVal: new(int(-1)),
5282 want: new(int(-1)),
5283 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[int]()),
5284 }, {
5285 name: jsontest.Name("Ints/Escaped"),
5286 opts: []Options{StringifyNumbers(true)},
5287 inBuf: `"\u002d\u0036\u0034\u0036\u0034"`,
5288 inVal: new(int),
5289 want: new(int(-6464)),
5290 }, {
5291 name: jsontest.Name("Ints/Valid/NegativeZero"),
5292 inBuf: `-0`,
5293 inVal: new(int(1)),
5294 want: new(int(0)),
5295 }, {
5296 name: jsontest.Name("Ints/Invalid/Fraction"),
5297 inBuf: `1.0`,
5298 inVal: new(int(-1)),
5299 want: new(int(-1)),
5300 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[int]()),
5301 }, {
5302 name: jsontest.Name("Ints/Invalid/Exponent"),
5303 inBuf: `1e0`,
5304 inVal: new(int(-1)),
5305 want: new(int(-1)),
5306 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[int]()),
5307 }, {
5308 name: jsontest.Name("Ints/Invalid/StringifiedFraction"),
5309 opts: []Options{StringifyNumbers(true)},
5310 inBuf: `"1.0"`,
5311 inVal: new(int(-1)),
5312 want: new(int(-1)),
5313 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[int]()),
5314 }, {
5315 name: jsontest.Name("Ints/Invalid/StringifiedExponent"),
5316 opts: []Options{StringifyNumbers(true)},
5317 inBuf: `"1e0"`,
5318 inVal: new(int(-1)),
5319 want: new(int(-1)),
5320 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[int]()),
5321 }, {
5322 name: jsontest.Name("Ints/Invalid/Overflow"),
5323 inBuf: `100000000000000000000000000000`,
5324 inVal: new(int(-1)),
5325 want: new(int(-1)),
5326 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[int]()),
5327 }, {
5328 name: jsontest.Name("Ints/Invalid/OverflowSyntax"),
5329 opts: []Options{StringifyNumbers(true)},
5330 inBuf: `"100000000000000000000000000000x"`,
5331 inVal: new(int(-1)),
5332 want: new(int(-1)),
5333 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[int]()),
5334 }, {
5335 name: jsontest.Name("Ints/Invalid/Whitespace"),
5336 opts: []Options{StringifyNumbers(true)},
5337 inBuf: `"0 "`,
5338 inVal: new(int(-1)),
5339 want: new(int(-1)),
5340 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[int]()),
5341 }, {
5342 name: jsontest.Name("Ints/Invalid/Bool"),
5343 inBuf: `true`,
5344 inVal: new(int(-1)),
5345 want: new(int(-1)),
5346 wantErr: EU(nil).withType('t', T[int]()),
5347 }, {
5348 name: jsontest.Name("Ints/Invalid/String"),
5349 inBuf: `"0"`,
5350 inVal: new(int(-1)),
5351 want: new(int(-1)),
5352 wantErr: EU(nil).withType('"', T[int]()),
5353 }, {
5354 name: jsontest.Name("Ints/Invalid/Object"),
5355 inBuf: `{}`,
5356 inVal: new(int(-1)),
5357 want: new(int(-1)),
5358 wantErr: EU(nil).withType('{', T[int]()),
5359 }, {
5360 name: jsontest.Name("Ints/Invalid/Array"),
5361 inBuf: `[]`,
5362 inVal: new(int(-1)),
5363 want: new(int(-1)),
5364 wantErr: EU(nil).withType('[', T[int]()),
5365 }, {
5366 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
5367 opts: []Options{invalidFormatOption},
5368 inBuf: `1`,
5369 inVal: new(int(0)),
5370 want: new(int(1)),
5371 }, {
5372 name: jsontest.Name("Uints/Null"),
5373 inBuf: `null`,
5374 inVal: new(uint(1)),
5375 want: new(uint(0)),
5376 }, {
5377 name: jsontest.Name("Uints/Uint"),
5378 inBuf: `1`,
5379 inVal: new(uint(0)),
5380 want: new(uint(1)),
5381 }, {
5382 name: jsontest.Name("Uints/Uint8/Min"),
5383 inBuf: `0`,
5384 inVal: new(uint8(1)),
5385 want: new(uint8(0)),
5386 }, {
5387 name: jsontest.Name("Uints/Uint8/Max"),
5388 inBuf: `255`,
5389 inVal: new(uint8(0)),
5390 want: new(uint8(255)),
5391 }, {
5392 name: jsontest.Name("Uints/Uint8/MaxOverflow"),
5393 inBuf: `256`,
5394 inVal: new(uint8(1)),
5395 want: new(uint8(1)),
5396 wantErr: EU(strconv.ErrRange).withVal(`256`).withType('0', T[uint8]()),
5397 }, {
5398 name: jsontest.Name("Uints/Uint16/Min"),
5399 inBuf: `0`,
5400 inVal: new(uint16(1)),
5401 want: new(uint16(0)),
5402 }, {
5403 name: jsontest.Name("Uints/Uint16/Max"),
5404 inBuf: `65535`,
5405 inVal: new(uint16(0)),
5406 want: new(uint16(65535)),
5407 }, {
5408 name: jsontest.Name("Uints/Uint16/MaxOverflow"),
5409 inBuf: `65536`,
5410 inVal: new(uint16(1)),
5411 want: new(uint16(1)),
5412 wantErr: EU(strconv.ErrRange).withVal(`65536`).withType('0', T[uint16]()),
5413 }, {
5414 name: jsontest.Name("Uints/Uint32/Min"),
5415 inBuf: `0`,
5416 inVal: new(uint32(1)),
5417 want: new(uint32(0)),
5418 }, {
5419 name: jsontest.Name("Uints/Uint32/Max"),
5420 inBuf: `4294967295`,
5421 inVal: new(uint32(0)),
5422 want: new(uint32(4294967295)),
5423 }, {
5424 name: jsontest.Name("Uints/Uint32/MaxOverflow"),
5425 inBuf: `4294967296`,
5426 inVal: new(uint32(1)),
5427 want: new(uint32(1)),
5428 wantErr: EU(strconv.ErrRange).withVal(`4294967296`).withType('0', T[uint32]()),
5429 }, {
5430 name: jsontest.Name("Uints/Uint64/Min"),
5431 inBuf: `0`,
5432 inVal: new(uint64(1)),
5433 want: new(uint64(0)),
5434 }, {
5435 name: jsontest.Name("Uints/Uint64/Max"),
5436 inBuf: `18446744073709551615`,
5437 inVal: new(uint64(0)),
5438 want: new(uint64(18446744073709551615)),
5439 }, {
5440 name: jsontest.Name("Uints/Uint64/MaxOverflow"),
5441 inBuf: `18446744073709551616`,
5442 inVal: new(uint64(1)),
5443 want: new(uint64(1)),
5444 wantErr: EU(strconv.ErrRange).withVal(`18446744073709551616`).withType('0', T[uint64]()),
5445 }, {
5446 name: jsontest.Name("Uints/Uintptr"),
5447 inBuf: `1`,
5448 inVal: new(uintptr(0)),
5449 want: new(uintptr(1)),
5450 }, {
5451 name: jsontest.Name("Uints/Named"),
5452 inBuf: `6464`,
5453 inVal: new(namedUint64(0)),
5454 want: new(namedUint64(6464)),
5455 }, {
5456 name: jsontest.Name("Uints/Stringified"),
5457 opts: []Options{StringifyNumbers(true)},
5458 inBuf: `"6464"`,
5459 inVal: new(uint),
5460 want: new(uint(6464)),
5461 }, {
5462 name: jsontest.Name("Uints/Stringified/Invalid"),
5463 opts: []Options{StringifyNumbers(true)},
5464 inBuf: `6464`,
5465 inVal: new(uint),
5466 want: new(uint),
5467 wantErr: EU(nil).withType('0', T[uint]()),
5468 }, {
5469 name: jsontest.Name("Uints/Stringified/LeadingZero"),
5470 opts: []Options{StringifyNumbers(true)},
5471 inBuf: `"00"`,
5472 inVal: new(uint(1)),
5473 want: new(uint(1)),
5474 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[uint]()),
5475 }, {
5476 name: jsontest.Name("Uints/Escaped"),
5477 opts: []Options{StringifyNumbers(true)},
5478 inBuf: `"\u0036\u0034\u0036\u0034"`,
5479 inVal: new(uint),
5480 want: new(uint(6464)),
5481 }, {
5482 name: jsontest.Name("Uints/Invalid/NegativeOne"),
5483 inBuf: `-1`,
5484 inVal: new(uint(1)),
5485 want: new(uint(1)),
5486 wantErr: EU(strconv.ErrSyntax).withVal(`-1`).withType('0', T[uint]()),
5487 }, {
5488 name: jsontest.Name("Uints/Invalid/NegativeZero"),
5489 inBuf: `-0`,
5490 inVal: new(uint(1)),
5491 want: new(uint(1)),
5492 wantErr: EU(strconv.ErrSyntax).withVal(`-0`).withType('0', T[uint]()),
5493 }, {
5494 name: jsontest.Name("Uints/Invalid/Fraction"),
5495 inBuf: `1.0`,
5496 inVal: new(uint(10)),
5497 want: new(uint(10)),
5498 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[uint]()),
5499 }, {
5500 name: jsontest.Name("Uints/Invalid/Exponent"),
5501 inBuf: `1e0`,
5502 inVal: new(uint(10)),
5503 want: new(uint(10)),
5504 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[uint]()),
5505 }, {
5506 name: jsontest.Name("Uints/Invalid/StringifiedFraction"),
5507 opts: []Options{StringifyNumbers(true)},
5508 inBuf: `"1.0"`,
5509 inVal: new(uint(10)),
5510 want: new(uint(10)),
5511 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[uint]()),
5512 }, {
5513 name: jsontest.Name("Uints/Invalid/StringifiedExponent"),
5514 opts: []Options{StringifyNumbers(true)},
5515 inBuf: `"1e0"`,
5516 inVal: new(uint(10)),
5517 want: new(uint(10)),
5518 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[uint]()),
5519 }, {
5520 name: jsontest.Name("Uints/Invalid/Overflow"),
5521 inBuf: `100000000000000000000000000000`,
5522 inVal: new(uint(1)),
5523 want: new(uint(1)),
5524 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[uint]()),
5525 }, {
5526 name: jsontest.Name("Uints/Invalid/OverflowSyntax"),
5527 opts: []Options{StringifyNumbers(true)},
5528 inBuf: `"100000000000000000000000000000x"`,
5529 inVal: new(uint(1)),
5530 want: new(uint(1)),
5531 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[uint]()),
5532 }, {
5533 name: jsontest.Name("Uints/Invalid/Whitespace"),
5534 opts: []Options{StringifyNumbers(true)},
5535 inBuf: `"0 "`,
5536 inVal: new(uint(1)),
5537 want: new(uint(1)),
5538 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[uint]()),
5539 }, {
5540 name: jsontest.Name("Uints/Invalid/Bool"),
5541 inBuf: `true`,
5542 inVal: new(uint(1)),
5543 want: new(uint(1)),
5544 wantErr: EU(nil).withType('t', T[uint]()),
5545 }, {
5546 name: jsontest.Name("Uints/Invalid/String"),
5547 inBuf: `"0"`,
5548 inVal: new(uint(1)),
5549 want: new(uint(1)),
5550 wantErr: EU(nil).withType('"', T[uint]()),
5551 }, {
5552 name: jsontest.Name("Uints/Invalid/Object"),
5553 inBuf: `{}`,
5554 inVal: new(uint(1)),
5555 want: new(uint(1)),
5556 wantErr: EU(nil).withType('{', T[uint]()),
5557 }, {
5558 name: jsontest.Name("Uints/Invalid/Array"),
5559 inBuf: `[]`,
5560 inVal: new(uint(1)),
5561 want: new(uint(1)),
5562 wantErr: EU(nil).withType('[', T[uint]()),
5563 }, {
5564 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
5565 opts: []Options{invalidFormatOption},
5566 inBuf: `1`,
5567 inVal: new(uint(0)),
5568 want: new(uint(1)),
5569 }, {
5570 name: jsontest.Name("Floats/Null"),
5571 inBuf: `null`,
5572 inVal: new(float64(64.64)),
5573 want: new(float64(0)),
5574 }, {
5575 name: jsontest.Name("Floats/Float32/Pi"),
5576 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5577 inVal: new(float32(32.32)),
5578 want: new(float32(math.Pi)),
5579 }, {
5580 name: jsontest.Name("Floats/Float32/Underflow"),
5581 inBuf: `1e-1000`,
5582 inVal: new(float32(32.32)),
5583 want: new(float32(0)),
5584 }, {
5585 name: jsontest.Name("Floats/Float32/Overflow"),
5586 inBuf: `-1e1000`,
5587 inVal: new(float32(32.32)),
5588 want: new(float32(32.32)),
5589 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float32]()),
5590 }, {
5591 name: jsontest.Name("Floats/Float64/Pi"),
5592 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5593 inVal: new(float64(64.64)),
5594 want: new(float64(math.Pi)),
5595 }, {
5596 name: jsontest.Name("Floats/Float64/Underflow"),
5597 inBuf: `1e-1000`,
5598 inVal: new(float64(64.64)),
5599 want: new(float64(0)),
5600 }, {
5601 name: jsontest.Name("Floats/Float64/Overflow"),
5602 inBuf: `-1e1000`,
5603 inVal: new(float64(64.64)),
5604 want: new(float64(64.64)),
5605 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float64]()),
5606 }, {
5607 name: jsontest.Name("Floats/Any/Overflow"),
5608 inBuf: `1e1000`,
5609 inVal: new(any),
5610 want: new(any(float64(0))),
5611 wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float64]()),
5612 }, {
5613 name: jsontest.Name("Floats/Any/ExistingFloat32/Overflow"),
5614 inBuf: `1e1000`,
5615 inVal: new(any(float32(32.32))),
5616 want: new(any(float32(32.32))),
5617 wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float32]()),
5618 }, {
5619 name: jsontest.Name("Floats/Any/ExistingFloat64/Overflow"),
5620 inBuf: `1e1000`,
5621 inVal: new(any(float64(64.64))),
5622 want: new(any(float64(64.64))),
5623 wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float64]()),
5624 }, {
5625 name: jsontest.Name("Floats/Named"),
5626 inBuf: `64.64`,
5627 inVal: new(namedFloat64(0)),
5628 want: new(namedFloat64(64.64)),
5629 }, {
5630 name: jsontest.Name("Floats/Stringified"),
5631 opts: []Options{StringifyNumbers(true)},
5632 inBuf: `"64.64"`,
5633 inVal: new(float64),
5634 want: new(float64(64.64)),
5635 }, {
5636 name: jsontest.Name("Floats/Stringified/Invalid"),
5637 opts: []Options{StringifyNumbers(true)},
5638 inBuf: `64.64`,
5639 inVal: new(float64),
5640 want: new(float64),
5641 wantErr: EU(nil).withType('0', T[float64]()),
5642 }, {
5643 name: jsontest.Name("Floats/Escaped"),
5644 opts: []Options{StringifyNumbers(true)},
5645 inBuf: `"\u0036\u0034\u002e\u0036\u0034"`,
5646 inVal: new(float64),
5647 want: new(float64(64.64)),
5648 }, {
5649 name: jsontest.Name("Floats/Invalid/NaN"),
5650 opts: []Options{StringifyNumbers(true)},
5651 inBuf: `"NaN"`,
5652 inVal: new(float64(64.64)),
5653 want: new(float64(64.64)),
5654 wantErr: EU(strconv.ErrSyntax).withVal(`"NaN"`).withType('"', float64Type),
5655 }, {
5656 name: jsontest.Name("Floats/Invalid/Infinity"),
5657 opts: []Options{StringifyNumbers(true)},
5658 inBuf: `"Infinity"`,
5659 inVal: new(float64(64.64)),
5660 want: new(float64(64.64)),
5661 wantErr: EU(strconv.ErrSyntax).withVal(`"Infinity"`).withType('"', float64Type),
5662 }, {
5663 name: jsontest.Name("Floats/Invalid/Whitespace"),
5664 opts: []Options{StringifyNumbers(true)},
5665 inBuf: `"1 "`,
5666 inVal: new(float64(64.64)),
5667 want: new(float64(64.64)),
5668 wantErr: EU(strconv.ErrSyntax).withVal(`"1 "`).withType('"', float64Type),
5669 }, {
5670 name: jsontest.Name("Floats/Invalid/GoSyntax"),
5671 opts: []Options{StringifyNumbers(true)},
5672 inBuf: `"1p-2"`,
5673 inVal: new(float64(64.64)),
5674 want: new(float64(64.64)),
5675 wantErr: EU(strconv.ErrSyntax).withVal(`"1p-2"`).withType('"', float64Type),
5676 }, {
5677 name: jsontest.Name("Floats/Invalid/Bool"),
5678 inBuf: `true`,
5679 inVal: new(float64(64.64)),
5680 want: new(float64(64.64)),
5681 wantErr: EU(nil).withType('t', float64Type),
5682 }, {
5683 name: jsontest.Name("Floats/Invalid/String"),
5684 inBuf: `"0"`,
5685 inVal: new(float64(64.64)),
5686 want: new(float64(64.64)),
5687 wantErr: EU(nil).withType('"', float64Type),
5688 }, {
5689 name: jsontest.Name("Floats/Invalid/Object"),
5690 inBuf: `{}`,
5691 inVal: new(float64(64.64)),
5692 want: new(float64(64.64)),
5693 wantErr: EU(nil).withType('{', float64Type),
5694 }, {
5695 name: jsontest.Name("Floats/Invalid/Array"),
5696 inBuf: `[]`,
5697 inVal: new(float64(64.64)),
5698 want: new(float64(64.64)),
5699 wantErr: EU(nil).withType('[', float64Type),
5700 }, {
5701 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
5702 opts: []Options{invalidFormatOption},
5703 inBuf: `1`,
5704 inVal: new(float64(0)),
5705 want: new(float64(1)),
5706 }, {
5707 name: jsontest.Name("Maps/Null"),
5708 inBuf: `null`,
5709 inVal: new(map[string]string{"key": "value"}),
5710 want: new(map[string]string),
5711 }, {
5712 name: jsontest.Name("Maps/InvalidKey/Bool"),
5713 inBuf: `{"true":"false"}`,
5714 inVal: new(map[bool]bool),
5715 want: new(make(map[bool]bool)),
5716 wantErr: EU(nil).withPos(`{`, "/true").withType('"', boolType),
5717 }, {
5718 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
5719 inBuf: `{"true":"false"}`,
5720 inVal: new(map[namedBool]bool),
5721 want: new(make(map[namedBool]bool)),
5722 wantErr: EU(nil).withPos(`{`, "/true").withType('"', T[namedBool]()),
5723 }, {
5724 name: jsontest.Name("Maps/InvalidKey/Array"),
5725 inBuf: `{"key":"value"}`,
5726 inVal: new(map[[1]string]string),
5727 want: new(make(map[[1]string]string)),
5728 wantErr: EU(nil).withPos(`{`, "/key").withType('"', T[[1]string]()),
5729 }, {
5730 name: jsontest.Name("Maps/InvalidKey/Channel"),
5731 inBuf: `{"key":"value"}`,
5732 inVal: new(map[chan string]string),
5733 want: new(make(map[chan string]string)),
5734 wantErr: EU(nil).withPos(`{`, "").withType(0, T[chan string]()),
5735 }, {
5736 name: jsontest.Name("Maps/ValidKey/Int"),
5737 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5738 inVal: new(map[int]int),
5739 want: new(map[int]int{0: 0, -1: 1, 2: 2, -3: 3}),
5740 }, {
5741 name: jsontest.Name("Maps/ValidKey/NamedInt"),
5742 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5743 inVal: new(map[namedInt64]int),
5744 want: new(map[namedInt64]int{0: 0, -1: 1, 2: 2, -3: 3}),
5745 }, {
5746 name: jsontest.Name("Maps/ValidKey/Uint"),
5747 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5748 inVal: new(map[uint]uint),
5749 want: new(map[uint]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5750 }, {
5751 name: jsontest.Name("Maps/ValidKey/NamedUint"),
5752 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5753 inVal: new(map[namedUint64]uint),
5754 want: new(map[namedUint64]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5755 }, {
5756 name: jsontest.Name("Maps/ValidKey/Float"),
5757 inBuf: `{"1.234":1.234,"12.34":12.34,"123.4":123.4}`,
5758 inVal: new(map[float64]float64),
5759 want: new(map[float64]float64{1.234: 1.234, 12.34: 12.34, 123.4: 123.4}),
5760 }, {
5761 name: jsontest.Name("Maps/DuplicateName/Int"),
5762 inBuf: `{"0":1,"-0":-1}`,
5763 inVal: new(map[int]int),
5764 want: new(map[int]int{0: 1}),
5765 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5766 }, {
5767 name: jsontest.Name("Maps/DuplicateName/Int/MergeWithLegacySemantics"),
5768 opts: []Options{jsonflags.MergeWithLegacySemantics | 1},
5769 inBuf: `{"0":1,"-0":-1}`,
5770 inVal: new(map[int]int),
5771 want: new(map[int]int{0: 1}),
5772 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5773 }, {
5774 name: jsontest.Name("Maps/DuplicateName/Int/AllowDuplicateNames"),
5775 opts: []Options{jsontext.AllowDuplicateNames(true)},
5776 inBuf: `{"0":1,"-0":-1}`,
5777 inVal: new(map[int]int),
5778 want: new(map[int]int{0: -1}),
5779 }, {
5780 name: jsontest.Name("Maps/DuplicateName/Int/OverwriteExisting"),
5781 inBuf: `{"-0":-1}`,
5782 inVal: new(map[int]int{0: 1}),
5783 want: new(map[int]int{0: -1}),
5784 }, {
5785 name: jsontest.Name("Maps/DuplicateName/Float"),
5786 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5787 inVal: new(map[float64]string),
5788 want: new(map[float64]string{1: "1.0"}),
5789 wantErr: newDuplicateNameError("", []byte(`"1"`), len64(`{"1.0":"1.0",`)),
5790 }, {
5791 name: jsontest.Name("Maps/DuplicateName/Float/AllowDuplicateNames"),
5792 opts: []Options{jsontext.AllowDuplicateNames(true)},
5793 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5794 inVal: new(map[float64]string),
5795 want: new(map[float64]string{1: "1e0"}),
5796 }, {
5797 name: jsontest.Name("Maps/DuplicateName/Float/OverwriteExisting"),
5798 inBuf: `{"1.0":"1.0"}`,
5799 inVal: new(map[float64]string{1: "1"}),
5800 want: new(map[float64]string{1: "1.0"}),
5801 }, {
5802 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
5803 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5804 inVal: new(map[nocaseString]string),
5805 want: new(map[nocaseString]string{"hello": "hello"}),
5806 wantErr: newDuplicateNameError("", []byte(`"HELLO"`), len64(`{"hello":"hello",`)),
5807 }, {
5808 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
5809 opts: []Options{jsontext.AllowDuplicateNames(true)},
5810 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5811 inVal: new(map[nocaseString]string),
5812 want: new(map[nocaseString]string{"hello": "HELLO"}),
5813 }, {
5814 name: jsontest.Name("Maps/DuplicateName/NoCaseString/OverwriteExisting"),
5815 opts: []Options{jsontext.AllowDuplicateNames(true)},
5816 inBuf: `{"HELLO":"HELLO"}`,
5817 inVal: new(map[nocaseString]string{"hello": "hello"}),
5818 want: new(map[nocaseString]string{"hello": "HELLO"}),
5819 }, {
5820 name: jsontest.Name("Maps/ValidKey/Interface"),
5821 inBuf: `{"false":"false","true":"true","string":"string","0":"0","[]":"[]","{}":"{}"}`,
5822 inVal: new(map[any]string),
5823 want: new(map[any]string{
5824 "false": "false",
5825 "true": "true",
5826 "string": "string",
5827 "0": "0",
5828 "[]": "[]",
5829 "{}": "{}",
5830 }),
5831 }, {
5832 name: jsontest.Name("Maps/InvalidValue/Channel"),
5833 inBuf: `{"key":"value"}`,
5834 inVal: new(map[string]chan string),
5835 want: new(map[string]chan string{
5836 "key": nil,
5837 }),
5838 wantErr: EU(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
5839 }, {
5840 name: jsontest.Name("Maps/RecursiveMap"),
5841 inBuf: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
5842 inVal: new(recursiveMap),
5843 want: new(recursiveMap{
5844 "fizz": {
5845 "foo": {},
5846 "bar": {},
5847 },
5848 "buzz": {},
5849 }),
5850 }, {
5851
5852
5853
5854 name: jsontest.Name("Maps/Merge"),
5855 opts: []Options{jsontext.AllowDuplicateNames(true)},
5856 inBuf: `{"k1":{"k2":"v2"},"k2":{"k1":"v1"},"k2":{"k2":"v2"}}`,
5857 inVal: new(map[string]map[string]string{
5858 "k1": {"k1": "v1"},
5859 }),
5860 want: new(map[string]map[string]string{
5861 "k1": {"k1": "v1", "k2": "v2"},
5862 "k2": {"k1": "v1", "k2": "v2"},
5863 }),
5864 }, {
5865 name: jsontest.Name("Maps/Invalid/Bool"),
5866 inBuf: `true`,
5867 inVal: new(map[string]string{"key": "value"}),
5868 want: new(map[string]string{"key": "value"}),
5869 wantErr: EU(nil).withType('t', T[map[string]string]()),
5870 }, {
5871 name: jsontest.Name("Maps/Invalid/String"),
5872 inBuf: `""`,
5873 inVal: new(map[string]string{"key": "value"}),
5874 want: new(map[string]string{"key": "value"}),
5875 wantErr: EU(nil).withType('"', T[map[string]string]()),
5876 }, {
5877 name: jsontest.Name("Maps/Invalid/Number"),
5878 inBuf: `0`,
5879 inVal: new(map[string]string{"key": "value"}),
5880 want: new(map[string]string{"key": "value"}),
5881 wantErr: EU(nil).withType('0', T[map[string]string]()),
5882 }, {
5883 name: jsontest.Name("Maps/Invalid/Array"),
5884 inBuf: `[]`,
5885 inVal: new(map[string]string{"key": "value"}),
5886 want: new(map[string]string{"key": "value"}),
5887 wantErr: EU(nil).withType('[', T[map[string]string]()),
5888 }, {
5889 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
5890 opts: []Options{invalidFormatOption},
5891 inBuf: `{"hello":"goodbye"}`,
5892 inVal: new(map[string]string{}),
5893 want: new(map[string]string{"hello": "goodbye"}),
5894 }, {
5895 name: jsontest.Name("Structs/Null"),
5896 inBuf: `null`,
5897 inVal: new(structAll{String: "something"}),
5898 want: new(structAll{}),
5899 }, {
5900 name: jsontest.Name("Structs/Empty"),
5901 inBuf: `{}`,
5902 inVal: new(structAll{
5903 String: "hello",
5904 Map: map[string]string{},
5905 Slice: []string{},
5906 }),
5907 want: new(structAll{
5908 String: "hello",
5909 Map: map[string]string{},
5910 Slice: []string{},
5911 }),
5912 }, {
5913 name: jsontest.Name("Structs/Normal"),
5914 inBuf: `{
5915 "Bool": true,
5916 "String": "hello",
5917 "Bytes": "AQID",
5918 "Int": -64,
5919 "Uint": 64,
5920 "Float": 3.14159,
5921 "Map": {"key": "value"},
5922 "StructScalars": {
5923 "Bool": true,
5924 "String": "hello",
5925 "Bytes": "AQID",
5926 "Int": -64,
5927 "Uint": 64,
5928 "Float": 3.14159
5929 },
5930 "StructMaps": {
5931 "MapBool": {"": true},
5932 "MapString": {"": "hello"},
5933 "MapBytes": {"": "AQID"},
5934 "MapInt": {"": -64},
5935 "MapUint": {"": 64},
5936 "MapFloat": {"": 3.14159}
5937 },
5938 "StructSlices": {
5939 "SliceBool": [true],
5940 "SliceString": ["hello"],
5941 "SliceBytes": ["AQID"],
5942 "SliceInt": [-64],
5943 "SliceUint": [64],
5944 "SliceFloat": [3.14159]
5945 },
5946 "Slice": ["fizz","buzz"],
5947 "Array": ["goodbye"],
5948 "Pointer": {},
5949 "Interface": null
5950 }`,
5951 inVal: new(structAll),
5952 want: new(structAll{
5953 Bool: true,
5954 String: "hello",
5955 Bytes: []byte{1, 2, 3},
5956 Int: -64,
5957 Uint: +64,
5958 Float: 3.14159,
5959 Map: map[string]string{"key": "value"},
5960 StructScalars: structScalars{
5961 Bool: true,
5962 String: "hello",
5963 Bytes: []byte{1, 2, 3},
5964 Int: -64,
5965 Uint: +64,
5966 Float: 3.14159,
5967 },
5968 StructMaps: structMaps{
5969 MapBool: map[string]bool{"": true},
5970 MapString: map[string]string{"": "hello"},
5971 MapBytes: map[string][]byte{"": {1, 2, 3}},
5972 MapInt: map[string]int64{"": -64},
5973 MapUint: map[string]uint64{"": +64},
5974 MapFloat: map[string]float64{"": 3.14159},
5975 },
5976 StructSlices: structSlices{
5977 SliceBool: []bool{true},
5978 SliceString: []string{"hello"},
5979 SliceBytes: [][]byte{{1, 2, 3}},
5980 SliceInt: []int64{-64},
5981 SliceUint: []uint64{+64},
5982 SliceFloat: []float64{3.14159},
5983 },
5984 Slice: []string{"fizz", "buzz"},
5985 Array: [1]string{"goodbye"},
5986 Pointer: new(structAll),
5987 }),
5988 }, {
5989 name: jsontest.Name("Structs/Merge"),
5990 inBuf: `{
5991 "Bool": false,
5992 "String": "goodbye",
5993 "Int": -64,
5994 "Float": 3.14159,
5995 "Map": {"k2": "v2"},
5996 "StructScalars": {
5997 "Bool": true,
5998 "String": "hello",
5999 "Bytes": "AQID",
6000 "Int": -64
6001 },
6002 "StructMaps": {
6003 "MapBool": {"": true},
6004 "MapString": {"": "hello"},
6005 "MapBytes": {"": "AQID"},
6006 "MapInt": {"": -64},
6007 "MapUint": {"": 64},
6008 "MapFloat": {"": 3.14159}
6009 },
6010 "StructSlices": {
6011 "SliceString": ["hello"],
6012 "SliceBytes": ["AQID"],
6013 "SliceInt": [-64],
6014 "SliceUint": [64]
6015 },
6016 "Slice": ["fizz","buzz"],
6017 "Array": ["goodbye"],
6018 "Pointer": {},
6019 "Interface": {"k2":"v2"}
6020 }`,
6021 inVal: new(structAll{
6022 Bool: true,
6023 String: "hello",
6024 Bytes: []byte{1, 2, 3},
6025 Uint: +64,
6026 Float: math.NaN(),
6027 Map: map[string]string{"k1": "v1"},
6028 StructScalars: structScalars{
6029 String: "hello",
6030 Bytes: make([]byte, 2, 4),
6031 Uint: +64,
6032 Float: 3.14159,
6033 },
6034 StructMaps: structMaps{
6035 MapBool: map[string]bool{"": false},
6036 MapBytes: map[string][]byte{"": {}},
6037 MapInt: map[string]int64{"": 123},
6038 MapFloat: map[string]float64{"": math.Inf(+1)},
6039 },
6040 StructSlices: structSlices{
6041 SliceBool: []bool{true},
6042 SliceBytes: [][]byte{nil, nil},
6043 SliceInt: []int64{-123},
6044 SliceUint: []uint64{+123},
6045 SliceFloat: []float64{3.14159},
6046 },
6047 Slice: []string{"buzz", "fizz", "gizz"},
6048 Array: [1]string{"hello"},
6049 Pointer: new(structAll),
6050 Interface: map[string]string{"k1": "v1"},
6051 }),
6052 want: new(structAll{
6053 Bool: false,
6054 String: "goodbye",
6055 Bytes: []byte{1, 2, 3},
6056 Int: -64,
6057 Uint: +64,
6058 Float: 3.14159,
6059 Map: map[string]string{"k1": "v1", "k2": "v2"},
6060 StructScalars: structScalars{
6061 Bool: true,
6062 String: "hello",
6063 Bytes: []byte{1, 2, 3},
6064 Int: -64,
6065 Uint: +64,
6066 Float: 3.14159,
6067 },
6068 StructMaps: structMaps{
6069 MapBool: map[string]bool{"": true},
6070 MapString: map[string]string{"": "hello"},
6071 MapBytes: map[string][]byte{"": {1, 2, 3}},
6072 MapInt: map[string]int64{"": -64},
6073 MapUint: map[string]uint64{"": +64},
6074 MapFloat: map[string]float64{"": 3.14159},
6075 },
6076 StructSlices: structSlices{
6077 SliceBool: []bool{true},
6078 SliceString: []string{"hello"},
6079 SliceBytes: [][]byte{{1, 2, 3}},
6080 SliceInt: []int64{-64},
6081 SliceUint: []uint64{+64},
6082 SliceFloat: []float64{3.14159},
6083 },
6084 Slice: []string{"fizz", "buzz"},
6085 Array: [1]string{"goodbye"},
6086 Pointer: new(structAll),
6087 Interface: map[string]string{"k1": "v1", "k2": "v2"},
6088 }),
6089 }, {
6090 name: jsontest.Name("Structs/Stringified"),
6091 inBuf: `{
6092 "Int": "-64",
6093 "Uint": "64",
6094 "Float": "3.14159",
6095 "PointerInt": "-64",
6096 "PointerUint": "64",
6097 "PointerFloat": "3.14159"
6098 }`,
6099 inVal: new(structStringified),
6100 want: new(structStringified{
6101 Int: -64,
6102 Uint: +64,
6103 Float: 3.14159,
6104 PointerInt: new(int64(-64)),
6105 PointerUint: new(uint64(+64)),
6106 PointerFloat: new(float64(3.14159)),
6107 }),
6108 }, {
6109 name: jsontest.Name("Structs/Stringified/Invalid/EmptyIntString"),
6110 inBuf: `{"Int":""}`,
6111 inVal: new(structStringified),
6112 want: new(structStringified),
6113 wantErr: EU(strconv.ErrSyntax).withVal(`""`).withPos(`{"Int":`, "/Int").withType('"', T[int64]()),
6114 }, {
6115 name: jsontest.Name("Structs/Stringified/Invalid/Bool"),
6116 inBuf: `{"Bool": "true"}`,
6117 inVal: new(structStringifiedBool),
6118 want: new(structStringifiedBool),
6119 wantErr: EU(errInvalidStringTag).withPos(`{"Bool": `, "/Bool").withType(0, T[bool]()),
6120 }, {
6121 name: jsontest.Name("Structs/Stringified/Ignored/Bool"),
6122 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6123 inBuf: `{"Bool": true}`,
6124 inVal: new(structStringifiedBool),
6125 want: new(structStringifiedBool{Bool: true}),
6126 }, {
6127 name: jsontest.Name("Structs/Stringified/Invalid/String"),
6128 inBuf: `{"String": "\"hello\""}`,
6129 inVal: new(structStringifiedString),
6130 want: new(structStringifiedString),
6131 wantErr: EU(errInvalidStringTag).withPos(`{"String": `, "/String").withType(0, T[string]()),
6132 }, {
6133 name: jsontest.Name("Structs/Stringified/Ignored/String"),
6134 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6135 inBuf: `{"String": "\"hello\""}`,
6136 inVal: new(structStringifiedString),
6137 want: new(structStringifiedString{String: `"hello"`}),
6138 }, {
6139 name: jsontest.Name("Structs/Stringified/Invalid/Bytes"),
6140 inBuf: `{"Bytes": "AQID"}`,
6141 inVal: new(structStringifiedBytes),
6142 want: new(structStringifiedBytes),
6143 wantErr: EU(errInvalidStringTag).withPos(`{"Bytes": `, "/Bytes").withType(0, T[[]byte]()),
6144 }, {
6145 name: jsontest.Name("Structs/Stringified/Ignored/Bytes"),
6146 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6147 inBuf: `{"Bytes": "AQID"}`,
6148 inVal: new(structStringifiedBytes),
6149 want: new(structStringifiedBytes{Bytes: []byte{1, 2, 3}}),
6150 }, {
6151 name: jsontest.Name("Structs/Stringified/Invalid/Map"),
6152 inBuf: `{"Map": {"Key": "Value"}}`,
6153 inVal: new(structStringifiedMap),
6154 want: new(structStringifiedMap),
6155 wantErr: EU(errInvalidStringTag).withPos(`{"Map": `, "/Map").withType(0, T[map[string]string]()),
6156 }, {
6157 name: jsontest.Name("Structs/Stringified/Ignored/Map"),
6158 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6159 inBuf: `{"Map": {"Key": "Value"}}`,
6160 inVal: new(structStringifiedMap),
6161 want: new(structStringifiedMap{Map: map[string]string{"Key": "Value"}}),
6162 }, {
6163 name: jsontest.Name("Structs/Stringified/Invalid/Slice"),
6164 inBuf: `{"Slice": ["hello"]}`,
6165 inVal: new(structStringifiedSlice),
6166 want: new(structStringifiedSlice),
6167 wantErr: EU(errInvalidStringTag).withPos(`{"Slice": `, "/Slice").withType(0, T[[]string]()),
6168 }, {
6169 name: jsontest.Name("Structs/Stringified/Ignored/Slice"),
6170 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6171 inBuf: `{"Slice": ["hello"]}`,
6172 inVal: new(structStringifiedSlice),
6173 want: new(structStringifiedSlice{Slice: []string{"hello"}}),
6174 }, {
6175 name: jsontest.Name("Structs/Stringified/Invalid/Array"),
6176 inBuf: `{"Array": ["hello"]}`,
6177 inVal: new(structStringifiedArray),
6178 want: new(structStringifiedArray),
6179 wantErr: EU(errInvalidStringTag).withPos(`{"Array": `, "/Array").withType(0, T[[1]string]()),
6180 }, {
6181 name: jsontest.Name("Structs/Stringified/Ignored/Array"),
6182 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6183 inBuf: `{"Array": ["hello"]}`,
6184 inVal: new(structStringifiedArray),
6185 want: new(structStringifiedArray{Array: [1]string{"hello"}}),
6186 }, {
6187 name: jsontest.Name("Structs/Stringified/Invalid/Struct"),
6188 inBuf: `{"Struct": {"Bool": true}}`,
6189 inVal: new(structStringifiedStruct),
6190 want: new(structStringifiedStruct),
6191 wantErr: EU(errInvalidStringTag).withPos(`{"Struct": `, "/Struct").withType(0, T[structAll]()),
6192 }, {
6193 name: jsontest.Name("Structs/Stringified/Ignored/Struct"),
6194 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6195 inBuf: `{"Struct": {"Bool": true}}`,
6196 inVal: new(structStringifiedStruct),
6197 want: new(structStringifiedStruct{Struct: structAll{Bool: true}}),
6198 }, {
6199 name: jsontest.Name("Structs/Stringified/Invalid/Pointer"),
6200 inBuf: `{"Pointer": {"Bool": true}}`,
6201 inVal: new(structStringifiedPointer),
6202 want: new(structStringifiedPointer{Pointer: new(structAll)}),
6203 wantErr: EU(errInvalidStringTag).withPos(`{"Pointer": `, "/Pointer").withType(0, T[structAll]()),
6204 }, {
6205 name: jsontest.Name("Structs/Stringified/Ignored/Pointer"),
6206 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6207 inBuf: `{"Pointer": {"Bool": true}}`,
6208 inVal: new(structStringifiedPointer),
6209 want: new(structStringifiedPointer{Pointer: new(structAll{Bool: true})}),
6210 }, {
6211 name: jsontest.Name("Structs/Stringified/PointerPointerInt"),
6212 inBuf: `{"Pointer": "5"}`,
6213 inVal: new(structStringifiedPointerPointerInt),
6214 want: new(structStringifiedPointerPointerInt{Pointer: new(new(5))}),
6215 }, {
6216 name: jsontest.Name("Structs/Stringified/Invalid/Interface"),
6217 inBuf: `{"Interface": null}`,
6218 inVal: new(structStringifiedInterface),
6219 want: new(structStringifiedInterface),
6220 wantErr: EU(errInvalidStringTag).withPos(`{"Interface": `, "/Interface").withType(0, T[any]()),
6221 }, {
6222 name: jsontest.Name("Structs/Stringified/Ignored/Interface"),
6223 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
6224 inBuf: `{"Interface": null}`,
6225 inVal: new(structStringifiedInterface),
6226 want: new(structStringifiedInterface),
6227 }, {
6228 name: jsontest.Name("Structs/LegacyStringified"),
6229 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6230 inBuf: `{
6231 "Bool": "true",
6232 "String": "\"hello\"",
6233 "Int": "-64",
6234 "Uint": "64",
6235 "Float": "3.14159",
6236 "PointerBool": "true",
6237 "PointerString": "\"hello\"",
6238 "PointerInt": "-64",
6239 "PointerUint": "64",
6240 "PointerFloat": "3.14159"
6241 }`,
6242 inVal: new(structStringifiedLegacy),
6243 want: new(structStringifiedLegacy{
6244 Bool: true,
6245 String: "hello",
6246 Int: -64,
6247 Uint: +64,
6248 Float: 3.14159,
6249 PointerBool: new(true),
6250 PointerString: new("hello"),
6251 PointerInt: new(int64(-64)),
6252 PointerUint: new(uint64(+64)),
6253 PointerFloat: new(float64(3.14159)),
6254 }),
6255 }, {
6256 name: jsontest.Name("Structs/LegacyStringified/Invalid/EmptyIntString"),
6257 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6258 inBuf: `{"Int":""}`,
6259 inVal: new(structStringifiedLegacy),
6260 want: new(structStringifiedLegacy),
6261 wantErr: EU(strconv.ErrSyntax).withVal(`""`).withPos(`{"Int":`, "/Int").withType('"', T[int64]()),
6262 }, {
6263 name: jsontest.Name("Structs/LegacyStringified/Invalid/Bool"),
6264 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6265 inBuf: `{"Bool": true}`,
6266 inVal: new(structStringifiedLegacy),
6267 wantErr: EU(nil).withPos(`{"Bool": `, "/Bool").withType('t', T[bool]()),
6268 }, {
6269 name: jsontest.Name("Structs/LegacyStringified/Invalid/String"),
6270 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6271 inBuf: `{"String": "string"}`,
6272 inVal: new(structStringifiedLegacy),
6273 wantErr: EU(newInvalidCharacterError("s", "at start of string (expecting '\"')", 0, "")).
6274 withPos(`{"String": `, "/String").withType('"', T[string]()),
6275 }, {
6276 name: jsontest.Name("Structs/LegacyStringified/Invalid/Bytes"),
6277 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6278 inBuf: `{"Bytes": "AQID"}`,
6279 inVal: new(structStringifiedBytes),
6280 want: new(structStringifiedBytes),
6281 wantErr: EU(errInvalidStringTag).withPos(`{"Bytes": `, "/Bytes").withType(0, T[[]byte]()),
6282 }, {
6283 name: jsontest.Name("Structs/LegacyStringified/Ignored/Bytes"),
6284 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
6285 inBuf: `{"Bytes": "AQID"}`,
6286 inVal: new(structStringifiedBytes),
6287 want: new(structStringifiedBytes{Bytes: []byte{1, 2, 3}}),
6288 }, {
6289 name: jsontest.Name("Structs/LegacyStringified/Invalid/Map"),
6290 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6291 inBuf: `{"Map": {"Key": "Value"}}`,
6292 inVal: new(structStringifiedMap),
6293 want: new(structStringifiedMap),
6294 wantErr: EU(errInvalidStringTag).withPos(`{"Map": `, "/Map").withType(0, T[map[string]string]()),
6295 }, {
6296 name: jsontest.Name("Structs/LegacyStringified/Ignored/Map"),
6297 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
6298 inBuf: `{"Map": {"Key": "Value"}}`,
6299 inVal: new(structStringifiedMap),
6300 want: new(structStringifiedMap{Map: map[string]string{"Key": "Value"}}),
6301 }, {
6302 name: jsontest.Name("Structs/LegacyStringified/Invalid/Slice"),
6303 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6304 inBuf: `{"Slice": ["hello"]}`,
6305 inVal: new(structStringifiedSlice),
6306 want: new(structStringifiedSlice),
6307 wantErr: EU(errInvalidStringTag).withPos(`{"Slice": `, "/Slice").withType(0, T[[]string]()),
6308 }, {
6309 name: jsontest.Name("Structs/LegacyStringified/Ignored/Slice"),
6310 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
6311 inBuf: `{"Slice": ["hello"]}`,
6312 inVal: new(structStringifiedSlice),
6313 want: new(structStringifiedSlice{Slice: []string{"hello"}}),
6314 }, {
6315 name: jsontest.Name("Structs/LegacyStringified/Invalid/Array"),
6316 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6317 inBuf: `{"Array": ["hello"]}`,
6318 inVal: new(structStringifiedArray),
6319 want: new(structStringifiedArray),
6320 wantErr: EU(errInvalidStringTag).withPos(`{"Array": `, "/Array").withType(0, T[[1]string]()),
6321 }, {
6322 name: jsontest.Name("Structs/LegacyStringified/Ignored/Array"),
6323 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
6324 inBuf: `{"Array": ["hello"]}`,
6325 inVal: new(structStringifiedArray),
6326 want: new(structStringifiedArray{Array: [1]string{"hello"}}),
6327 }, {
6328 name: jsontest.Name("Structs/LegacyStringified/Invalid/Struct"),
6329 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6330 inBuf: `{"Struct": {"Bool": true}}`,
6331 inVal: new(structStringifiedStruct),
6332 want: new(structStringifiedStruct),
6333 wantErr: EU(errInvalidStringTag).withPos(`{"Struct": `, "/Struct").withType(0, T[structAll]()),
6334 }, {
6335 name: jsontest.Name("Structs/LegacyStringified/Ignored/Struct"),
6336 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
6337 inBuf: `{"Struct": {"Bool": true}}`,
6338 inVal: new(structStringifiedStruct),
6339 want: new(structStringifiedStruct{Struct: structAll{Bool: true}}),
6340 }, {
6341 name: jsontest.Name("Structs/LegacyStringified/Invalid/Pointer"),
6342 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6343 inBuf: `{"Pointer": {"Bool": true}}`,
6344 inVal: new(structStringifiedPointer),
6345 want: new(structStringifiedPointer{Pointer: new(structAll)}),
6346 wantErr: EU(errInvalidStringTag).withPos(`{"Pointer": `, "/Pointer").withType(0, T[structAll]()),
6347 }, {
6348 name: jsontest.Name("Structs/LegacyStringified/Ignored/Pointer"),
6349 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
6350 inBuf: `{"Pointer": {"Bool": true}}`,
6351 inVal: new(structStringifiedPointer),
6352 want: new(structStringifiedPointer{Pointer: new(structAll{Bool: true})}),
6353 }, {
6354 name: jsontest.Name("Structs/Stringified/Invalid/PointerPointerInt"),
6355 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6356 inBuf: `{"Pointer": 5}`,
6357 inVal: new(structStringifiedPointerPointerInt),
6358 want: new(structStringifiedPointerPointerInt{}),
6359 wantErr: EU(errInvalidStringTag).withPos(`{"Pointer": `, "/Pointer").withType(0, T[**int]()),
6360 }, {
6361 name: jsontest.Name("Structs/Stringified/Ignored/PointerPointerInt"),
6362 opts: []Options{jsonflags.StringifyWithLegacySemantics | jsonflags.ReportErrorsWithLegacySemantics | 1},
6363 inBuf: `{"Pointer": 5}`,
6364 inVal: new(structStringifiedPointerPointerInt),
6365 want: new(structStringifiedPointerPointerInt{Pointer: new(new(5))}),
6366 }, {
6367 name: jsontest.Name("Structs/LegacyStringified/Invalid/Interface"),
6368 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6369 inBuf: `{"Interface": null}`,
6370 inVal: new(structStringifiedInterface),
6371 want: new(structStringifiedInterface),
6372 wantErr: EU(errInvalidStringTag).withPos(`{"Interface": `, "/Interface").withType(0, T[any]()),
6373 }, {
6374 name: jsontest.Name("Structs/LegacyStringified/Ignored/Interface"),
6375 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1, jsonflags.ReportErrorsWithLegacySemantics | 1},
6376 inBuf: `{"Interface": null}`,
6377 inVal: new(structStringifiedInterface),
6378 want: new(structStringifiedInterface),
6379 }, {
6380 name: jsontest.Name("Structs/Format/Bytes/Unsupported"),
6381 inBuf: `{}`,
6382 inVal: new(structFormatBytes),
6383 wantErr: EU(errors.New("Go struct field Base16 has unsupported `format` tag option")).withType('{', T[structFormatBytes]()),
6384 }, {
6385 name: jsontest.Name("Structs/Format/Bytes"),
6386 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6387 inBuf: `{
6388 "Base16": "0123456789abcdef",
6389 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
6390 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
6391 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
6392 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
6393 "Array": [1, 2, 3, 4]
6394 }`,
6395 inVal: new(structFormatBytes),
6396 want: new(structFormatBytes{
6397 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
6398 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6399 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6400 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߿"),
6401 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߿"),
6402 Array: []byte{1, 2, 3, 4},
6403 }),
6404 }, {
6405 name: jsontest.Name("Structs/Format/ArrayBytes"),
6406 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6407 inBuf: `{
6408 "Base16": "01020304",
6409 "Base32": "AEBAGBA=",
6410 "Base32Hex": "0410610=",
6411 "Base64": "AQIDBA==",
6412 "Base64URL": "AQIDBA==",
6413 "Array": [1, 2, 3, 4],
6414 "Default": "AQIDBA=="
6415 }`,
6416 inVal: new(structFormatArrayBytes),
6417 want: new(structFormatArrayBytes{
6418 Base16: [4]byte{1, 2, 3, 4},
6419 Base32: [4]byte{1, 2, 3, 4},
6420 Base32Hex: [4]byte{1, 2, 3, 4},
6421 Base64: [4]byte{1, 2, 3, 4},
6422 Base64URL: [4]byte{1, 2, 3, 4},
6423 Array: [4]byte{1, 2, 3, 4},
6424 Default: [4]byte{1, 2, 3, 4},
6425 }),
6426 }, {
6427 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
6428 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsonflags.FormatBytesWithLegacySemantics | 1},
6429 inBuf: `{
6430 "Base16": "01020304",
6431 "Base32": "AEBAGBA=",
6432 "Base32Hex": "0410610=",
6433 "Base64": "AQIDBA==",
6434 "Base64URL": "AQIDBA==",
6435 "Array": [1, 2, 3, 4],
6436 "Default": [1, 2, 3, 4]
6437 }`,
6438 inVal: new(structFormatArrayBytes),
6439 want: new(structFormatArrayBytes{
6440 Base16: [4]byte{1, 2, 3, 4},
6441 Base32: [4]byte{1, 2, 3, 4},
6442 Base32Hex: [4]byte{1, 2, 3, 4},
6443 Base64: [4]byte{1, 2, 3, 4},
6444 Base64URL: [4]byte{1, 2, 3, 4},
6445 Array: [4]byte{1, 2, 3, 4},
6446 Default: [4]byte{1, 2, 3, 4},
6447 }),
6448 }, {
6449 name: jsontest.Name("Structs/Format/Bytes/Array"),
6450 opts: []Options{
6451 jsonopts.ExperimentalSupportFormatTag(true),
6452 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *byte) error {
6453 if string(b) == "true" {
6454 *v = 1
6455 } else {
6456 *v = 0
6457 }
6458 return nil
6459 })),
6460 },
6461 inBuf: `{"Array":[false,true,false,true,false,true]}`,
6462 inVal: new(struct {
6463 Array []byte `json:",format:array"`
6464 }),
6465 want: new(struct {
6466 Array []byte `json:",format:array"`
6467 }{
6468 Array: []byte{0, 1, 0, 1, 0, 1},
6469 }),
6470 }, {
6471 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/WrongKind"),
6472 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6473 inBuf: `{"Base16": [1,2,3,4]}`,
6474 inVal: new(structFormatBytes),
6475 wantErr: EU(nil).withPos(`{"Base16": `, "/Base16").withType('[', T[[]byte]()),
6476 }, {
6477 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/AllPadding"),
6478 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6479 inBuf: `{"Base16": "===="}`,
6480 inVal: new(structFormatBytes),
6481 wantErr: EU(func() error {
6482 _, err := hex.Decode(make([]byte, 2), []byte("====="))
6483 return err
6484 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6485 }, {
6486 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/EvenPadding"),
6487 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6488 inBuf: `{"Base16": "0123456789abcdef="}`,
6489 inVal: new(structFormatBytes),
6490 wantErr: EU(func() error {
6491 _, err := hex.Decode(make([]byte, 8), []byte("0123456789abcdef="))
6492 return err
6493 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6494 }, {
6495 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/OddPadding"),
6496 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6497 inBuf: `{"Base16": "0123456789abcdef0="}`,
6498 inVal: new(structFormatBytes),
6499 wantErr: EU(func() error {
6500 _, err := hex.Decode(make([]byte, 9), []byte("0123456789abcdef0="))
6501 return err
6502 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6503 }, {
6504 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/LineFeed"),
6505 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6506 inBuf: `{"Base16": "aa\naa"}`,
6507 inVal: new(structFormatBytes),
6508 wantErr: EU(func() error {
6509 _, err := hex.Decode(make([]byte, 9), []byte("aa\naa"))
6510 return err
6511 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6512 }, {
6513 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/CarriageReturn"),
6514 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6515 inBuf: `{"Base16": "aa\raa"}`,
6516 inVal: new(structFormatBytes),
6517 wantErr: EU(func() error {
6518 _, err := hex.Decode(make([]byte, 9), []byte("aa\raa"))
6519 return err
6520 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6521 }, {
6522 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/Space"),
6523 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6524 inBuf: `{"Base16": "aa aa"}`,
6525 inVal: new(structFormatBytes),
6526 wantErr: EU(func() error {
6527 _, err := hex.Decode(make([]byte, 9), []byte("aa aa"))
6528 return err
6529 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6530 }, {
6531 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Padding"),
6532 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6533 inBuf: `[
6534 {"Base32": "NA======"},
6535 {"Base32": "NBSQ===="},
6536 {"Base32": "NBSWY==="},
6537 {"Base32": "NBSWY3A="},
6538 {"Base32": "NBSWY3DP"}
6539 ]`,
6540 inVal: new([]structFormatBytes),
6541 want: new([]structFormatBytes{
6542 {Base32: []byte("h")},
6543 {Base32: []byte("he")},
6544 {Base32: []byte("hel")},
6545 {Base32: []byte("hell")},
6546 {Base32: []byte("hello")},
6547 }),
6548 }, {
6549 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Invalid/NoPadding"),
6550 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6551 inBuf: `[
6552 {"Base32": "NA"},
6553 {"Base32": "NBSQ"},
6554 {"Base32": "NBSWY"},
6555 {"Base32": "NBSWY3A"},
6556 {"Base32": "NBSWY3DP"}
6557 ]`,
6558 inVal: new([]structFormatBytes),
6559 wantErr: EU(func() error {
6560 _, err := base32.StdEncoding.Decode(make([]byte, 1), []byte("NA"))
6561 return err
6562 }()).withPos(`[`+"\n\t\t\t\t"+`{"Base32": `, "/0/Base32").withType('"', T[[]byte]()),
6563 }, {
6564 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/WrongAlphabet"),
6565 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6566 inBuf: `{"Base32": "0123456789ABCDEFGHIJKLMNOPQRSTUV"}`,
6567 inVal: new(structFormatBytes),
6568 wantErr: EU(func() error {
6569 _, err := base32.StdEncoding.Decode(make([]byte, 20), []byte("0123456789ABCDEFGHIJKLMNOPQRSTUV"))
6570 return err
6571 }()).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6572 }, {
6573 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32Hex/WrongAlphabet"),
6574 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6575 inBuf: `{"Base32Hex": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"}`,
6576 inVal: new(structFormatBytes),
6577 wantErr: EU(func() error {
6578 _, err := base32.HexEncoding.Decode(make([]byte, 20), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"))
6579 return err
6580 }()).withPos(`{"Base32Hex": `, "/Base32Hex").withType('"', T[[]byte]()),
6581 }, {
6582 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/LineFeed"),
6583 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6584 inBuf: `{"Base32": "AAAA\nAAAA"}`,
6585 inVal: new(structFormatBytes),
6586 wantErr: EU(errors.New("illegal character '\\n' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6587 }, {
6588 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/CarriageReturn"),
6589 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6590 inBuf: `{"Base32": "AAAA\rAAAA"}`,
6591 inVal: new(structFormatBytes),
6592 wantErr: EU(errors.New("illegal character '\\r' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6593 }, {
6594 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/Space"),
6595 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6596 inBuf: `{"Base32": "AAAA AAAA"}`,
6597 inVal: new(structFormatBytes),
6598 wantErr: EU(base32.CorruptInputError(4)).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6599 }, {
6600 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/WrongAlphabet"),
6601 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6602 inBuf: `{"Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"}`,
6603 inVal: new(structFormatBytes),
6604 wantErr: EU(func() error {
6605 _, err := base64.StdEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"))
6606 return err
6607 }()).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6608 }, {
6609 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64URL/WrongAlphabet"),
6610 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6611 inBuf: `{"Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}`,
6612 inVal: new(structFormatBytes),
6613 wantErr: EU(func() error {
6614 _, err := base64.URLEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
6615 return err
6616 }()).withPos(`{"Base64URL": `, "/Base64URL").withType('"', T[[]byte]()),
6617 }, {
6618 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/LineFeed"),
6619 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6620 inBuf: `{"Base64": "aa=\n="}`,
6621 inVal: new(structFormatBytes),
6622 wantErr: EU(errors.New("illegal character '\\n' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6623 }, {
6624 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/CarriageReturn"),
6625 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6626 inBuf: `{"Base64": "aa=\r="}`,
6627 inVal: new(structFormatBytes),
6628 wantErr: EU(errors.New("illegal character '\\r' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6629 }, {
6630 name: jsontest.Name("Structs/Format/Bytes/Base64/NonAlphabet/Ignored"),
6631 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true), jsonflags.ParseBytesWithLooseRFC4648 | 1},
6632 inBuf: `{"Base64": "aa=\r\n="}`,
6633 inVal: new(structFormatBytes),
6634 want: &structFormatBytes{Base64: []byte{105}},
6635 }, {
6636 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/Space"),
6637 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6638 inBuf: `{"Base64": "aa= ="}`,
6639 inVal: new(structFormatBytes),
6640 wantErr: EU(base64.CorruptInputError(2)).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6641 }, {
6642 name: jsontest.Name("Structs/Format/Floats"),
6643 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6644 inBuf: `[
6645 {"NonFinite": 3.141592653589793, "PointerNonFinite": 3.141592653589793},
6646 {"NonFinite": "-Infinity", "PointerNonFinite": "-Infinity"},
6647 {"NonFinite": "Infinity", "PointerNonFinite": "Infinity"}
6648 ]`,
6649 inVal: new([]structFormatFloats),
6650 want: new([]structFormatFloats{
6651 {NonFinite: math.Pi, PointerNonFinite: new(math.Pi)},
6652 {NonFinite: math.Inf(-1), PointerNonFinite: new(math.Inf(-1))},
6653 {NonFinite: math.Inf(+1), PointerNonFinite: new(math.Inf(+1))},
6654 }),
6655 }, {
6656 name: jsontest.Name("Structs/Format/Floats/NaN"),
6657 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6658 inBuf: `{"NonFinite": "NaN"}`,
6659 inVal: new(structFormatFloats),
6660
6661 }, {
6662 name: jsontest.Name("Structs/Format/Floats/Invalid/NaN"),
6663 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6664 inBuf: `{"NonFinite": "nan"}`,
6665 inVal: new(structFormatFloats),
6666 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6667 }, {
6668 name: jsontest.Name("Structs/Format/Floats/Invalid/PositiveInfinity"),
6669 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6670 inBuf: `{"NonFinite": "+Infinity"}`,
6671 inVal: new(structFormatFloats),
6672 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6673 }, {
6674 name: jsontest.Name("Structs/Format/Floats/Invalid/NegativeInfinitySpace"),
6675 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6676 inBuf: `{"NonFinite": "-Infinity "}`,
6677 inVal: new(structFormatFloats),
6678 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6679 }, {
6680 name: jsontest.Name("Structs/Format/Maps"),
6681 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6682 inBuf: `[
6683 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6684 {"EmitNull": {}, "PointerEmitNull": {}, "EmitEmpty": {}, "PointerEmitEmpty": {}, "EmitDefault": {}, "PointerEmitDefault": {}},
6685 {"EmitNull": {"k": "v"}, "PointerEmitNull": {"k": "v"}, "EmitEmpty": {"k": "v"}, "PointerEmitEmpty": {"k": "v"}, "EmitDefault": {"k": "v"}, "PointerEmitDefault": {"k": "v"}}
6686 ]`,
6687 inVal: new([]structFormatMaps),
6688 want: new([]structFormatMaps{{
6689 EmitNull: map[string]string(nil), PointerEmitNull: (*map[string]string)(nil),
6690 EmitEmpty: map[string]string(nil), PointerEmitEmpty: (*map[string]string)(nil),
6691 EmitDefault: map[string]string(nil), PointerEmitDefault: (*map[string]string)(nil),
6692 }, {
6693 EmitNull: map[string]string{}, PointerEmitNull: new(map[string]string{}),
6694 EmitEmpty: map[string]string{}, PointerEmitEmpty: new(map[string]string{}),
6695 EmitDefault: map[string]string{}, PointerEmitDefault: new(map[string]string{}),
6696 }, {
6697 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: new(map[string]string{"k": "v"}),
6698 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: new(map[string]string{"k": "v"}),
6699 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: new(map[string]string{"k": "v"}),
6700 }}),
6701 }, {
6702 name: jsontest.Name("Structs/Format/Slices"),
6703 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6704 inBuf: `[
6705 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6706 {"EmitNull": [], "PointerEmitNull": [], "EmitEmpty": [], "PointerEmitEmpty": [], "EmitDefault": [], "PointerEmitDefault": []},
6707 {"EmitNull": ["v"], "PointerEmitNull": ["v"], "EmitEmpty": ["v"], "PointerEmitEmpty": ["v"], "EmitDefault": ["v"], "PointerEmitDefault": ["v"]}
6708 ]`,
6709 inVal: new([]structFormatSlices),
6710 want: new([]structFormatSlices{{
6711 EmitNull: []string(nil), PointerEmitNull: (*[]string)(nil),
6712 EmitEmpty: []string(nil), PointerEmitEmpty: (*[]string)(nil),
6713 EmitDefault: []string(nil), PointerEmitDefault: (*[]string)(nil),
6714 }, {
6715 EmitNull: []string{}, PointerEmitNull: new([]string{}),
6716 EmitEmpty: []string{}, PointerEmitEmpty: new([]string{}),
6717 EmitDefault: []string{}, PointerEmitDefault: new([]string{}),
6718 }, {
6719 EmitNull: []string{"v"}, PointerEmitNull: new([]string{"v"}),
6720 EmitEmpty: []string{"v"}, PointerEmitEmpty: new([]string{"v"}),
6721 EmitDefault: []string{"v"}, PointerEmitDefault: new([]string{"v"}),
6722 }}),
6723 }, {
6724 name: jsontest.Name("Structs/Format/Invalid/Bool"),
6725 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6726 inBuf: `{"Bool":true}`,
6727 inVal: new(structFormatInvalid),
6728 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, T[bool]()),
6729 }, {
6730 name: jsontest.Name("Structs/Format/Invalid/String"),
6731 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6732 inBuf: `{"String": "string"}`,
6733 inVal: new(structFormatInvalid),
6734 wantErr: EU(errInvalidFormatFlag).withPos(`{"String": `, "/String").withType(0, T[string]()),
6735 }, {
6736 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
6737 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6738 inBuf: `{"Bytes": "bytes"}`,
6739 inVal: new(structFormatInvalid),
6740 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bytes": `, "/Bytes").withType(0, T[[]byte]()),
6741 }, {
6742 name: jsontest.Name("Structs/Format/Invalid/Int"),
6743 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6744 inBuf: `{"Int": 1}`,
6745 inVal: new(structFormatInvalid),
6746 wantErr: EU(errInvalidFormatFlag).withPos(`{"Int": `, "/Int").withType(0, T[int64]()),
6747 }, {
6748 name: jsontest.Name("Structs/Format/Invalid/Uint"),
6749 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6750 inBuf: `{"Uint": 1}`,
6751 inVal: new(structFormatInvalid),
6752 wantErr: EU(errInvalidFormatFlag).withPos(`{"Uint": `, "/Uint").withType(0, T[uint64]()),
6753 }, {
6754 name: jsontest.Name("Structs/Format/Invalid/Float"),
6755 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6756 inBuf: `{"Float" : 1}`,
6757 inVal: new(structFormatInvalid),
6758 wantErr: EU(errInvalidFormatFlag).withPos(`{"Float" : `, "/Float").withType(0, T[float64]()),
6759 }, {
6760 name: jsontest.Name("Structs/Format/Invalid/Map"),
6761 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6762 inBuf: `{"Map":{}}`,
6763 inVal: new(structFormatInvalid),
6764 wantErr: EU(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
6765 }, {
6766 name: jsontest.Name("Structs/Format/Invalid/Struct"),
6767 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6768 inBuf: `{"Struct": {}}`,
6769 inVal: new(structFormatInvalid),
6770 wantErr: EU(errInvalidFormatFlag).withPos(`{"Struct": `, "/Struct").withType(0, T[structAll]()),
6771 }, {
6772 name: jsontest.Name("Structs/Format/Invalid/Slice"),
6773 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6774 inBuf: `{"Slice": {}}`,
6775 inVal: new(structFormatInvalid),
6776 wantErr: EU(errInvalidFormatFlag).withPos(`{"Slice": `, "/Slice").withType(0, T[[]string]()),
6777 }, {
6778 name: jsontest.Name("Structs/Format/Invalid/Array"),
6779 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6780 inBuf: `{"Array": []}`,
6781 inVal: new(structFormatInvalid),
6782 wantErr: EU(errInvalidFormatFlag).withPos(`{"Array": `, "/Array").withType(0, T[[1]string]()),
6783 }, {
6784 name: jsontest.Name("Structs/Format/Invalid/Interface"),
6785 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
6786 inBuf: `{"Interface": "anything"}`,
6787 inVal: new(structFormatInvalid),
6788 wantErr: EU(errInvalidFormatFlag).withPos(`{"Interface": `, "/Interface").withType(0, T[any]()),
6789 }, {
6790 name: jsontest.Name("Structs/Embed/Zero"),
6791 inBuf: `{"D":""}`,
6792 inVal: new(structEmbedded),
6793 want: new(structEmbedded),
6794 }, {
6795 name: jsontest.Name("Structs/Embed/Alloc"),
6796 inBuf: `{"E":"","F":"","G":"","A":"","B":"","D":""}`,
6797 inVal: new(structEmbedded),
6798 want: new(structEmbedded{
6799 X: structEmbeddedL1{
6800 X: &structEmbeddedL2{},
6801 StructEmbed1: StructEmbed1{},
6802 },
6803 StructEmbed2: &StructEmbed2{},
6804 }),
6805 }, {
6806 name: jsontest.Name("Structs/Embed/NonZero"),
6807 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6808 inVal: new(structEmbedded),
6809 want: new(structEmbedded{
6810 X: structEmbeddedL1{
6811 X: &structEmbeddedL2{A: "A1", B: "B1" },
6812 StructEmbed1: StructEmbed1{ D: "D2" },
6813 },
6814 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6815 }),
6816 }, {
6817 name: jsontest.Name("Structs/Embed/Merge"),
6818 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6819 inVal: new(structEmbedded{
6820 X: structEmbeddedL1{
6821 X: &structEmbeddedL2{B: "##", C: "C1"},
6822 StructEmbed1: StructEmbed1{C: "C2", E: "E2"},
6823 },
6824 StructEmbed2: &StructEmbed2{E: "##", G: "G3"},
6825 }),
6826 want: new(structEmbedded{
6827 X: structEmbeddedL1{
6828 X: &structEmbeddedL2{A: "A1", B: "B1", C: "C1"},
6829 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
6830 },
6831 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6832 }),
6833 }, {
6834 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Noop"),
6835 inBuf: `{"A":1,"B":2}`,
6836 inVal: new(structEmbedTextValue),
6837 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(nil), B: 2}),
6838 }, {
6839 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/MergeN1/Nil"),
6840 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6841 inVal: new(structEmbedTextValue),
6842 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6843 }, {
6844 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/MergeN1/Empty"),
6845 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6846 inVal: new(structEmbedTextValue{X: jsontext.Value{}}),
6847 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6848 }, {
6849 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/MergeN1/Whitespace"),
6850 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6851 inVal: new(structEmbedTextValue{X: jsontext.Value("\n\r\t ")}),
6852 want: new(structEmbedTextValue{A: 1, X: jsontext.Value("")}),
6853 wantErr: EU(errRawEmbedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6854 }, {
6855 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/MergeN1/Null"),
6856 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6857 inVal: new(structEmbedTextValue{X: jsontext.Value("null")}),
6858 want: new(structEmbedTextValue{A: 1, X: jsontext.Value("null")}),
6859 wantErr: EU(errRawEmbedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6860 }, {
6861 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/MergeN1/ObjectN0"),
6862 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6863 inVal: new(structEmbedTextValue{X: jsontext.Value(` { } `)}),
6864 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(` {"fizz":"buzz"}`), B: 2}),
6865 }, {
6866 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/MergeN2/ObjectN1"),
6867 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6868 inVal: new(structEmbedTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)}),
6869 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(` { "fizz" : "buzz","fizz":"buzz","foo":[ 1 , 2 , 3 ]}`), B: 2}),
6870 }, {
6871 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Merge/EndObject"),
6872 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6873 inVal: new(structEmbedTextValue{X: jsontext.Value(` } `)}),
6874
6875
6876 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(`,"fizz":"buzz"}`), B: 2}),
6877 }, {
6878 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/MergeInvalidValue"),
6879 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6880 inVal: new(structEmbedTextValue),
6881 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(`{"fizz":`)}),
6882 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6883 }, {
6884 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/CaseSensitive"),
6885 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6886 inVal: new(structEmbedTextValue),
6887 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","a":3}`), B: 2}),
6888 }, {
6889 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/RejectDuplicateNames"),
6890 opts: []Options{jsontext.AllowDuplicateNames(false)},
6891 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6892 inVal: new(structEmbedTextValue),
6893 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6894 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6895 }, {
6896 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/AllowDuplicateNames"),
6897 opts: []Options{jsontext.AllowDuplicateNames(true)},
6898 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6899 inVal: new(structEmbedTextValue),
6900 want: new(structEmbedTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`), B: 2}),
6901 }, {
6902 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Nested/Noop"),
6903 inBuf: `{}`,
6904 inVal: new(structEmbedPointerEmbedTextValue),
6905 want: new(structEmbedPointerEmbedTextValue),
6906 }, {
6907 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Nested/Alloc"),
6908 inBuf: `{"A":1,"fizz":"buzz"}`,
6909 inVal: new(structEmbedPointerEmbedTextValue),
6910 want: new(structEmbedPointerEmbedTextValue{
6911 X: &struct {
6912 A int
6913 X jsontext.Value `json:",embed"`
6914 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6915 }),
6916 }, {
6917 name: jsontest.Name("Structs/EmbeddedFallback/TextValue/Nested/Merge"),
6918 inBuf: `{"fizz":"buzz"}`,
6919 inVal: new(structEmbedPointerEmbedTextValue{
6920 X: &struct {
6921 A int
6922 X jsontext.Value `json:",embed"`
6923 }{A: 1},
6924 }),
6925 want: new(structEmbedPointerEmbedTextValue{
6926 X: &struct {
6927 A int
6928 X jsontext.Value `json:",embed"`
6929 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6930 }),
6931 }, {
6932 name: jsontest.Name("Structs/EmbeddedFallback/PointerTextValue/Noop"),
6933 inBuf: `{"A":1,"B":2}`,
6934 inVal: new(structEmbedPointerTextValue),
6935 want: new(structEmbedPointerTextValue{A: 1, X: nil, B: 2}),
6936 }, {
6937 name: jsontest.Name("Structs/EmbeddedFallback/PointerTextValue/Alloc"),
6938 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6939 inVal: new(structEmbedPointerTextValue),
6940 want: new(structEmbedPointerTextValue{A: 1, X: new(jsontext.Value(`{"fizz":"buzz"}`)), B: 2}),
6941 }, {
6942 name: jsontest.Name("Structs/EmbeddedFallback/PointerTextValue/Merge"),
6943 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6944 inVal: new(structEmbedPointerTextValue{X: new(jsontext.Value(`{"fizz":"buzz"}`))}),
6945 want: new(structEmbedPointerTextValue{A: 1, X: new(jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`)), B: 2}),
6946 }, {
6947 name: jsontest.Name("Structs/EmbeddedFallback/PointerTextValue/Nested/Nil"),
6948 inBuf: `{"fizz":"buzz"}`,
6949 inVal: new(structEmbedEmbedPointerTextValue),
6950 want: new(structEmbedEmbedPointerTextValue{
6951 X: struct {
6952 X *jsontext.Value `json:",embed"`
6953 }{X: new(jsontext.Value(`{"fizz":"buzz"}`))},
6954 }),
6955 }, {
6956 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/Noop"),
6957 inBuf: `{"A":1,"B":2}`,
6958 inVal: new(structEmbedMapStringAny),
6959 want: new(structEmbedMapStringAny{A: 1, X: nil, B: 2}),
6960 }, {
6961 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/MergeN1/Nil"),
6962 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6963 inVal: new(structEmbedMapStringAny),
6964 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6965 }, {
6966 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/MergeN1/Empty"),
6967 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6968 inVal: new(structEmbedMapStringAny{X: jsonObject{}}),
6969 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6970 }, {
6971 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/MergeN1/ObjectN1"),
6972 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6973 inVal: new(structEmbedMapStringAny{X: jsonObject{"fizz": jsonObject{
6974 "alpha": "bravo",
6975 "charlie": "delta",
6976 }}}),
6977 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{
6978 "alpha": "bravo",
6979 "charlie": "DELTA",
6980 "echo": "foxtrot",
6981 }}, B: 2}),
6982 }, {
6983 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/MergeN2/ObjectN1"),
6984 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6985 inVal: new(structEmbedMapStringAny{X: jsonObject{"fizz": "wuzz"}}),
6986 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6987 }, {
6988 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/MergeInvalidValue"),
6989 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6990 inVal: new(structEmbedMapStringAny),
6991 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": nil}}),
6992 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6993 }, {
6994 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/MergeInvalidValue/Existing"),
6995 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6996 inVal: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6997 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6998 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6999 }, {
7000 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/CaseSensitive"),
7001 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
7002 inVal: new(structEmbedMapStringAny),
7003 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "a": 3.0}, B: 2}),
7004 }, {
7005 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/RejectDuplicateNames"),
7006 opts: []Options{jsontext.AllowDuplicateNames(false)},
7007 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
7008 inVal: new(structEmbedMapStringAny),
7009 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
7010 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
7011 }, {
7012 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/AllowDuplicateNames"),
7013 opts: []Options{jsontext.AllowDuplicateNames(true)},
7014 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
7015 inVal: new(structEmbedMapStringAny),
7016 want: new(structEmbedMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
7017 }, {
7018 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/Nested/Noop"),
7019 inBuf: `{}`,
7020 inVal: new(structEmbedPointerEmbedMapStringAny),
7021 want: new(structEmbedPointerEmbedMapStringAny),
7022 }, {
7023 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/Nested/Alloc"),
7024 inBuf: `{"A":1,"fizz":"buzz"}`,
7025 inVal: new(structEmbedPointerEmbedMapStringAny),
7026 want: new(structEmbedPointerEmbedMapStringAny{
7027 X: &struct {
7028 A int
7029 X jsonObject `json:",embed"`
7030 }{A: 1, X: jsonObject{"fizz": "buzz"}},
7031 }),
7032 }, {
7033 name: jsontest.Name("Structs/EmbeddedFallback/MapStringAny/Nested/Merge"),
7034 inBuf: `{"fizz":"buzz"}`,
7035 inVal: new(structEmbedPointerEmbedMapStringAny{
7036 X: &struct {
7037 A int
7038 X jsonObject `json:",embed"`
7039 }{A: 1},
7040 }),
7041 want: new(structEmbedPointerEmbedMapStringAny{
7042 X: &struct {
7043 A int
7044 X jsonObject `json:",embed"`
7045 }{A: 1, X: jsonObject{"fizz": "buzz"}},
7046 }),
7047 }, {
7048 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/UnmarshalFunc"),
7049 opts: []Options{
7050 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
7051 var err error
7052 *v, err = strconv.ParseFloat(string(bytes.Trim(b, `"`)), 64)
7053 return err
7054 })),
7055 },
7056 inBuf: `{"D":"1.1","E":"2.2","F":"3.3"}`,
7057 inVal: new(structEmbedMapStringAny),
7058 want: new(structEmbedMapStringAny{X: jsonObject{"D": 1.1, "E": 2.2, "F": 3.3}}),
7059 }, {
7060 name: jsontest.Name("Structs/EmbeddedFallback/PointerMapStringAny/Noop"),
7061 inBuf: `{"A":1,"B":2}`,
7062 inVal: new(structEmbedPointerMapStringAny),
7063 want: new(structEmbedPointerMapStringAny{A: 1, X: nil, B: 2}),
7064 }, {
7065 name: jsontest.Name("Structs/EmbeddedFallback/PointerMapStringAny/Alloc"),
7066 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7067 inVal: new(structEmbedPointerMapStringAny),
7068 want: new(structEmbedPointerMapStringAny{A: 1, X: new(jsonObject{"fizz": "buzz"}), B: 2}),
7069 }, {
7070 name: jsontest.Name("Structs/EmbeddedFallback/PointerMapStringAny/Merge"),
7071 inBuf: `{"A":1,"fizz":"wuzz","B":2}`,
7072 inVal: new(structEmbedPointerMapStringAny{X: new(jsonObject{"fizz": "buzz"})}),
7073 want: new(structEmbedPointerMapStringAny{A: 1, X: new(jsonObject{"fizz": "wuzz"}), B: 2}),
7074 }, {
7075 name: jsontest.Name("Structs/EmbeddedFallback/PointerMapStringAny/Nested/Nil"),
7076 inBuf: `{"fizz":"buzz"}`,
7077 inVal: new(structEmbedEmbedPointerMapStringAny),
7078 want: new(structEmbedEmbedPointerMapStringAny{
7079 X: struct {
7080 X *jsonObject `json:",embed"`
7081 }{X: new(jsonObject{"fizz": "buzz"})},
7082 }),
7083 }, {
7084 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt"),
7085 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
7086 inVal: new(structEmbedMapStringInt),
7087 want: new(structEmbedMapStringInt{
7088 X: map[string]int{"zero": 0, "one": 1, "two": 2},
7089 }),
7090 }, {
7091 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/Null"),
7092 inBuf: `{"zero": 0, "one": null, "two": 2}`,
7093 inVal: new(structEmbedMapStringInt),
7094 want: new(structEmbedMapStringInt{
7095 X: map[string]int{"zero": 0, "one": 0, "two": 2},
7096 }),
7097 }, {
7098 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/Invalid"),
7099 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
7100 inVal: new(structEmbedMapStringInt),
7101 want: new(structEmbedMapStringInt{
7102 X: map[string]int{"zero": 0, "one": 0},
7103 }),
7104 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
7105 }, {
7106 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/StringifiedNumbers"),
7107 opts: []Options{StringifyNumbers(true)},
7108 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
7109 inVal: new(structEmbedMapStringInt),
7110 want: new(structEmbedMapStringInt{
7111 X: map[string]int{"zero": 0, "one": 1, "two": 2},
7112 }),
7113 }, {
7114 name: jsontest.Name("Structs/EmbeddedFallback/MapStringInt/UnmarshalFunc"),
7115 opts: []Options{
7116 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
7117 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
7118 if err != nil {
7119 return err
7120 }
7121 *v = int(i)
7122 return nil
7123 })),
7124 },
7125 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
7126 inVal: new(structEmbedMapStringInt),
7127 want: new(structEmbedMapStringInt{
7128 X: map[string]int{"zero": 0, "one": 1, "two": 2},
7129 }),
7130 }, {
7131 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringInt"),
7132 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
7133 inVal: new(structEmbedMapNamedStringInt),
7134 want: new(structEmbedMapNamedStringInt{
7135 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
7136 }),
7137 }, {
7138 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringInt/Null"),
7139 inBuf: `{"zero": 0, "one": null, "two": 2}`,
7140 inVal: new(structEmbedMapNamedStringInt),
7141 want: new(structEmbedMapNamedStringInt{
7142 X: map[namedString]int{"zero": 0, "one": 0, "two": 2},
7143 }),
7144 }, {
7145 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringInt/Invalid"),
7146 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
7147 inVal: new(structEmbedMapNamedStringInt),
7148 want: new(structEmbedMapNamedStringInt{
7149 X: map[namedString]int{"zero": 0, "one": 0},
7150 }),
7151 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
7152 }, {
7153 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringInt/StringifiedNumbers"),
7154 opts: []Options{StringifyNumbers(true)},
7155 inBuf: `{"zero": "0", "one": 1, "two": "2"}`,
7156 inVal: new(structEmbedMapNamedStringInt),
7157 want: new(structEmbedMapNamedStringInt{
7158 X: map[namedString]int{"zero": 0, "one": 0},
7159 }),
7160 wantErr: EU(nil).withPos(`{"zero": "0", "one": `, "/one").withType('0', T[int]()),
7161 }, {
7162 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringInt/UnmarshalFunc"),
7163 opts: []Options{
7164 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
7165 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
7166 if err != nil {
7167 return err
7168 }
7169 *v = int(i)
7170 return nil
7171 })),
7172 },
7173 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
7174 inVal: new(structEmbedMapNamedStringInt),
7175 want: new(structEmbedMapNamedStringInt{
7176 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
7177 }),
7178 }, {
7179 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/Noop"),
7180 inBuf: `{"A":1,"B":2}`,
7181 inVal: new(structEmbedMapNamedStringAny),
7182 want: new(structEmbedMapNamedStringAny{A: 1, X: nil, B: 2}),
7183 }, {
7184 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/MergeN1/Nil"),
7185 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7186 inVal: new(structEmbedMapNamedStringAny),
7187 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
7188 }, {
7189 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/MergeN1/Empty"),
7190 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7191 inVal: new(structEmbedMapNamedStringAny{X: map[namedString]any{}}),
7192 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
7193 }, {
7194 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/MergeN1/ObjectN1"),
7195 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
7196 inVal: new(structEmbedMapNamedStringAny{X: map[namedString]any{"fizz": jsonObject{
7197 "alpha": "bravo",
7198 "charlie": "delta",
7199 }}}),
7200 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": jsonObject{
7201 "alpha": "bravo",
7202 "charlie": "DELTA",
7203 "echo": "foxtrot",
7204 }}, B: 2}),
7205 }, {
7206 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/MergeN2/ObjectN1"),
7207 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
7208 inVal: new(structEmbedMapNamedStringAny{X: map[namedString]any{"fizz": "wuzz"}}),
7209 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
7210 }, {
7211 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/MergeInvalidValue"),
7212 inBuf: `{"A":1,"fizz":nil,"B":2}`,
7213 inVal: new(structEmbedMapNamedStringAny),
7214 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": nil}}),
7215 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
7216 }, {
7217 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/MergeInvalidValue/Existing"),
7218 inBuf: `{"A":1,"fizz":nil,"B":2}`,
7219 inVal: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
7220 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
7221 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
7222 }, {
7223 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/CaseSensitive"),
7224 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
7225 inVal: new(structEmbedMapNamedStringAny),
7226 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "a": 3.0}, B: 2}),
7227 }, {
7228 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/RejectDuplicateNames"),
7229 opts: []Options{jsontext.AllowDuplicateNames(false)},
7230 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
7231 inVal: new(structEmbedMapNamedStringAny),
7232 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
7233 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
7234 }, {
7235 name: jsontest.Name("Structs/EmbeddedFallback/MapNamedStringAny/AllowDuplicateNames"),
7236 opts: []Options{jsontext.AllowDuplicateNames(true)},
7237 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
7238 inVal: new(structEmbedMapNamedStringAny),
7239 want: new(structEmbedMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": map[string]any{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
7240 }, {
7241 name: jsontest.Name("Structs/EmbeddedFallback/RejectUnknownMembers"),
7242 opts: []Options{RejectUnknownMembers(true)},
7243 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7244 inVal: new(structEmbedTextValue),
7245 want: new(structEmbedTextValue{
7246 A: 1,
7247 X: jsontext.Value(`{"fizz":"buzz"}`),
7248 B: 2,
7249 }),
7250 }, {
7251 name: jsontest.Name("Structs/UnknownIgnored"),
7252 opts: []Options{RejectUnknownMembers(false)},
7253 inBuf: `{"unknown":"fizzbuzz"}`,
7254 inVal: new(structAll),
7255 want: new(structAll),
7256 }, {
7257 name: jsontest.Name("Structs/RejectUnknownMembers"),
7258 opts: []Options{RejectUnknownMembers(true)},
7259 inBuf: `{"unknown":"fizzbuzz"}`,
7260 inVal: new(structAll),
7261 want: new(structAll),
7262 wantErr: EU(ErrUnknownName).withPos(`{`, "/unknown").withType('"', T[structAll]()),
7263 }, {
7264 name: jsontest.Name("Structs/UnexportedIgnored"),
7265 inBuf: `{"ignored":"unused"}`,
7266 inVal: new(structUnexportedIgnored),
7267 want: new(structUnexportedIgnored),
7268 }, {
7269 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
7270 inBuf: `{"namedString":"unused"}`,
7271 inVal: new(structIgnoredUnexportedEmbedded),
7272 want: new(structIgnoredUnexportedEmbedded),
7273 }, {
7274 name: jsontest.Name("Structs/NoCase/Exact"),
7275 inBuf: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
7276 inVal: new(structNoCase),
7277 want: new(structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"}),
7278 }, {
7279 name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault/Ambiguous"),
7280 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
7281 inBuf: `{"aa_a":"aa_a"}`,
7282 inVal: new(structNoCase),
7283 want: new(structNoCase{AaA: "aa_a"}),
7284 }, {
7285 name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault/Ambiguous"),
7286 inBuf: `{"aa_a":"aa_a"}`,
7287 inVal: new(structNoCase),
7288 want: new(structNoCase{}),
7289 wantErr: EU(errAmbiguousName).withPos(`{`, "/aa_a").withType('"', T[structNoCase]()),
7290 }, {
7291 name: jsontest.Name("Structs/NoCase/MatchCaseSensitiveDelimiter"),
7292 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
7293 inBuf: `{"aa_a":"aa_a"}`,
7294 inVal: new(structNoCase),
7295 want: new(structNoCase{}),
7296 }, {
7297 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
7298 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
7299 inBuf: `{"aa_a":"aa_a"}`,
7300 inVal: new(structNoCase),
7301 want: new(structNoCase{AA_A: "aa_a"}),
7302 }, {
7303 name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames"),
7304 opts: []Options{jsontext.AllowDuplicateNames(true), jsonflags.ReportErrorsWithLegacySemantics | 1},
7305 inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`,
7306 inVal: new(structNoCase),
7307 want: new(structNoCase{AaA: "aAa"}),
7308 }, {
7309 name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames/Ambiguous"),
7310 opts: []Options{jsontext.AllowDuplicateNames(true)},
7311 inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`,
7312 inVal: new(structNoCase),
7313 want: new(structNoCase{AaA: "AaA"}),
7314 wantErr: EU(errAmbiguousName).withPos(`{"AaA":"AaA",`, "/aaa").withType('"', T[structNoCase]()),
7315 }, {
7316 name: jsontest.Name("Structs/NoCase/Merge/RejectDuplicateNames/Ambiguous"),
7317 opts: []Options{jsontext.AllowDuplicateNames(false)},
7318 inBuf: `{"AaA":"AaA","aaa":"aaa"}`,
7319 inVal: new(structNoCase),
7320 want: new(structNoCase{AaA: "AaA"}),
7321 wantErr: EU(errAmbiguousName).withPos(`{"AaA":"AaA",`, "/aaa").withType('"', T[structNoCase]()),
7322 }, {
7323 name: jsontest.Name("Structs/CaseSensitive"),
7324 inBuf: `{"BOOL": true, "STRING": "hello", "BYTES": "AQID", "INT": -64, "UINT": 64, "FLOAT": 3.14159}`,
7325 inVal: new(structScalars),
7326 want: new(structScalars{}),
7327 }, {
7328 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactDifferent"),
7329 inBuf: `{"AAA":"AAA","AaA":"AaA","AAa":"AAa","Aaa":"Aaa"}`,
7330 inVal: new(structNoCaseEmbedTextValue{}),
7331 want: new(structNoCaseEmbedTextValue{AAA: "AAA", AaA: "AaA", AAa: "AAa", Aaa: "Aaa"}),
7332 }, {
7333 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactConflict"),
7334 inBuf: `{"AAA":"AAA","AAA":"AAA"}`,
7335 inVal: new(structNoCaseEmbedTextValue{}),
7336 want: new(structNoCaseEmbedTextValue{AAA: "AAA"}),
7337 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"AAA",`)),
7338 }, {
7339 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteExact"),
7340 inBuf: `{"AAA":"after"}`,
7341 inVal: new(structNoCaseEmbedTextValue{AAA: "before"}),
7342 want: new(structNoCaseEmbedTextValue{AAA: "after"}),
7343 }, {
7344 name: jsontest.Name("Structs/AmbiguousName/NoCase"),
7345 inBuf: `{"aaa":"aaa"}`,
7346 inVal: new(structNoCaseEmbedTextValue{}),
7347 want: new(structNoCaseEmbedTextValue{}),
7348 wantErr: EU(errAmbiguousName).withPos(`{`, "/aaa").withType('"', T[structNoCaseEmbedTextValue]()),
7349 }, {
7350 name: jsontest.Name("Structs/DuplicateName/Embed/Unknown"),
7351 inBuf: `{"unknown":""}`,
7352 inVal: new(structNoCaseEmbedTextValue{}),
7353 want: new(structNoCaseEmbedTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7354 }, {
7355 name: jsontest.Name("Structs/DuplicateName/Embed/UnknownMerge"),
7356 inBuf: `{"unknown":""}`,
7357 inVal: new(structNoCaseEmbedTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7358 want: new(structNoCaseEmbedTextValue{X: jsontext.Value(`{"unknown":"","unknown":""}`)}),
7359 }, {
7360 name: jsontest.Name("Structs/DuplicateName/Embed/NoCaseOkay"),
7361 inBuf: `{"b":"","B":""}`,
7362 inVal: new(structNoCaseEmbedTextValue{}),
7363 want: new(structNoCaseEmbedTextValue{X: jsontext.Value(`{"b":"","B":""}`)}),
7364 }, {
7365 name: jsontest.Name("Structs/DuplicateName/Embed/ExactConflict"),
7366 inBuf: `{"b":"","b":""}`,
7367 inVal: new(structNoCaseEmbedTextValue{}),
7368 want: new(structNoCaseEmbedTextValue{X: jsontext.Value(`{"b":""}`)}),
7369 wantErr: newDuplicateNameError("", []byte(`"b"`), len64(`{"b":"",`)),
7370 }, {
7371 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7372 inBuf: ``,
7373 inVal: new(structAll{}),
7374 want: new(structAll{}),
7375 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF},
7376 }, {
7377 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7378 inBuf: " \n\r\t",
7379 inVal: new(structAll{}),
7380 want: new(structAll{}),
7381 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF, ByteOffset: len64(" \n\r\t")},
7382 }, {
7383 name: jsontest.Name("Structs/Invalid/NestedErrUnexpectedEOF"),
7384 inBuf: `{"Pointer":`,
7385 inVal: new(structAll{}),
7386 want: new(structAll{Pointer: new(structAll)}),
7387 wantErr: &jsontext.SyntacticError{ByteOffset: len64(`{"Pointer":`), JSONPointer: "/Pointer", Err: io.ErrUnexpectedEOF},
7388 }, {
7389 name: jsontest.Name("Structs/Invalid/Conflicting"),
7390 inBuf: `{}`,
7391 inVal: new(structConflicting{}),
7392 want: new(structConflicting{}),
7393 wantErr: EU(errors.New(`Go struct fields A and B conflict over JSON object name "conflict"`)).withType('{', T[structConflicting]()),
7394 }, {
7395 name: jsontest.Name("Structs/Invalid/NoneExported"),
7396 inBuf: ` {}`,
7397 inVal: new(structNoneExported{}),
7398 want: new(structNoneExported{}),
7399 wantErr: EU(errNoExportedFields).withPos(` `, "").withType('{', T[structNoneExported]()),
7400 }, {
7401 name: jsontest.Name("Structs/Invalid/MalformedTag"),
7402 inBuf: `{}`,
7403 inVal: new(structMalformedTag{}),
7404 want: new(structMalformedTag{}),
7405 wantErr: EU(errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter)")).withType('{', T[structMalformedTag]()),
7406 }, {
7407 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
7408 inBuf: `{}`,
7409 inVal: new(structUnexportedTag{}),
7410 want: new(structUnexportedTag{}),
7411 wantErr: EU(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType('{', T[structUnexportedTag]()),
7412 }, {
7413 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
7414 inBuf: `{"NamedString":"hello"}`,
7415 inVal: new(structExportedEmbedded{}),
7416 want: new(structExportedEmbedded{}),
7417 wantErr: EU(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structExportedEmbedded]()),
7418 }, {
7419 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
7420 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
7421 inBuf: `{"NamedString":"hello"}`,
7422 inVal: new(structExportedEmbedded{}),
7423 want: new(structExportedEmbedded{"hello"}),
7424 }, {
7425 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
7426 inBuf: `{"name":"hello"}`,
7427 inVal: new(structExportedEmbeddedTag{}),
7428 want: new(structExportedEmbeddedTag{"hello"}),
7429 }, {
7430 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
7431 inBuf: `{}`,
7432 inVal: new(structUnexportedEmbedded{}),
7433 want: new(structUnexportedEmbedded{}),
7434 wantErr: EU(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structUnexportedEmbedded]()),
7435 }, {
7436 name: jsontest.Name("Structs/UnexportedEmbeddedStruct"),
7437 inBuf: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7438 inVal: new(structUnexportedEmbeddedStruct{}),
7439 want: new(structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7440 }, {
7441 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7442 inBuf: `{"Bool":true,"FizzBuzz":5}`,
7443 inVal: new(structUnexportedEmbeddedStructPointer{}),
7444 wantErr: EU(errNilField).withPos(`{"Bool":`, "/Bool").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7445 }, {
7446 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7447 inBuf: `{"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7448 inVal: new(structUnexportedEmbeddedStructPointer{}),
7449 wantErr: EU(errNilField).withPos(`{"FizzBuzz":5,"Addr":`, "/Addr").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7450 }, {
7451 name: jsontest.Name("Structs/UnexportedEmbeddedPointer/MapStringInt/Nil"),
7452 inBuf: `{"A":1,"fizz":2,"buzz":3}`,
7453 inVal: new(structUnexportedEmbeddedPointerMapStringInt),
7454 want: new(structUnexportedEmbeddedPointerMapStringInt{A: 1}),
7455 wantErr: EU(errNilField).withPos(`{"A":1,"fizz":`, "/fizz").withType(0, T[structUnexportedEmbeddedPointerMapStringInt]()),
7456 }, {
7457 name: jsontest.Name("Structs/UnexportedEmbeddedPointer/MapStringInt/NonNil"),
7458 inBuf: `{"A":1,"fizz":2,"buzz":3}`,
7459 inVal: new(structUnexportedEmbeddedPointerMapStringInt{structEmbedMapStringInt: new(structEmbedMapStringInt)}),
7460 want: new(structUnexportedEmbeddedPointerMapStringInt{1, &structEmbedMapStringInt{map[string]int{"fizz": 2, "buzz": 3}}}),
7461 }, {
7462 name: jsontest.Name("Structs/UnexportedEmbeddedPointer/TextValue/Nil"),
7463 inBuf: `{"A":1,"fizz":2,"buzz":3}`,
7464 inVal: new(structUnexportedEmbeddedPointerTextValue),
7465 want: new(structUnexportedEmbeddedPointerTextValue{A: 1}),
7466 wantErr: EU(errNilField).withPos(`{"A":1,"fizz":`, "/fizz").withType(0, T[structUnexportedEmbeddedPointerTextValue]()),
7467 }, {
7468 name: jsontest.Name("Structs/UnexportedEmbeddedPointer/TextValue/NonNil"),
7469 inBuf: `{"A":1,"fizz":2,"buzz":3}`,
7470 inVal: new(structUnexportedEmbeddedPointerTextValue{structEmbedEmbedPointerTextValue: new(structEmbedEmbedPointerTextValue)}),
7471 want: new(structUnexportedEmbeddedPointerTextValue{A: 1, structEmbedEmbedPointerTextValue: &structEmbedEmbedPointerTextValue{
7472 X: struct {
7473 X *jsontext.Value `json:",embed"`
7474 }{new(jsontext.Value(`{"fizz":2,"buzz":3}`))},
7475 }}),
7476 }, {
7477 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7478 inBuf: `{"Bool":true,"FizzBuzz":10,"Addr":"192.168.0.1"}`,
7479 inVal: new(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Int: 5}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{127, 0, 0, 1})}}),
7480 want: new(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true, Int: 5}, 10, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7481 }, {
7482 name: jsontest.Name("Structs/Unknown"),
7483 inBuf: `{
7484 "object0": {},
7485 "object1": {"key1": "value"},
7486 "object2": {"key1": "value", "key2": "value"},
7487 "objects": {"":{"":{"":{}}}},
7488 "array0": [],
7489 "array1": ["value1"],
7490 "array2": ["value1", "value2"],
7491 "array": [[[]]],
7492 "scalars": [null, false, true, "string", 12.345]
7493 }`,
7494 inVal: new(struct{}{}),
7495 want: new(struct{}{}),
7496 }, {
7497 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
7498 opts: []Options{invalidFormatOption},
7499 inBuf: `{"Field":"Value"}`,
7500 inVal: new(struct{ Field string }{}),
7501 want: new(struct{ Field string }{"Value"}),
7502 }, {
7503 name: jsontest.Name("Slices/Null"),
7504 inBuf: `null`,
7505 inVal: new([]string{"something"}),
7506 want: new([]string(nil)),
7507 }, {
7508 name: jsontest.Name("Slices/Bool"),
7509 inBuf: `[true,false]`,
7510 inVal: new([]bool),
7511 want: new([]bool{true, false}),
7512 }, {
7513 name: jsontest.Name("Slices/String"),
7514 inBuf: `["hello","goodbye"]`,
7515 inVal: new([]string),
7516 want: new([]string{"hello", "goodbye"}),
7517 }, {
7518 name: jsontest.Name("Slices/Bytes"),
7519 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7520 inVal: new([][]byte),
7521 want: new([][]byte{[]byte("hello"), []byte("goodbye")}),
7522 }, {
7523 name: jsontest.Name("Slices/Int"),
7524 inBuf: `[-2,-1,0,1,2]`,
7525 inVal: new([]int),
7526 want: new([]int{-2, -1, 0, 1, 2}),
7527 }, {
7528 name: jsontest.Name("Slices/Uint"),
7529 inBuf: `[0,1,2,3,4]`,
7530 inVal: new([]uint),
7531 want: new([]uint{0, 1, 2, 3, 4}),
7532 }, {
7533 name: jsontest.Name("Slices/Float"),
7534 inBuf: `[3.14159,12.34]`,
7535 inVal: new([]float64),
7536 want: new([]float64{3.14159, 12.34}),
7537 }, {
7538
7539
7540
7541 name: jsontest.Name("Slices/Merge"),
7542 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7543 inVal: new([]map[string]string{{"k1": "v1"}, {"k2": "v2"}}[:1]),
7544 want: new([]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7545 }, {
7546 name: jsontest.Name("Slices/Invalid/Channel"),
7547 inBuf: `["hello"]`,
7548 inVal: new([]chan string),
7549 want: new([]chan string{nil}),
7550 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7551 }, {
7552 name: jsontest.Name("Slices/RecursiveSlice"),
7553 inBuf: `[[],[],[[]],[[],[]]]`,
7554 inVal: new(recursiveSlice),
7555 want: new(recursiveSlice{
7556 {},
7557 {},
7558 {{}},
7559 {{}, {}},
7560 }),
7561 }, {
7562 name: jsontest.Name("Slices/Invalid/Bool"),
7563 inBuf: `true`,
7564 inVal: new([]string{"nochange"}),
7565 want: new([]string{"nochange"}),
7566 wantErr: EU(nil).withType('t', T[[]string]()),
7567 }, {
7568 name: jsontest.Name("Slices/Invalid/String"),
7569 inBuf: `""`,
7570 inVal: new([]string{"nochange"}),
7571 want: new([]string{"nochange"}),
7572 wantErr: EU(nil).withType('"', T[[]string]()),
7573 }, {
7574 name: jsontest.Name("Slices/Invalid/Number"),
7575 inBuf: `0`,
7576 inVal: new([]string{"nochange"}),
7577 want: new([]string{"nochange"}),
7578 wantErr: EU(nil).withType('0', T[[]string]()),
7579 }, {
7580 name: jsontest.Name("Slices/Invalid/Object"),
7581 inBuf: `{}`,
7582 inVal: new([]string{"nochange"}),
7583 want: new([]string{"nochange"}),
7584 wantErr: EU(nil).withType('{', T[[]string]()),
7585 }, {
7586 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
7587 opts: []Options{invalidFormatOption},
7588 inBuf: `[false,true]`,
7589 inVal: new([]bool{true, false}),
7590 want: new([]bool{false, true}),
7591 }, {
7592 name: jsontest.Name("Arrays/Null"),
7593 inBuf: `null`,
7594 inVal: new([1]string{"something"}),
7595 want: new([1]string{}),
7596 }, {
7597 name: jsontest.Name("Arrays/Bool"),
7598 inBuf: `[true,false]`,
7599 inVal: new([2]bool),
7600 want: new([2]bool{true, false}),
7601 }, {
7602 name: jsontest.Name("Arrays/String"),
7603 inBuf: `["hello","goodbye"]`,
7604 inVal: new([2]string),
7605 want: new([2]string{"hello", "goodbye"}),
7606 }, {
7607 name: jsontest.Name("Arrays/Bytes"),
7608 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7609 inVal: new([2][]byte),
7610 want: new([2][]byte{[]byte("hello"), []byte("goodbye")}),
7611 }, {
7612 name: jsontest.Name("Arrays/Int"),
7613 inBuf: `[-2,-1,0,1,2]`,
7614 inVal: new([5]int),
7615 want: new([5]int{-2, -1, 0, 1, 2}),
7616 }, {
7617 name: jsontest.Name("Arrays/Uint"),
7618 inBuf: `[0,1,2,3,4]`,
7619 inVal: new([5]uint),
7620 want: new([5]uint{0, 1, 2, 3, 4}),
7621 }, {
7622 name: jsontest.Name("Arrays/Float"),
7623 inBuf: `[3.14159,12.34]`,
7624 inVal: new([2]float64),
7625 want: new([2]float64{3.14159, 12.34}),
7626 }, {
7627
7628
7629 name: jsontest.Name("Arrays/Merge"),
7630 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7631 inVal: new([2]map[string]string{{"k1": "v1"}, {"k2": "v2"}}),
7632 want: new([2]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7633 }, {
7634 name: jsontest.Name("Arrays/Invalid/Channel"),
7635 inBuf: `["hello"]`,
7636 inVal: new([1]chan string),
7637 want: new([1]chan string),
7638 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7639 }, {
7640 name: jsontest.Name("Arrays/Invalid/Underflow"),
7641 inBuf: `{"F":[ ]}`,
7642 inVal: new(struct{ F [1]string }),
7643 want: new(struct{ F [1]string }{}),
7644 wantErr: EU(errArrayUnderflow).withPos(`{"F":[ `, "/F").withType(']', T[[1]string]()),
7645 }, {
7646 name: jsontest.Name("Arrays/Invalid/Underflow/UnmarshalArrayFromAnyLength"),
7647 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7648 inBuf: `[-1,-2]`,
7649 inVal: new([4]int{1, 2, 3, 4}),
7650 want: new([4]int{-1, -2, 0, 0}),
7651 }, {
7652 name: jsontest.Name("Arrays/Invalid/Overflow"),
7653 inBuf: `["1","2"]`,
7654 inVal: new([1]string),
7655 want: new([1]string{"1"}),
7656 wantErr: EU(errArrayOverflow).withPos(`["1","2"`, "").withType(']', T[[1]string]()),
7657 }, {
7658 name: jsontest.Name("Arrays/Invalid/Overflow/UnmarshalArrayFromAnyLength"),
7659 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7660 inBuf: `[-1,-2,-3,-4,-5,-6]`,
7661 inVal: new([4]int{1, 2, 3, 4}),
7662 want: new([4]int{-1, -2, -3, -4}),
7663 }, {
7664 name: jsontest.Name("Arrays/Invalid/Bool"),
7665 inBuf: `true`,
7666 inVal: new([1]string{"nochange"}),
7667 want: new([1]string{"nochange"}),
7668 wantErr: EU(nil).withType('t', T[[1]string]()),
7669 }, {
7670 name: jsontest.Name("Arrays/Invalid/String"),
7671 inBuf: `""`,
7672 inVal: new([1]string{"nochange"}),
7673 want: new([1]string{"nochange"}),
7674 wantErr: EU(nil).withType('"', T[[1]string]()),
7675 }, {
7676 name: jsontest.Name("Arrays/Invalid/Number"),
7677 inBuf: `0`,
7678 inVal: new([1]string{"nochange"}),
7679 want: new([1]string{"nochange"}),
7680 wantErr: EU(nil).withType('0', T[[1]string]()),
7681 }, {
7682 name: jsontest.Name("Arrays/Invalid/Object"),
7683 inBuf: `{}`,
7684 inVal: new([1]string{"nochange"}),
7685 want: new([1]string{"nochange"}),
7686 wantErr: EU(nil).withType('{', T[[1]string]()),
7687 }, {
7688 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
7689 opts: []Options{invalidFormatOption},
7690 inBuf: `[false,true]`,
7691 inVal: new([2]bool{true, false}),
7692 want: new([2]bool{false, true}),
7693 }, {
7694 name: jsontest.Name("Pointers/NullL0"),
7695 inBuf: `null`,
7696 inVal: new(*string),
7697 want: new((*string)(nil)),
7698 }, {
7699 name: jsontest.Name("Pointers/NullL1"),
7700 inBuf: `null`,
7701 inVal: new(new(*string)),
7702 want: new((**string)(nil)),
7703 }, {
7704 name: jsontest.Name("Pointers/Bool"),
7705 inBuf: `true`,
7706 inVal: new(new(bool)),
7707 want: new(new(true)),
7708 }, {
7709 name: jsontest.Name("Pointers/String"),
7710 inBuf: `"hello"`,
7711 inVal: new(new(string)),
7712 want: new(new("hello")),
7713 }, {
7714 name: jsontest.Name("Pointers/Bytes"),
7715 inBuf: `"aGVsbG8="`,
7716 inVal: new(new([]byte)),
7717 want: new(new([]byte("hello"))),
7718 }, {
7719 name: jsontest.Name("Pointers/Int"),
7720 inBuf: `-123`,
7721 inVal: new(new(int)),
7722 want: new(new(int(-123))),
7723 }, {
7724 name: jsontest.Name("Pointers/Uint"),
7725 inBuf: `123`,
7726 inVal: new(new(int)),
7727 want: new(new(int(123))),
7728 }, {
7729 name: jsontest.Name("Pointers/Float"),
7730 inBuf: `123.456`,
7731 inVal: new(new(float64)),
7732 want: new(new(float64(123.456))),
7733 }, {
7734 name: jsontest.Name("Pointers/Allocate"),
7735 inBuf: `"hello"`,
7736 inVal: new((*string)(nil)),
7737 want: new(new("hello")),
7738 }, {
7739 name: jsontest.Name("Points/IgnoreInvalidFormat"),
7740 opts: []Options{invalidFormatOption},
7741 inBuf: `true`,
7742 inVal: new(new(bool)),
7743 want: new(new(true)),
7744 }, {
7745 name: jsontest.Name("Interfaces/Empty/Null"),
7746 inBuf: `null`,
7747 inVal: new(any),
7748 want: new(any),
7749 }, {
7750 name: jsontest.Name("Interfaces/NonEmpty/Null"),
7751 inBuf: `null`,
7752 inVal: new(io.Reader),
7753 want: new(io.Reader),
7754 }, {
7755 name: jsontest.Name("Interfaces/NonEmpty/Invalid"),
7756 inBuf: `"hello"`,
7757 inVal: new(io.Reader),
7758 want: new(io.Reader),
7759 wantErr: EU(internal.ErrNilInterface).withType(0, T[io.Reader]()),
7760 }, {
7761 name: jsontest.Name("Interfaces/Empty/False"),
7762 inBuf: `false`,
7763 inVal: new(any),
7764 want: func() any {
7765 var vi any = false
7766 return &vi
7767 }(),
7768 }, {
7769 name: jsontest.Name("Interfaces/Empty/True"),
7770 inBuf: `true`,
7771 inVal: new(any),
7772 want: func() any {
7773 var vi any = true
7774 return &vi
7775 }(),
7776 }, {
7777 name: jsontest.Name("Interfaces/Empty/String"),
7778 inBuf: `"string"`,
7779 inVal: new(any),
7780 want: func() any {
7781 var vi any = "string"
7782 return &vi
7783 }(),
7784 }, {
7785 name: jsontest.Name("Interfaces/Empty/Number"),
7786 inBuf: `3.14159`,
7787 inVal: new(any),
7788 want: func() any {
7789 var vi any = 3.14159
7790 return &vi
7791 }(),
7792 }, {
7793 name: jsontest.Name("Interfaces/Empty/Object"),
7794 inBuf: `{"k":"v"}`,
7795 inVal: new(any),
7796 want: func() any {
7797 var vi any = map[string]any{"k": "v"}
7798 return &vi
7799 }(),
7800 }, {
7801 name: jsontest.Name("Interfaces/Empty/Array"),
7802 inBuf: `["v"]`,
7803 inVal: new(any),
7804 want: func() any {
7805 var vi any = []any{"v"}
7806 return &vi
7807 }(),
7808 }, {
7809 name: jsontest.Name("Interfaces/NamedAny/String"),
7810 inBuf: `"string"`,
7811 inVal: new(namedAny),
7812 want: func() namedAny {
7813 var vi namedAny = "string"
7814 return &vi
7815 }(),
7816 }, {
7817 name: jsontest.Name("Interfaces/Invalid"),
7818 inBuf: `]`,
7819 inVal: new(any),
7820 want: new(any),
7821 wantErr: newInvalidCharacterError("]", "at start of value", 0, ""),
7822 }, {
7823
7824
7825
7826
7827 name: jsontest.Name("Interfaces/Merge/Map"),
7828 inBuf: `{"k2":"v2"}`,
7829 inVal: func() any {
7830 var vi any = map[string]string{"k1": "v1"}
7831 return &vi
7832 }(),
7833 want: func() any {
7834 var vi any = map[string]string{"k1": "v1", "k2": "v2"}
7835 return &vi
7836 }(),
7837 }, {
7838 name: jsontest.Name("Interfaces/Merge/Struct"),
7839 inBuf: `{"Array":["goodbye"]}`,
7840 inVal: func() any {
7841 var vi any = structAll{String: "hello"}
7842 return &vi
7843 }(),
7844 want: func() any {
7845 var vi any = structAll{String: "hello", Array: [1]string{"goodbye"}}
7846 return &vi
7847 }(),
7848 }, {
7849 name: jsontest.Name("Interfaces/Merge/NamedInt"),
7850 inBuf: `64`,
7851 inVal: func() any {
7852 var vi any = namedInt64(-64)
7853 return &vi
7854 }(),
7855 want: func() any {
7856 var vi any = namedInt64(+64)
7857 return &vi
7858 }(),
7859 }, {
7860 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
7861 opts: []Options{invalidFormatOption},
7862 inBuf: `true`,
7863 inVal: new(any),
7864 want: func() any {
7865 var vi any = true
7866 return &vi
7867 }(),
7868 }, {
7869 name: jsontest.Name("Interfaces/Any"),
7870 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7871 inVal: new(struct{ X any }),
7872 want: new(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7873 }, {
7874 name: jsontest.Name("Interfaces/Any/Named"),
7875 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7876 inVal: new(struct{ X namedAny }),
7877 want: new(struct{ X namedAny }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7878 }, {
7879 name: jsontest.Name("Interfaces/Any/Stringified"),
7880 opts: []Options{StringifyNumbers(true)},
7881 inBuf: `{"X":"0"}`,
7882 inVal: new(struct{ X any }),
7883 want: new(struct{ X any }{"0"}),
7884 }, {
7885 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Any"),
7886 opts: []Options{
7887 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
7888 *v = "called"
7889 return nil
7890 })),
7891 },
7892 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7893 inVal: new(struct{ X any }),
7894 want: new(struct{ X any }{"called"}),
7895 }, {
7896 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Bool"),
7897 opts: []Options{
7898 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *bool) error {
7899 *v = string(b) != "true"
7900 return nil
7901 })),
7902 },
7903 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7904 inVal: new(struct{ X any }),
7905 want: new(struct{ X any }{[]any{nil, true, false, "", 0.0, map[string]any{}, []any{}}}),
7906 }, {
7907 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/String"),
7908 opts: []Options{
7909 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7910 *v = "called"
7911 return nil
7912 })),
7913 },
7914 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7915 inVal: new(struct{ X any }),
7916 want: new(struct{ X any }{[]any{nil, false, true, "called", 0.0, map[string]any{}, []any{}}}),
7917 }, {
7918 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Float64"),
7919 opts: []Options{
7920 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *float64) error {
7921 *v = 3.14159
7922 return nil
7923 })),
7924 },
7925 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7926 inVal: new(struct{ X any }),
7927 want: new(struct{ X any }{[]any{nil, false, true, "", 3.14159, map[string]any{}, []any{}}}),
7928 }, {
7929 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/MapStringAny"),
7930 opts: []Options{
7931 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *map[string]any) error {
7932 *v = map[string]any{"called": nil}
7933 return nil
7934 })),
7935 },
7936 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7937 inVal: new(struct{ X any }),
7938 want: new(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{"called": nil}, []any{}}}),
7939 }, {
7940 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/SliceAny"),
7941 opts: []Options{
7942 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *[]any) error {
7943 *v = []any{"called"}
7944 return nil
7945 })),
7946 },
7947 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7948 inVal: new(struct{ X any }),
7949 want: new(struct{ X any }{[]any{"called"}}),
7950 }, {
7951 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
7952 inBuf: `{"X":{"fizz":"buzz"}}`,
7953 inVal: new(struct{ X any }),
7954 want: new(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7955 }, {
7956 name: jsontest.Name("Interfaces/Any/Maps/RejectDuplicateNames"),
7957 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7958 inVal: new(struct{ X any }),
7959 want: new(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7960 wantErr: newDuplicateNameError("/X", []byte(`"fizz"`), len64(`{"X":{"fizz":"buzz",`)),
7961 }, {
7962 name: jsontest.Name("Interfaces/Any/Maps/AllowDuplicateNames"),
7963 opts: []Options{jsontext.AllowDuplicateNames(true)},
7964 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7965 inVal: new(struct{ X any }),
7966 want: new(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7967 wantErr: EU(nil).withPos(`{"X":{"fizz":"buzz","fizz":`, "/X/fizz").withType('t', T[string]()),
7968 }, {
7969 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
7970 inBuf: `{"X":["fizz","buzz"]}`,
7971 inVal: new(struct{ X any }),
7972 want: new(struct{ X any }{[]any{"fizz", "buzz"}}),
7973 }, {
7974 name: jsontest.Name("Methods/NilPointer/Null"),
7975 inBuf: `{"X":null}`,
7976 inVal: new(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7977 want: new(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7978 }, {
7979 name: jsontest.Name("Methods/NilPointer/Value"),
7980 inBuf: `{"X":"value"}`,
7981 inVal: new(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7982 want: new(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7983 }, {
7984 name: jsontest.Name("Methods/NilInterface/Null"),
7985 inBuf: `{"X":null}`,
7986 inVal: new(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7987 want: new(struct{ X MarshalerTo }{X: nil}),
7988 }, {
7989 name: jsontest.Name("Methods/NilInterface/Value"),
7990 inBuf: `{"X":"value"}`,
7991 inVal: new(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7992 want: new(struct{ X MarshalerTo }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7993 }, {
7994 name: jsontest.Name("Methods/AllMethods"),
7995 inBuf: `{"X":"hello"}`,
7996 inVal: new(struct{ X *allMethods }),
7997 want: new(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}),
7998 }, {
7999 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
8000 inBuf: `{"X":"hello"}`,
8001 inVal: new(struct{ X *allMethodsExceptJSONv2 }),
8002 want: new(struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
8003 }, {
8004 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
8005 inBuf: `{"X":"hello"}`,
8006 inVal: new(struct{ X *allMethodsExceptJSONv1 }),
8007 want: new(struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
8008 }, {
8009 name: jsontest.Name("Methods/AllMethodsExceptText"),
8010 inBuf: `{"X":"hello"}`,
8011 inVal: new(struct{ X *allMethodsExceptText }),
8012 want: new(struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
8013 }, {
8014 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
8015 inBuf: `{"X":"hello"}`,
8016 inVal: new(struct{ X *onlyMethodJSONv2 }),
8017 want: new(struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
8018 }, {
8019 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
8020 inBuf: `{"X":"hello"}`,
8021 inVal: new(struct{ X *onlyMethodJSONv1 }),
8022 want: new(struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
8023 }, {
8024 name: jsontest.Name("Methods/OnlyMethodText"),
8025 inBuf: `{"X":"hello"}`,
8026 inVal: new(struct{ X *onlyMethodText }),
8027 want: new(struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "UnmarshalText", value: []byte(`hello`)}}}),
8028 }, {
8029 name: jsontest.Name("Methods/Text/Null"),
8030 inBuf: `{"X":null}`,
8031 inVal: new(struct{ X unmarshalTextFunc }{unmarshalTextFunc(func(b []byte) error {
8032 return errMustNotCall
8033 })}),
8034 want: new(struct{ X unmarshalTextFunc }{nil}),
8035 }, {
8036 name: jsontest.Name("Methods/IP"),
8037 inBuf: `"192.168.0.100"`,
8038 inVal: new(net.IP),
8039 want: new(net.IPv4(192, 168, 0, 100)),
8040 }, {
8041
8042 name: jsontest.Name("Methods/Anonymous"),
8043 inBuf: `{"X":"hello"}`,
8044 inVal: new(struct{ X struct{ allMethods } }),
8045 want: new(struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
8046 }, {
8047
8048 name: jsontest.Name("Methods/Addressable"),
8049 inBuf: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
8050 inVal: new(struct {
8051 V allMethods
8052 M map[string]allMethods
8053 I any
8054 }{
8055 I: allMethods{},
8056 }),
8057 want: new(struct {
8058 V allMethods
8059 M map[string]allMethods
8060 I any
8061 }{
8062 V: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
8063 M: map[string]allMethods{"K": {method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}},
8064 I: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
8065 }),
8066 }, {
8067
8068 name: jsontest.Name("Methods/MapKey/JSONv2"),
8069 inBuf: `{"k1":"v1b","k2":"v2"}`,
8070 inVal: new(map[structMethodJSONv2]string{{"k1"}: "v1a", {"k3"}: "v3"}),
8071 want: new(map[structMethodJSONv2]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
8072 }, {
8073
8074 name: jsontest.Name("Methods/MapKey/JSONv1"),
8075 inBuf: `{"k1":"v1b","k2":"v2"}`,
8076 inVal: new(map[structMethodJSONv1]string{{"k1"}: "v1a", {"k3"}: "v3"}),
8077 want: new(map[structMethodJSONv1]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
8078 }, {
8079 name: jsontest.Name("Methods/MapKey/Text"),
8080 inBuf: `{"k1":"v1b","k2":"v2"}`,
8081 inVal: new(map[structMethodText]string{{"k1"}: "v1a", {"k3"}: "v3"}),
8082 want: new(map[structMethodText]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
8083 }, {
8084 name: jsontest.Name("Methods/JSONv2/ErrUnsupported"),
8085 inBuf: `{"fizz":123}`,
8086 inVal: new(unsupportedMethodJSONv2{}),
8087 want: new(unsupportedMethodJSONv2{"called": 1, "fizz": 123}),
8088 }, {
8089 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
8090 inBuf: `{}`,
8091 inVal: new(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
8092 return errSomeError
8093 })),
8094 wantErr: EU(errSomeError).withType(0, T[unmarshalJSONv2Func]()),
8095 }, {
8096 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
8097 inBuf: `{}`,
8098 inVal: new(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
8099 return nil
8100 })),
8101 wantErr: EU(errNonSingularValue).withType(0, T[unmarshalJSONv2Func]()),
8102 }, {
8103 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
8104 inBuf: `{}{}`,
8105 inVal: new(unmarshalJSONv2Func(func(dec *jsontext.Decoder) error {
8106 dec.ReadValue()
8107 dec.ReadValue()
8108 return nil
8109 })),
8110 wantErr: EU(errNonSingularValue).withPos(`{}`, "").withType(0, T[unmarshalJSONv2Func]()),
8111 }, {
8112 name: jsontest.Name("Methods/Invalid/JSONv2/ErrUnsupported"),
8113 inBuf: `{}`,
8114 inVal: new(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
8115 return errors.ErrUnsupported
8116 })),
8117 wantErr: EU(nil).withType(0, T[unmarshalJSONv2Func]()),
8118 }, {
8119 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
8120 inBuf: `{}`,
8121 inVal: new(unmarshalJSONv1Func(func([]byte) error {
8122 return errSomeError
8123 })),
8124 wantErr: EU(errSomeError).withType('{', T[unmarshalJSONv1Func]()),
8125 }, {
8126 name: jsontest.Name("Methods/Invalid/JSONv1/ErrUnsupported"),
8127 inBuf: `{}`,
8128 inVal: new(unmarshalJSONv1Func(func([]byte) error {
8129 return errors.ErrUnsupported
8130 })),
8131 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "UnmarshalJSON method")).withType('{', T[unmarshalJSONv1Func]()),
8132 }, {
8133 name: jsontest.Name("Methods/Invalid/Text/Error"),
8134 inBuf: `"value"`,
8135 inVal: new(unmarshalTextFunc(func([]byte) error {
8136 return errSomeError
8137 })),
8138 wantErr: EU(errSomeError).withType('"', T[unmarshalTextFunc]()),
8139 }, {
8140 name: jsontest.Name("Methods/Invalid/Text/Syntax"),
8141 inBuf: `{}`,
8142 inVal: new(unmarshalTextFunc(func([]byte) error {
8143 panic("should not be called")
8144 })),
8145 wantErr: EU(errNonStringValue).withType('{', T[unmarshalTextFunc]()),
8146 }, {
8147 name: jsontest.Name("Methods/Invalid/Text/ErrUnsupported"),
8148 inBuf: `"value"`,
8149 inVal: new(unmarshalTextFunc(func([]byte) error {
8150 return errors.ErrUnsupported
8151 })),
8152 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "UnmarshalText method")).withType('"', T[unmarshalTextFunc]()),
8153 }, {
8154 name: jsontest.Name("Functions/String/V1"),
8155 opts: []Options{
8156 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8157 if string(b) != `""` {
8158 return fmt.Errorf("got %s, want %s", b, `""`)
8159 }
8160 *v = "called"
8161 return nil
8162 })),
8163 },
8164 inBuf: `""`,
8165 inVal: new(""),
8166 want: new("called"),
8167 }, {
8168 name: jsontest.Name("Functions/String/Empty"),
8169 opts: []Options{WithUnmarshalers(nil)},
8170 inBuf: `"hello"`,
8171 inVal: new(""),
8172 want: new("hello"),
8173 }, {
8174 name: jsontest.Name("Functions/NamedString/V1/NoMatch"),
8175 opts: []Options{
8176 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
8177 panic("should not be called")
8178 })),
8179 },
8180 inBuf: `""`,
8181 inVal: new(""),
8182 want: new(""),
8183 }, {
8184 name: jsontest.Name("Functions/NamedString/V1/Match"),
8185 opts: []Options{
8186 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
8187 if string(b) != `""` {
8188 return fmt.Errorf("got %s, want %s", b, `""`)
8189 }
8190 *v = "called"
8191 return nil
8192 })),
8193 },
8194 inBuf: `""`,
8195 inVal: new(namedString("")),
8196 want: new(namedString("called")),
8197 }, {
8198 name: jsontest.Name("Functions/String/V2"),
8199 opts: []Options{
8200 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8201 switch b, err := dec.ReadValue(); {
8202 case err != nil:
8203 return err
8204 case string(b) != `""`:
8205 return fmt.Errorf("got %s, want %s", b, `""`)
8206 }
8207 *v = "called"
8208 return nil
8209 })),
8210 },
8211 inBuf: `""`,
8212 inVal: new(""),
8213 want: new("called"),
8214 }, {
8215 name: jsontest.Name("Functions/NamedString/V2/NoMatch"),
8216 opts: []Options{
8217 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
8218 panic("should not be called")
8219 })),
8220 },
8221 inBuf: `""`,
8222 inVal: new(""),
8223 want: new(""),
8224 }, {
8225 name: jsontest.Name("Functions/NamedString/V2/Match"),
8226 opts: []Options{
8227 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
8228 switch t, err := dec.ReadToken(); {
8229 case err != nil:
8230 return err
8231 case t.String() != ``:
8232 return fmt.Errorf("got %q, want %q", t, ``)
8233 }
8234 *v = "called"
8235 return nil
8236 })),
8237 },
8238 inBuf: `""`,
8239 inVal: new(namedString("")),
8240 want: new(namedString("called")),
8241 }, {
8242 name: jsontest.Name("Functions/String/Empty1/NoMatch"),
8243 opts: []Options{
8244 WithUnmarshalers(new(Unmarshalers)),
8245 },
8246 inBuf: `""`,
8247 inVal: new(""),
8248 want: new(""),
8249 }, {
8250 name: jsontest.Name("Functions/String/Empty2/NoMatch"),
8251 opts: []Options{
8252 WithUnmarshalers(JoinUnmarshalers()),
8253 },
8254 inBuf: `""`,
8255 inVal: new(""),
8256 want: new(""),
8257 }, {
8258 name: jsontest.Name("Functions/String/V1/DirectError"),
8259 opts: []Options{
8260 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8261 return errSomeError
8262 })),
8263 },
8264 inBuf: `""`,
8265 inVal: new(""),
8266 want: new(""),
8267 wantErr: EU(errSomeError).withType('"', reflect.PointerTo(stringType)),
8268 }, {
8269 name: jsontest.Name("Functions/String/V1/SkipError"),
8270 opts: []Options{
8271 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8272 return errors.ErrUnsupported
8273 })),
8274 },
8275 inBuf: `""`,
8276 inVal: new(""),
8277 want: new(""),
8278 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "unmarshal function of type func([]byte, T) error")).withType('"', reflect.PointerTo(stringType)),
8279 }, {
8280 name: jsontest.Name("Functions/String/V2/DirectError"),
8281 opts: []Options{
8282 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8283 return errSomeError
8284 })),
8285 },
8286 inBuf: `""`,
8287 inVal: new(""),
8288 want: new(""),
8289 wantErr: EU(errSomeError).withType(0, reflect.PointerTo(stringType)),
8290 }, {
8291 name: jsontest.Name("Functions/String/V2/TooFew"),
8292 opts: []Options{
8293 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8294 return nil
8295 })),
8296 },
8297 inBuf: `""`,
8298 inVal: new(""),
8299 want: new(""),
8300 wantErr: EU(errNonSingularValue).withType(0, reflect.PointerTo(stringType)),
8301 }, {
8302 name: jsontest.Name("Functions/String/V2/TooMany"),
8303 opts: []Options{
8304 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8305 if _, err := dec.ReadValue(); err != nil {
8306 return err
8307 }
8308 if _, err := dec.ReadValue(); err != nil {
8309 return err
8310 }
8311 return nil
8312 })),
8313 },
8314 inBuf: `{"X":["",""]}`,
8315 inVal: new(struct{ X []string }{}),
8316 want: new(struct{ X []string }{[]string{""}}),
8317 wantErr: EU(errNonSingularValue).withPos(`{"X":["",`, "/X").withType(0, reflect.PointerTo(stringType)),
8318 }, {
8319 name: jsontest.Name("Functions/String/V2/Skipped"),
8320 opts: []Options{
8321 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8322 return errors.ErrUnsupported
8323 })),
8324 },
8325 inBuf: `""`,
8326 inVal: new(""),
8327 want: new(""),
8328 }, {
8329 name: jsontest.Name("Functions/String/V2/ProcessBeforeSkip"),
8330 opts: []Options{
8331 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8332 if _, err := dec.ReadValue(); err != nil {
8333 return err
8334 }
8335 return errors.ErrUnsupported
8336 })),
8337 },
8338 inBuf: `""`,
8339 inVal: new(""),
8340 want: new(""),
8341 wantErr: EU(errUnsupportedMutation).withType(0, reflect.PointerTo(stringType)),
8342 }, {
8343 name: jsontest.Name("Functions/String/V2/WrappedUnsupported"),
8344 opts: []Options{
8345 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8346 return fmt.Errorf("wrap: %w", errors.ErrUnsupported)
8347 })),
8348 },
8349 inBuf: `""`,
8350 inVal: new(""),
8351 want: new(""),
8352 }, {
8353 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
8354 opts: []Options{
8355 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8356 if string(b) != `"hello"` {
8357 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8358 }
8359 *v = "called"
8360 return nil
8361 })),
8362 },
8363 inBuf: `{"hello":"world"}`,
8364 inVal: new(map[nocaseString]string{}),
8365 want: new(map[nocaseString]string{"called": "world"}),
8366 }, {
8367 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
8368 opts: []Options{
8369 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8370 if string(b) != `"hello"` {
8371 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8372 }
8373 *v.(*nocaseString) = "called"
8374 return nil
8375 })),
8376 },
8377 inBuf: `{"hello":"world"}`,
8378 inVal: new(map[nocaseString]string{}),
8379 want: new(map[nocaseString]string{"called": "world"}),
8380 }, {
8381 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
8382 opts: []Options{
8383 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8384 switch t, err := dec.ReadToken(); {
8385 case err != nil:
8386 return err
8387 case t.String() != "hello":
8388 return fmt.Errorf("got %q, want %q", t, "hello")
8389 }
8390 *v = "called"
8391 return nil
8392 })),
8393 },
8394 inBuf: `{"hello":"world"}`,
8395 inVal: new(map[nocaseString]string{}),
8396 want: new(map[nocaseString]string{"called": "world"}),
8397 }, {
8398 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
8399 opts: []Options{
8400 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8401 switch b, err := dec.ReadValue(); {
8402 case err != nil:
8403 return err
8404 case string(b) != `"hello"`:
8405 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8406 }
8407 *v.(*nocaseString) = "called"
8408 return nil
8409 })),
8410 },
8411 inBuf: `{"hello":"world"}`,
8412 inVal: new(map[nocaseString]string{}),
8413 want: new(map[nocaseString]string{"called": "world"}),
8414 }, {
8415 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
8416 opts: []Options{
8417 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8418 if _, err := dec.ReadValue(); err != nil {
8419 return err
8420 }
8421 xd := export.Decoder(dec)
8422 *v = fmt.Sprintf("%d-%d", len(xd.Tokens.Stack), xd.Tokens.Last.Length())
8423 return nil
8424 })),
8425 },
8426 inBuf: `{"name":"value","name":"value"}`,
8427 inVal: new(map[string]string{}),
8428 want: new(map[string]string{"1-1": "1-2"}),
8429 wantErr: newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"value",`)),
8430 }, {
8431 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
8432 opts: []Options{
8433 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8434 if string(b) != `"world"` {
8435 return fmt.Errorf("got %s, want %s", b, `"world"`)
8436 }
8437 *v = "called"
8438 return nil
8439 })),
8440 },
8441 inBuf: `{"hello":"world"}`,
8442 inVal: new(map[string]nocaseString{}),
8443 want: new(map[string]nocaseString{"hello": "called"}),
8444 }, {
8445 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
8446 opts: []Options{
8447 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8448 if string(b) != `"world"` {
8449 return fmt.Errorf("got %s, want %s", b, `"world"`)
8450 }
8451 *v.(*nocaseString) = "called"
8452 return nil
8453 })),
8454 },
8455 inBuf: `{"hello":"world"}`,
8456 inVal: new(map[string]nocaseString{}),
8457 want: new(map[string]nocaseString{"hello": "called"}),
8458 }, {
8459 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
8460 opts: []Options{
8461 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8462 switch t, err := dec.ReadToken(); {
8463 case err != nil:
8464 return err
8465 case t.String() != "world":
8466 return fmt.Errorf("got %q, want %q", t, "world")
8467 }
8468 *v = "called"
8469 return nil
8470 })),
8471 },
8472 inBuf: `{"hello":"world"}`,
8473 inVal: new(map[string]nocaseString{}),
8474 want: new(map[string]nocaseString{"hello": "called"}),
8475 }, {
8476 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
8477 opts: []Options{
8478 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8479 switch b, err := dec.ReadValue(); {
8480 case err != nil:
8481 return err
8482 case string(b) != `"world"`:
8483 return fmt.Errorf("got %s, want %s", b, `"world"`)
8484 }
8485 *v.(*nocaseString) = "called"
8486 return nil
8487 })),
8488 },
8489 inBuf: `{"hello":"world"}`,
8490 inVal: new(map[string]nocaseString{}),
8491 want: new(map[string]nocaseString{"hello": "called"}),
8492 }, {
8493 name: jsontest.Name("Funtions/Struct/Fields"),
8494 opts: []Options{
8495 WithUnmarshalers(JoinUnmarshalers(
8496 UnmarshalFunc(func(b []byte, v *bool) error {
8497 if string(b) != `"called1"` {
8498 return fmt.Errorf("got %s, want %s", b, `"called1"`)
8499 }
8500 *v = true
8501 return nil
8502 }),
8503 UnmarshalFunc(func(b []byte, v *string) error {
8504 if string(b) != `"called2"` {
8505 return fmt.Errorf("got %s, want %s", b, `"called2"`)
8506 }
8507 *v = "called2"
8508 return nil
8509 }),
8510 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[]byte) error {
8511 switch t, err := dec.ReadToken(); {
8512 case err != nil:
8513 return err
8514 case t.String() != "called3":
8515 return fmt.Errorf("got %q, want %q", t, "called3")
8516 }
8517 *v = []byte("called3")
8518 return nil
8519 }),
8520 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *int64) error {
8521 switch b, err := dec.ReadValue(); {
8522 case err != nil:
8523 return err
8524 case string(b) != `"called4"`:
8525 return fmt.Errorf("got %s, want %s", b, `"called4"`)
8526 }
8527 *v = 123
8528 return nil
8529 }),
8530 )),
8531 },
8532 inBuf: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":456,"Float":789}`,
8533 inVal: new(structScalars{}),
8534 want: new(structScalars{Bool: true, String: "called2", Bytes: []byte("called3"), Int: 123, Uint: 456, Float: 789}),
8535 }, {
8536 name: jsontest.Name("Functions/Struct/Embedded"),
8537 opts: []Options{
8538 WithUnmarshalers(JoinUnmarshalers(
8539 UnmarshalFunc(func([]byte, *structEmbeddedL1) error {
8540 panic("should not be called")
8541 }),
8542 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *StructEmbed2) error {
8543 panic("should not be called")
8544 }),
8545 )),
8546 },
8547 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
8548 inVal: new(structEmbedded),
8549 want: new(structEmbedded{
8550 X: structEmbeddedL1{
8551 X: &structEmbeddedL2{A: "A1", B: "B1" },
8552 StructEmbed1: StructEmbed1{ D: "D2" },
8553 },
8554 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
8555 }),
8556 }, {
8557 name: jsontest.Name("Functions/Slice/Elem"),
8558 opts: []Options{
8559 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8560 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8561 return nil
8562 })),
8563 },
8564 inBuf: `["hello","World"]`,
8565 inVal: new([]string{}),
8566 want: new([]string{"HELLO", "WORLD"}),
8567 }, {
8568 name: jsontest.Name("Functions/Array/Elem"),
8569 opts: []Options{
8570 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8571 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8572 return nil
8573 })),
8574 },
8575 inBuf: `["hello","World"]`,
8576 inVal: new([2]string{}),
8577 want: new([2]string{"HELLO", "WORLD"}),
8578 }, {
8579 name: jsontest.Name("Functions/Pointer/Nil"),
8580 opts: []Options{
8581 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8582 t, err := dec.ReadToken()
8583 *v = strings.ToUpper(t.String())
8584 return err
8585 })),
8586 },
8587 inBuf: `{"X":"hello"}`,
8588 inVal: new(struct{ X *string }{nil}),
8589 want: new(struct{ X *string }{new("HELLO")}),
8590 }, {
8591 name: jsontest.Name("Functions/Pointer/NonNil"),
8592 opts: []Options{
8593 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8594 t, err := dec.ReadToken()
8595 *v = strings.ToUpper(t.String())
8596 return err
8597 })),
8598 },
8599 inBuf: `{"X":"hello"}`,
8600 inVal: new(struct{ X *string }{new("")}),
8601 want: new(struct{ X *string }{new("HELLO")}),
8602 }, {
8603 name: jsontest.Name("Functions/Interface/Nil"),
8604 opts: []Options{
8605 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v fmt.Stringer) error {
8606 panic("should not be called")
8607 })),
8608 },
8609 inBuf: `{"X":"hello"}`,
8610 inVal: new(struct{ X fmt.Stringer }{nil}),
8611 want: new(struct{ X fmt.Stringer }{nil}),
8612 wantErr: EU(internal.ErrNilInterface).withPos(`{"X":`, "/X").withType(0, T[fmt.Stringer]()),
8613 }, {
8614 name: jsontest.Name("Functions/Interface/NetIP"),
8615 opts: []Options{
8616 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8617 *v = net.IP{}
8618 return errors.ErrUnsupported
8619 })),
8620 },
8621 inBuf: `{"X":"1.1.1.1"}`,
8622 inVal: new(struct{ X fmt.Stringer }{nil}),
8623 want: new(struct{ X fmt.Stringer }{net.IPv4(1, 1, 1, 1)}),
8624 }, {
8625 name: jsontest.Name("Functions/Interface/NewPointerNetIP"),
8626 opts: []Options{
8627 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8628 *v = new(net.IP)
8629 return errors.ErrUnsupported
8630 })),
8631 },
8632 inBuf: `{"X":"1.1.1.1"}`,
8633 inVal: new(struct{ X fmt.Stringer }{nil}),
8634 want: new(struct{ X fmt.Stringer }{new(net.IPv4(1, 1, 1, 1))}),
8635 }, {
8636 name: jsontest.Name("Functions/Interface/NilPointerNetIP"),
8637 opts: []Options{
8638 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8639 *v = (*net.IP)(nil)
8640 return errors.ErrUnsupported
8641 })),
8642 },
8643 inBuf: `{"X":"1.1.1.1"}`,
8644 inVal: new(struct{ X fmt.Stringer }{nil}),
8645 want: new(struct{ X fmt.Stringer }{new(net.IPv4(1, 1, 1, 1))}),
8646 }, {
8647 name: jsontest.Name("Functions/Interface/NilPointerNetIP/Override"),
8648 opts: []Options{
8649 WithUnmarshalers(JoinUnmarshalers(
8650 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8651 *v = (*net.IP)(nil)
8652 return errors.ErrUnsupported
8653 }),
8654 UnmarshalFunc(func(b []byte, v *net.IP) error {
8655 b = bytes.ReplaceAll(b, []byte(`1`), []byte(`8`))
8656 return v.UnmarshalText(bytes.Trim(b, `"`))
8657 }),
8658 )),
8659 },
8660 inBuf: `{"X":"1.1.1.1"}`,
8661 inVal: new(struct{ X fmt.Stringer }{nil}),
8662 want: new(struct{ X fmt.Stringer }{new(net.IPv4(8, 8, 8, 8))}),
8663 }, {
8664 name: jsontest.Name("Functions/Interface/Any"),
8665 opts: []Options{
8666 WithUnmarshalers(func() *Unmarshalers {
8667 type P struct {
8668 D int
8669 N int64
8670 }
8671 type PV struct {
8672 P P
8673 V any
8674 }
8675
8676 var lastChecks []func() error
8677 checkLast := func() error {
8678 for _, fn := range lastChecks {
8679 if err := fn(); err != nil {
8680 return err
8681 }
8682 }
8683 return errors.ErrUnsupported
8684 }
8685 makeValueChecker := func(name string, want []PV) func(d *jsontext.Decoder, v any) error {
8686 checkNext := func(d *jsontext.Decoder, v any) error {
8687 xd := export.Decoder(d)
8688 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8689 rv := reflect.ValueOf(v)
8690 pv := PV{p, v}
8691 switch {
8692 case len(want) == 0:
8693 return fmt.Errorf("%s: %v: got more values than expected", name, p)
8694 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
8695 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
8696 case !reflect.DeepEqual(pv, want[0]):
8697 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
8698 default:
8699 want = want[1:]
8700 return errors.ErrUnsupported
8701 }
8702 }
8703 lastChecks = append(lastChecks, func() error {
8704 if len(want) > 0 {
8705 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8706 }
8707 return nil
8708 })
8709 return checkNext
8710 }
8711 makePositionChecker := func(name string, want []P) func(d *jsontext.Decoder, v any) error {
8712 checkNext := func(d *jsontext.Decoder, v any) error {
8713 xd := export.Decoder(d)
8714 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8715 switch {
8716 case len(want) == 0:
8717 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
8718 case p != want[0]:
8719 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
8720 default:
8721 want = want[1:]
8722 return errors.ErrUnsupported
8723 }
8724 }
8725 lastChecks = append(lastChecks, func() error {
8726 if len(want) > 0 {
8727 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8728 }
8729 return nil
8730 })
8731 return checkNext
8732 }
8733
8734
8735
8736 wantAny := []PV{
8737 {P{1, 0}, new(any(nil))},
8738 {P{1, 1}, new(any(valueStringer{}))},
8739 {P{1, 1}, new(valueStringer{})},
8740 {P{1, 2}, new(any((*valueStringer)(nil)))},
8741 {P{1, 2}, new((*valueStringer)(nil))},
8742 {P{1, 2}, new(valueStringer{})},
8743 {P{1, 3}, new(any(new(valueStringer{})))},
8744 {P{1, 3}, new(new(valueStringer{}))},
8745 {P{1, 3}, new(valueStringer{})},
8746 {P{1, 4}, new(any((**valueStringer)(nil)))},
8747 {P{1, 4}, new((**valueStringer)(nil))},
8748 {P{1, 4}, new((*valueStringer)(nil))},
8749 {P{1, 4}, new(valueStringer{})},
8750 {P{1, 5}, new(any(new((*valueStringer)(nil))))},
8751 {P{1, 5}, new(new((*valueStringer)(nil)))},
8752 {P{1, 5}, new((*valueStringer)(nil))},
8753 {P{1, 5}, new(valueStringer{})},
8754 {P{1, 6}, new(any(new(new(valueStringer{}))))},
8755 {P{1, 6}, new(new(new(valueStringer{})))},
8756 {P{1, 6}, new(new(valueStringer{}))},
8757 {P{1, 6}, new(valueStringer{})},
8758 {P{1, 7}, new(any(pointerStringer{}))},
8759 {P{1, 7}, new(pointerStringer{})},
8760 {P{1, 8}, new(any((*pointerStringer)(nil)))},
8761 {P{1, 8}, new((*pointerStringer)(nil))},
8762 {P{1, 8}, new(pointerStringer{})},
8763 {P{1, 9}, new(any(new(pointerStringer{})))},
8764 {P{1, 9}, new(new(pointerStringer{}))},
8765 {P{1, 9}, new(pointerStringer{})},
8766 {P{1, 10}, new(any((**pointerStringer)(nil)))},
8767 {P{1, 10}, new((**pointerStringer)(nil))},
8768 {P{1, 10}, new((*pointerStringer)(nil))},
8769 {P{1, 10}, new(pointerStringer{})},
8770 {P{1, 11}, new(any(new((*pointerStringer)(nil))))},
8771 {P{1, 11}, new(new((*pointerStringer)(nil)))},
8772 {P{1, 11}, new((*pointerStringer)(nil))},
8773 {P{1, 11}, new(pointerStringer{})},
8774 {P{1, 12}, new(any(new(new(pointerStringer{}))))},
8775 {P{1, 12}, new(new(new(pointerStringer{})))},
8776 {P{1, 12}, new(new(pointerStringer{}))},
8777 {P{1, 12}, new(pointerStringer{})},
8778 {P{1, 13}, new(any("LAST"))},
8779 {P{1, 13}, new("LAST")},
8780 }
8781 checkAny := makeValueChecker("any", wantAny)
8782 anyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v any) error {
8783 return checkAny(dec, v)
8784 })
8785
8786 var wantPointerAny []PV
8787 for _, v := range wantAny {
8788 if _, ok := v.V.(*any); ok {
8789 wantPointerAny = append(wantPointerAny, v)
8790 }
8791 }
8792 checkPointerAny := makeValueChecker("*any", wantPointerAny)
8793 pointerAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *any) error {
8794 return checkPointerAny(dec, v)
8795 })
8796
8797 checkNamedAny := makeValueChecker("namedAny", wantAny)
8798 namedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v namedAny) error {
8799 return checkNamedAny(dec, v)
8800 })
8801
8802 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
8803 pointerNamedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedAny) error {
8804 return checkPointerNamedAny(dec, v)
8805 })
8806
8807 type stringer = fmt.Stringer
8808 var wantStringer []PV
8809 for _, v := range wantAny {
8810 if _, ok := v.V.(stringer); ok {
8811 wantStringer = append(wantStringer, v)
8812 }
8813 }
8814 checkStringer := makeValueChecker("stringer", wantStringer)
8815 stringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v stringer) error {
8816 return checkStringer(dec, v)
8817 })
8818
8819 checkPointerStringer := makeValueChecker("*stringer", nil)
8820 pointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *stringer) error {
8821 return checkPointerStringer(dec, v)
8822 })
8823
8824 wantValueStringer := []P{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}}
8825 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
8826 pointerValueStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *valueStringer) error {
8827 return checkPointerValueStringer(dec, v)
8828 })
8829
8830 wantPointerStringer := []P{{1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}}
8831 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
8832 pointerPointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *pointerStringer) error {
8833 return checkPointerPointerStringer(dec, v)
8834 })
8835
8836 lastUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8837 return checkLast()
8838 })
8839
8840 return JoinUnmarshalers(
8841
8842
8843 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[14]any) error {
8844 if _, err := dec.ReadToken(); err != nil {
8845 return err
8846 }
8847 for i := range len(*v) {
8848 if err := UnmarshalDecode(dec, &(*v)[i]); err != nil {
8849 return err
8850 }
8851 }
8852 if _, err := dec.ReadToken(); err != nil {
8853 return err
8854 }
8855 return nil
8856 }),
8857
8858 anyUnmarshaler,
8859 pointerAnyUnmarshaler,
8860 namedAnyUnmarshaler,
8861 pointerNamedAnyUnmarshaler,
8862 stringerUnmarshaler,
8863 pointerStringerUnmarshaler,
8864 pointerValueStringerUnmarshaler,
8865 pointerPointerStringerUnmarshaler,
8866 lastUnmarshaler,
8867 )
8868 }()),
8869 },
8870 inBuf: `[null,{},{},{},{},{},{},{},{},{},{},{},{},"LAST"]`,
8871 inVal: new([...]any{
8872 nil,
8873 valueStringer{},
8874 (*valueStringer)(nil),
8875 new(valueStringer{}),
8876 (**valueStringer)(nil),
8877 new((*valueStringer)(nil)),
8878 new(new(valueStringer{})),
8879 pointerStringer{},
8880 (*pointerStringer)(nil),
8881 new(pointerStringer{}),
8882 (**pointerStringer)(nil),
8883 new((*pointerStringer)(nil)),
8884 new(new(pointerStringer{})),
8885 "LAST",
8886 }),
8887 }, {
8888 name: jsontest.Name("Functions/Precedence/V1First"),
8889 opts: []Options{
8890 WithUnmarshalers(JoinUnmarshalers(
8891 UnmarshalFunc(func(b []byte, v *string) error {
8892 if string(b) != `"called"` {
8893 return fmt.Errorf("got %s, want %s", b, `"called"`)
8894 }
8895 *v = "called"
8896 return nil
8897 }),
8898 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8899 panic("should not be called")
8900 }),
8901 )),
8902 },
8903 inBuf: `"called"`,
8904 inVal: new(""),
8905 want: new("called"),
8906 }, {
8907 name: jsontest.Name("Functions/Precedence/V2First"),
8908 opts: []Options{
8909 WithUnmarshalers(JoinUnmarshalers(
8910 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8911 switch t, err := dec.ReadToken(); {
8912 case err != nil:
8913 return err
8914 case t.String() != "called":
8915 return fmt.Errorf("got %q, want %q", t, "called")
8916 }
8917 *v = "called"
8918 return nil
8919 }),
8920 UnmarshalFunc(func([]byte, *string) error {
8921 panic("should not be called")
8922 }),
8923 )),
8924 },
8925 inBuf: `"called"`,
8926 inVal: new(""),
8927 want: new("called"),
8928 }, {
8929 name: jsontest.Name("Functions/Precedence/V2Skipped"),
8930 opts: []Options{
8931 WithUnmarshalers(JoinUnmarshalers(
8932 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8933 return errors.ErrUnsupported
8934 }),
8935 UnmarshalFunc(func(b []byte, v *string) error {
8936 if string(b) != `"called"` {
8937 return fmt.Errorf("got %s, want %s", b, `"called"`)
8938 }
8939 *v = "called"
8940 return nil
8941 }),
8942 )),
8943 },
8944 inBuf: `"called"`,
8945 inVal: new(""),
8946 want: new("called"),
8947 }, {
8948 name: jsontest.Name("Functions/Precedence/NestedFirst"),
8949 opts: []Options{
8950 WithUnmarshalers(JoinUnmarshalers(
8951 JoinUnmarshalers(
8952 UnmarshalFunc(func(b []byte, v *string) error {
8953 if string(b) != `"called"` {
8954 return fmt.Errorf("got %s, want %s", b, `"called"`)
8955 }
8956 *v = "called"
8957 return nil
8958 }),
8959 ),
8960 UnmarshalFunc(func([]byte, *string) error {
8961 panic("should not be called")
8962 }),
8963 )),
8964 },
8965 inBuf: `"called"`,
8966 inVal: new(""),
8967 want: new("called"),
8968 }, {
8969 name: jsontest.Name("Functions/Precedence/NestedLast"),
8970 opts: []Options{
8971 WithUnmarshalers(JoinUnmarshalers(
8972 UnmarshalFunc(func(b []byte, v *string) error {
8973 if string(b) != `"called"` {
8974 return fmt.Errorf("got %s, want %s", b, `"called"`)
8975 }
8976 *v = "called"
8977 return nil
8978 }),
8979 JoinUnmarshalers(
8980 UnmarshalFunc(func([]byte, *string) error {
8981 panic("should not be called")
8982 }),
8983 ),
8984 )),
8985 },
8986 inBuf: `"called"`,
8987 inVal: new(""),
8988 want: new("called"),
8989 }, {
8990 name: jsontest.Name("Duration/Null"),
8991 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
8992 inBuf: `{"D1":null,"D2":null}`,
8993 inVal: new(struct {
8994 D1 time.Duration `json:",format:units"`
8995 D2 time.Duration `json:",format:nano"`
8996 }{1, 1}),
8997 want: new(struct {
8998 D1 time.Duration `json:",format:units"`
8999 D2 time.Duration `json:",format:nano"`
9000 }{0, 0}),
9001 }, {
9002 name: jsontest.Name("Duration/Zero"),
9003 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9004 inBuf: `{"D1":"0s","D2":0}`,
9005 inVal: new(struct {
9006 D1 time.Duration `json:",format:units"`
9007 D2 time.Duration `json:",format:nano"`
9008 }{1, 1}),
9009 want: new(struct {
9010 D1 time.Duration `json:",format:units"`
9011 D2 time.Duration `json:",format:nano"`
9012 }{0, 0}),
9013 }, {
9014 name: jsontest.Name("Duration/Positive"),
9015 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9016 inBuf: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
9017 inVal: new(struct {
9018 D1 time.Duration `json:",format:units"`
9019 D2 time.Duration `json:",format:nano"`
9020 }),
9021 want: new(struct {
9022 D1 time.Duration `json:",format:units"`
9023 D2 time.Duration `json:",format:nano"`
9024 }{
9025 123456789123456789,
9026 123456789123456789,
9027 }),
9028 }, {
9029 name: jsontest.Name("Duration/Negative"),
9030 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9031 inBuf: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
9032 inVal: new(struct {
9033 D1 time.Duration `json:",format:units"`
9034 D2 time.Duration `json:",format:nano"`
9035 }),
9036 want: new(struct {
9037 D1 time.Duration `json:",format:units"`
9038 D2 time.Duration `json:",format:nano"`
9039 }{
9040 -123456789123456789,
9041 -123456789123456789,
9042 }),
9043 }, {
9044 name: jsontest.Name("Duration/Nanos/String"),
9045 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9046 inBuf: `{"D":"12345"}`,
9047 inVal: new(struct {
9048 D time.Duration `json:",string,format:nano"`
9049 }{1}),
9050 want: new(struct {
9051 D time.Duration `json:",string,format:nano"`
9052 }{12345}),
9053 }, {
9054 name: jsontest.Name("Duration/Nanos/String/Invalid"),
9055 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9056 inBuf: `{"D":"+12345"}`,
9057 inVal: new(struct {
9058 D time.Duration `json:",string,format:nano"`
9059 }{1}),
9060 want: new(struct {
9061 D time.Duration `json:",string,format:nano"`
9062 }{1}),
9063 wantErr: EU(fmt.Errorf(`invalid duration "+12345": %w`, strconv.ErrSyntax)).withPos(`{"D":`, "/D").withType('"', timeDurationType),
9064 }, {
9065 name: jsontest.Name("Duration/Nanos/Mismatch"),
9066 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9067 inBuf: `{"D":"34293h33m9.123456789s"}`,
9068 inVal: new(struct {
9069 D time.Duration `json:",format:nano"`
9070 }{1}),
9071 want: new(struct {
9072 D time.Duration `json:",format:nano"`
9073 }{1}),
9074 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('"', timeDurationType),
9075 }, {
9076 name: jsontest.Name("Duration/Nanos"),
9077 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9078 inBuf: `{"D":1.324}`,
9079 inVal: new(struct {
9080 D time.Duration `json:",format:nano"`
9081 }{-1}),
9082 want: new(struct {
9083 D time.Duration `json:",format:nano"`
9084 }{1}),
9085 }, {
9086 name: jsontest.Name("Duration/String/Mismatch"),
9087 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9088 inBuf: `{"D":-123456789123456789}`,
9089 inVal: new(struct {
9090 D time.Duration `json:",format:units"`
9091 }{1}),
9092 want: new(struct {
9093 D time.Duration `json:",format:units"`
9094 }{1}),
9095 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('0', timeDurationType),
9096 }, {
9097 name: jsontest.Name("Duration/String/Invalid"),
9098 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9099 inBuf: `{"D":"5minkutes"}`,
9100 inVal: new(struct {
9101 D time.Duration `json:",format:units"`
9102 }{1}),
9103 want: new(struct {
9104 D time.Duration `json:",format:units"`
9105 }{1}),
9106 wantErr: EU(func() error {
9107 _, err := time.ParseDuration("5minkutes")
9108 return err
9109 }()).withPos(`{"D":`, "/D").withType('"', timeDurationType),
9110 }, {
9111 name: jsontest.Name("Duration/Syntax/Invalid"),
9112 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9113 inBuf: `{"D":x}`,
9114 inVal: new(struct {
9115 D time.Duration `json:",format:units"`
9116 }{1}),
9117 want: new(struct {
9118 D time.Duration `json:",format:units"`
9119 }{1}),
9120 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"D":`), "/D"),
9121 }, {
9122 name: jsontest.Name("Duration/Format"),
9123 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9124 inBuf: `{
9125 "D1": "12h34m56.078090012s",
9126 "D2": "12h34m56.078090012s",
9127 "D3": 45296.078090012,
9128 "D4": "45296.078090012",
9129 "D5": 45296078.090012,
9130 "D6": "45296078.090012",
9131 "D7": 45296078090.012,
9132 "D8": "45296078090.012",
9133 "D9": 45296078090012,
9134 "D10": "45296078090012",
9135 "D11": "PT12H34M56.078090012S"
9136 }`,
9137 inVal: new(structDurationFormat),
9138 want: new(structDurationFormat{
9139 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9140 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9141 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9142 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9143 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9144 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9145 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9146 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9147 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9148 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9149 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
9150 }),
9151 }, {
9152 name: jsontest.Name("Duration/Format/Invalid"),
9153 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9154 inBuf: `{"D":"0s"}`,
9155 inVal: new(struct {
9156 D time.Duration `json:",format:invalid"`
9157 }{1}),
9158 want: new(struct {
9159 D time.Duration `json:",format:invalid"`
9160 }{1}),
9161 wantErr: EU(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, timeDurationType),
9162 }, {
9163
9173
9179 name: jsontest.Name("Duration/MapKey/Legacy"),
9180 opts: []Options{jsonflags.FormatDurationAsNano | 1},
9181 inBuf: `{"1000000000":""}`,
9182 inVal: new(map[time.Duration]string),
9183 want: new(map[time.Duration]string{time.Second: ""}),
9184 }, {
9185
9192 name: jsontest.Name("Time/Zero"),
9193 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9194 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"}`,
9195 inVal: new(struct {
9196 T1 time.Time
9197 T2 time.Time `json:",format:RFC822"`
9198 T3 time.Time `json:",format:'2006-01-02'"`
9199 T4 time.Time `json:",omitzero"`
9200 T5 time.Time `json:",omitempty"`
9201 }),
9202 want: new(struct {
9203 T1 time.Time
9204 T2 time.Time `json:",format:RFC822"`
9205 T3 time.Time `json:",format:'2006-01-02'"`
9206 T4 time.Time `json:",omitzero"`
9207 T5 time.Time `json:",omitempty"`
9208 }{
9209 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
9210 mustParseTime(time.RFC822, "01 Jan 01 00:00 UTC"),
9211 mustParseTime("2006-01-02", "0001-01-01"),
9212 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
9213 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
9214 }),
9215 }, {
9216 name: jsontest.Name("Time/Format"),
9217 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9218 inBuf: `{
9219 "T1": "1234-01-02T03:04:05.000000006Z",
9220 "T2": "Mon Jan 2 03:04:05 1234",
9221 "T3": "Mon Jan 2 03:04:05 UTC 1234",
9222 "T4": "Mon Jan 02 03:04:05 +0000 1234",
9223 "T5": "02 Jan 34 03:04 UTC",
9224 "T6": "02 Jan 34 03:04 +0000",
9225 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
9226 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
9227 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
9228 "T10": "1234-01-02T03:04:05Z",
9229 "T11": "1234-01-02T03:04:05.000000006Z",
9230 "T12": "3:04AM",
9231 "T13": "Jan 2 03:04:05",
9232 "T14": "Jan 2 03:04:05.000",
9233 "T15": "Jan 2 03:04:05.000000",
9234 "T16": "Jan 2 03:04:05.000000006",
9235 "T17": "1234-01-02 03:04:05",
9236 "T18": "1234-01-02",
9237 "T19": "03:04:05",
9238 "T20": "1234-01-02",
9239 "T21": "\"weird\"1234",
9240 "T22": -23225777754.999999994,
9241 "T23": "-23225777754.999999994",
9242 "T24": -23225777754999.999994,
9243 "T25": "-23225777754999.999994",
9244 "T26": -23225777754999999.994,
9245 "T27": "-23225777754999999.994",
9246 "T28": -23225777754999999994,
9247 "T29": "-23225777754999999994"
9248 }`,
9249 inVal: new(structTimeFormat),
9250 want: new(structTimeFormat{
9251 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9252 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9253 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9254 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9255 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9256 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9257 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9258 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9259 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9260 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9261 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9262 mustParseTime(time.Kitchen, "3:04AM"),
9263 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9264 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9265 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9266 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9267 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9268 mustParseTime(time.DateOnly, "1234-01-02"),
9269 mustParseTime(time.TimeOnly, "03:04:05"),
9270 mustParseTime("2006-01-02", "1234-01-02"),
9271 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9272 time.Unix(-23225777755, 6).UTC(),
9273 time.Unix(-23225777755, 6).UTC(),
9274 time.Unix(-23225777755, 6).UTC(),
9275 time.Unix(-23225777755, 6).UTC(),
9276 time.Unix(-23225777755, 6).UTC(),
9277 time.Unix(-23225777755, 6).UTC(),
9278 time.Unix(-23225777755, 6).UTC(),
9279 time.Unix(-23225777755, 6).UTC(),
9280 }),
9281 }, {
9282 name: jsontest.Name("Time/Format/String/Invalid"),
9283 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9284 inBuf: `{"T":"2023-01-01T00:00:00Z"}`,
9285 inVal: new(structTimeFormatStringInvalid),
9286 want: new(structTimeFormatStringInvalid),
9287 wantErr: EU(errInvalidStringTag).withPos(`{"T":`, "/T").withType(0, timeTimeType),
9288 }, {
9289 name: jsontest.Name("Time/Format/UnixString/InvalidNumber"),
9290 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9291 inBuf: `{
9292 "T23": -23225777754.999999994,
9293 "T25": -23225777754999.999994,
9294 "T27": -23225777754999999.994,
9295 "T29": -23225777754999999994
9296 }`,
9297 inVal: new(structTimeFormat),
9298 want: new(structTimeFormat),
9299 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T23": `, "/T23").withType('0', timeTimeType),
9300 }, {
9301 name: jsontest.Name("Time/Format/UnixString/InvalidString"),
9302 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9303 inBuf: `{
9304 "T22": "-23225777754.999999994",
9305 "T24": "-23225777754999.999994",
9306 "T26": "-23225777754999999.994",
9307 "T28": "-23225777754999999994"
9308 }`,
9309 inVal: new(structTimeFormat),
9310 want: new(structTimeFormat),
9311 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T22": `, "/T22").withType('"', timeTimeType),
9312 }, {
9313 name: jsontest.Name("Time/Format/Null"),
9314 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9315 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}`,
9316 inVal: new(structTimeFormat{
9317 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9318 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9319 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9320 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9321 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9322 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9323 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9324 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9325 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9326 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9327 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9328 mustParseTime(time.Kitchen, "3:04AM"),
9329 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9330 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9331 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9332 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9333 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9334 mustParseTime(time.DateOnly, "1234-01-02"),
9335 mustParseTime(time.TimeOnly, "03:04:05"),
9336 mustParseTime("2006-01-02", "1234-01-02"),
9337 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9338 time.Unix(-23225777755, 6).UTC(),
9339 time.Unix(-23225777755, 6).UTC(),
9340 time.Unix(-23225777755, 6).UTC(),
9341 time.Unix(-23225777755, 6).UTC(),
9342 time.Unix(-23225777755, 6).UTC(),
9343 time.Unix(-23225777755, 6).UTC(),
9344 time.Unix(-23225777755, 6).UTC(),
9345 time.Unix(-23225777755, 6).UTC(),
9346 }),
9347 want: new(structTimeFormat),
9348 }, {
9349 name: jsontest.Name("Time/RFC3339/Mismatch"),
9350 inBuf: `{"T":1234}`,
9351 inVal: new(struct {
9352 T time.Time
9353 }),
9354 wantErr: EU(nil).withPos(`{"T":`, "/T").withType('0', timeTimeType),
9355 }, {
9356 name: jsontest.Name("Time/RFC3339/ParseError"),
9357 inBuf: `{"T":"2021-09-29T12:44:52"}`,
9358 inVal: new(struct {
9359 T time.Time
9360 }),
9361 wantErr: EU(func() error {
9362 _, err := time.Parse(time.RFC3339, "2021-09-29T12:44:52")
9363 return err
9364 }()).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9365 }, {
9366 name: jsontest.Name("Time/Format/Invalid"),
9367 opts: []Options{jsonopts.ExperimentalSupportFormatTag(true)},
9368 inBuf: `{"T":""}`,
9369 inVal: new(struct {
9370 T time.Time `json:",format:UndefinedConstant"`
9371 }),
9372 wantErr: EU(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
9373 }, {
9374 name: jsontest.Name("Time/Format/SingleDigitHour"),
9375 inBuf: `{"T":"2000-01-01T1:12:34Z"}`,
9376 inVal: new(struct{ T time.Time }),
9377 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T1:12:34Z", "15", "1", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9378 }, {
9379 name: jsontest.Name("Time/Format/SubsecondComma"),
9380 inBuf: `{"T":"2000-01-01T00:00:00,000Z"}`,
9381 inVal: new(struct{ T time.Time }),
9382 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00,000Z", ".", ",", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9383 }, {
9384 name: jsontest.Name("Time/Format/TimezoneHourOverflow"),
9385 inBuf: `{"T":"2000-01-01T00:00:00+24:00"}`,
9386 inVal: new(struct{ T time.Time }),
9387 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),
9388 }, {
9389 name: jsontest.Name("Time/Format/TimezoneMinuteOverflow"),
9390 inBuf: `{"T":"2000-01-01T00:00:00+00:60"}`,
9391 inVal: new(struct{ T time.Time }),
9392 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),
9393 }, {
9394 name: jsontest.Name("Time/Syntax/Invalid"),
9395 inBuf: `{"T":x}`,
9396 inVal: new(struct {
9397 T time.Time
9398 }),
9399 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"T":`), "/T"),
9400 }, {
9401 name: jsontest.Name("Time/IgnoreInvalidFormat"),
9402 opts: []Options{invalidFormatOption},
9403 inBuf: `"2000-01-01T00:00:00Z"`,
9404 inVal: new(time.Time{}),
9405 want: new(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)),
9406 }}
9407
9408 for _, tt := range tests {
9409 if tt.skip {
9410 continue
9411 }
9412 t.Run(tt.name.Name, func(t *testing.T) {
9413 got := tt.inVal
9414 gotErr := Unmarshal([]byte(tt.inBuf), got, tt.opts...)
9415 if !reflect.DeepEqual(got, tt.want) && tt.want != nil {
9416 t.Errorf("%s: Unmarshal output mismatch:\ngot %v\nwant %v", tt.name.Where, got, tt.want)
9417 }
9418 if !reflect.DeepEqual(gotErr, tt.wantErr) {
9419 t.Errorf("%s: Unmarshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
9420 }
9421 })
9422 }
9423 }
9424
9425 func TestMarshalInvalidNamespace(t *testing.T) {
9426 tests := []struct {
9427 name jsontest.CaseName
9428 val any
9429 }{
9430 {jsontest.Name("Map"), map[string]string{"X": "\xde\xad\xbe\xef"}},
9431 {jsontest.Name("Struct"), struct{ X string }{"\xde\xad\xbe\xef"}},
9432 {jsontest.Name("MapBadKey"), map[string]int{"\xde\xad\xbe\xef": 0}},
9433 }
9434 for _, tt := range tests {
9435 t.Run(tt.name.Name, func(t *testing.T) {
9436 enc := jsontext.NewEncoder(new(bytes.Buffer))
9437 if err := MarshalEncode(enc, tt.val); err == nil {
9438 t.Fatalf("%s: MarshalEncode error is nil, want non-nil", tt.name.Where)
9439 }
9440 for _, tok := range []jsontext.Token{
9441 jsontext.Null, jsontext.String(""), jsontext.Int(0), jsontext.BeginObject, jsontext.EndObject, jsontext.BeginArray, jsontext.EndArray,
9442 } {
9443 if err := enc.WriteToken(tok); err == nil {
9444 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9445 }
9446 }
9447 for _, val := range []string{`null`, `""`, `0`, `{}`, `[]`} {
9448 if err := enc.WriteValue([]byte(val)); err == nil {
9449 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9450 }
9451 }
9452 })
9453 }
9454 }
9455
9456
9457
9458
9459 func TestMarshalEncodeInvalidNamespaceAtName(t *testing.T) {
9460 enc := jsontext.NewEncoder(new(bytes.Buffer))
9461
9462
9463
9464
9465 if err := MarshalEncode(enc, map[string]int{"\xde\xad\xbe\xef": 0}); err == nil {
9466 t.Fatal("MarshalEncode error is nil, want non-nil")
9467 }
9468
9469 var serr *jsontext.SyntacticError
9470 if err := MarshalEncode(enc, 0); !errors.As(err, &serr) || serr.Err == nil {
9471 t.Fatalf("MarshalEncode error = %v, want *jsontext.SyntacticError wrapping a non-nil error", err)
9472 }
9473 }
9474
9475 func TestUnmarshalInvalidNamespace(t *testing.T) {
9476 tests := []struct {
9477 name jsontest.CaseName
9478 val any
9479 }{
9480 {jsontest.Name("Map"), new(map[string]int{})},
9481 {jsontest.Name("Struct"), new(struct{ X int }{})},
9482 }
9483 for _, tt := range tests {
9484 t.Run(tt.name.Name, func(t *testing.T) {
9485 dec := jsontext.NewDecoder(strings.NewReader(`{"X":""}`))
9486 if err := UnmarshalDecode(dec, tt.val); err == nil {
9487 t.Fatalf("%s: UnmarshalDecode error is nil, want non-nil", tt.name.Where)
9488 }
9489 if _, err := dec.ReadToken(); err == nil {
9490 t.Fatalf("%s: ReadToken error is nil, want non-nil", tt.name.Where)
9491 }
9492 if _, err := dec.ReadValue(); err == nil {
9493 t.Fatalf("%s: ReadValue error is nil, want non-nil", tt.name.Where)
9494 }
9495 })
9496 }
9497 }
9498
9499 func TestUnmarshalReuse(t *testing.T) {
9500 t.Run("Bytes", func(t *testing.T) {
9501 in := make([]byte, 3)
9502 want := &in[0]
9503 if err := Unmarshal([]byte(`"AQID"`), &in); err != nil {
9504 t.Fatalf("Unmarshal error: %v", err)
9505 }
9506 got := &in[0]
9507 if got != want {
9508 t.Errorf("input buffer was not reused")
9509 }
9510 })
9511 t.Run("Slices", func(t *testing.T) {
9512 in := make([]int, 3)
9513 want := &in[0]
9514 if err := Unmarshal([]byte(`[0,1,2]`), &in); err != nil {
9515 t.Fatalf("Unmarshal error: %v", err)
9516 }
9517 got := &in[0]
9518 if got != want {
9519 t.Errorf("input slice was not reused")
9520 }
9521 })
9522 t.Run("Maps", func(t *testing.T) {
9523 in := make(map[string]string)
9524 want := reflect.ValueOf(in).Pointer()
9525 if err := Unmarshal([]byte(`{"key":"value"}`), &in); err != nil {
9526 t.Fatalf("Unmarshal error: %v", err)
9527 }
9528 got := reflect.ValueOf(in).Pointer()
9529 if got != want {
9530 t.Errorf("input map was not reused")
9531 }
9532 })
9533 t.Run("Pointers", func(t *testing.T) {
9534 in := new(new(new("hello")))
9535 want := **in
9536 if err := Unmarshal([]byte(`"goodbye"`), &in); err != nil {
9537 t.Fatalf("Unmarshal error: %v", err)
9538 }
9539 got := **in
9540 if got != want {
9541 t.Errorf("input pointer was not reused")
9542 }
9543 })
9544 }
9545
9546 type unmarshalerEOF struct{}
9547
9548 func (unmarshalerEOF) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
9549 return io.EOF
9550 }
9551
9552
9553
9554 func TestUnmarshalEOF(t *testing.T) {
9555 opts := WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ *struct{}) error {
9556 return io.EOF
9557 }))
9558
9559 for _, in := range []string{"", "[", "[null", "[null]"} {
9560 for _, newOut := range []func() any{
9561 func() any { return new(unmarshalerEOF) },
9562 func() any { return new([]unmarshalerEOF) },
9563 func() any { return new(struct{}) },
9564 func() any { return new([]struct{}) },
9565 } {
9566 wantErr := io.ErrUnexpectedEOF
9567 if gotErr := Unmarshal([]byte(in), newOut(), opts); !errors.Is(gotErr, wantErr) {
9568 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9569 }
9570 if gotErr := UnmarshalRead(strings.NewReader(in), newOut(), opts); !errors.Is(gotErr, wantErr) {
9571 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9572 }
9573 switch gotErr := UnmarshalDecode(jsontext.NewDecoder(strings.NewReader(in)), newOut(), opts); {
9574 case in != "" && !errors.Is(gotErr, wantErr):
9575 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9576 case in == "" && gotErr != io.EOF:
9577 t.Errorf("Unmarshal = %v, want %v", gotErr, io.EOF)
9578 }
9579 }
9580 }
9581 }
9582
9583 type ReaderFunc func([]byte) (int, error)
9584
9585 func (f ReaderFunc) Read(b []byte) (int, error) { return f(b) }
9586
9587 type WriterFunc func([]byte) (int, error)
9588
9589 func (f WriterFunc) Write(b []byte) (int, error) { return f(b) }
9590
9591 func TestCoderBufferGrowth(t *testing.T) {
9592
9593
9594 checkGrowth := func(ns []int) {
9595 t.Helper()
9596 var sumBytes, sumRates, numGrows float64
9597 prev := ns[0]
9598 for i := 1; i < len(ns)-1; i++ {
9599 n := ns[i]
9600 if n != prev {
9601 sumRates += float64(n) / float64(prev)
9602 numGrows++
9603 prev = n
9604 }
9605 if n > 1<<20 {
9606 t.Fatalf("single Read/Write too large: %d", n)
9607 }
9608 sumBytes += float64(n)
9609 }
9610 if mean := sumBytes / float64(len(ns)); mean < 1<<10 {
9611 t.Fatalf("average Read/Write too small: %0.1f", mean)
9612 }
9613 switch mean := sumRates / numGrows; {
9614 case mean < 1.25:
9615 t.Fatalf("average growth rate too slow: %0.3f", mean)
9616 case mean > 2.00:
9617 t.Fatalf("average growth rate too fast: %0.3f", mean)
9618 }
9619 }
9620
9621
9622
9623 bb := struct{ *bytes.Buffer }{new(bytes.Buffer)}
9624
9625 var writeSizes []int
9626 if err := MarshalWrite(WriterFunc(func(b []byte) (int, error) {
9627 n, err := bb.Write(b)
9628 writeSizes = append(writeSizes, n)
9629 return n, err
9630 }), make([]struct{}, 1e6)); err != nil {
9631 t.Fatalf("MarshalWrite error: %v", err)
9632 }
9633 checkGrowth(writeSizes)
9634
9635 var readSizes []int
9636 if err := UnmarshalRead(ReaderFunc(func(b []byte) (int, error) {
9637 n, err := bb.Read(b)
9638 readSizes = append(readSizes, n)
9639 return n, err
9640 }), new([]struct{})); err != nil {
9641 t.Fatalf("UnmarshalRead error: %v", err)
9642 }
9643 checkGrowth(readSizes)
9644 }
9645
9646 func TestUintSet(t *testing.T) {
9647 type operation any
9648 type has struct {
9649 in uint
9650 want bool
9651 }
9652 type insert struct {
9653 in uint
9654 want bool
9655 }
9656
9657
9658 ops := []operation{
9659 has{0, false},
9660 has{63, false},
9661 has{64, false},
9662 has{1234, false},
9663 insert{3, true},
9664 has{2, false},
9665 has{3, true},
9666 has{4, false},
9667 has{63, false},
9668 insert{3, false},
9669 insert{63, true},
9670 has{63, true},
9671 insert{64, true},
9672 insert{64, false},
9673 has{64, true},
9674 insert{3264, true},
9675 has{3264, true},
9676 insert{3, false},
9677 has{3, true},
9678 }
9679
9680 var us uintSet
9681 for i, op := range ops {
9682 switch op := op.(type) {
9683 case has:
9684 if got := us.has(op.in); got != op.want {
9685 t.Fatalf("%d: uintSet.has(%v) = %v, want %v", i, op.in, got, op.want)
9686 }
9687 case insert:
9688 if got := us.insert(op.in); got != op.want {
9689 t.Fatalf("%d: uintSet.insert(%v) = %v, want %v", i, op.in, got, op.want)
9690 }
9691 default:
9692 panic(fmt.Sprintf("unknown operation: %T", op))
9693 }
9694 }
9695 }
9696
9697 func TestUnmarshalDecodeOptions(t *testing.T) {
9698 var calledFuncs int
9699 var calledOptions Options
9700 in := strings.NewReader(strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9701 dec := jsontext.NewDecoder(in,
9702 jsontext.AllowInvalidUTF8(true),
9703 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ any) error {
9704 opts := dec.Options()
9705 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9706 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9707 }
9708 calledFuncs++
9709 calledOptions = opts
9710 return errors.ErrUnsupported
9711 })),
9712 )
9713
9714 if err := UnmarshalDecode(dec, new(string)); err != nil {
9715 t.Fatalf("UnmarshalDecode: %v", err)
9716 }
9717 if calledFuncs != 1 {
9718 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9719 }
9720 if err := UnmarshalDecode(dec, new(string), calledOptions); err != nil {
9721 t.Fatalf("UnmarshalDecode: %v", err)
9722 }
9723 if calledFuncs != 2 {
9724 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9725 }
9726 if err := UnmarshalDecode(dec, new(string),
9727 jsontext.AllowInvalidUTF8(false),
9728 WithUnmarshalers(nil),
9729 ); !errors.Is(err, jsonwire.ErrInvalidUTF8) {
9730 t.Fatalf("UnmarshalDecode = %v, want %v", err, jsonwire.ErrInvalidUTF8)
9731 }
9732 if err := UnmarshalDecode(dec, new(string),
9733 WithUnmarshalers(nil),
9734 ); err != nil {
9735 t.Fatalf("UnmarshalDecode: %v", err)
9736 }
9737 if calledFuncs != 2 {
9738 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9739 }
9740 if err := UnmarshalDecode(dec, new(string)); err != nil {
9741 t.Fatalf("UnmarshalDecode: %v", err)
9742 }
9743 if calledFuncs != 3 {
9744 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9745 }
9746 if err := UnmarshalDecode(dec, new(string), JoinOptions(
9747 WithUnmarshalers(UnmarshalFromFunc(func(_ *jsontext.Decoder, _ any) error {
9748 opts := dec.Options()
9749 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9750 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9751 }
9752 calledFuncs = math.MaxInt
9753 return errors.ErrUnsupported
9754 })),
9755 )); err != nil {
9756 t.Fatalf("UnmarshalDecode: %v", err)
9757 }
9758 if calledFuncs != math.MaxInt {
9759 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9760 }
9761
9762
9763
9764 opts := dec.Options()
9765 dec.Reset(in, jsontext.AllowInvalidUTF8(false), opts)
9766 if v, _ := GetOption(dec.Options(), jsontext.AllowInvalidUTF8); v == false {
9767 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9768 }
9769
9770
9771
9772 {
9773 dec2 := jsontext.NewDecoder(strings.NewReader(`{"name":{"dupe":"value","dupe":"value"}}`))
9774 if tok, err := dec2.ReadToken(); tok.Kind() != '{' || err != nil {
9775 t.Fatalf("ReadToken = (%v, %v), want ('{', nil)", tok.Kind(), err)
9776 }
9777 var name string
9778 if err := UnmarshalDecode(dec2, &name, jsontext.AllowDuplicateNames(true)); !errors.Is(err, errChangingDuplicateNames) {
9779 t.Errorf("UnmarshalDecode(name) = %v, want %v", err, errChangingDuplicateNames)
9780 }
9781 if err := UnmarshalDecode(dec2, &name, jsontext.AllowInvalidUTF8(true)); !errors.Is(err, errChangingInvalidUTF8) {
9782 t.Errorf("UnmarshalDecode(name) = %v, want %v", err, errChangingInvalidUTF8)
9783 }
9784
9785 if err := UnmarshalDecode(dec2, &name, jsontext.AllowDuplicateNames(false)); err != nil {
9786 t.Errorf("UnmarshalDecode(name) = %v, want nil", err)
9787 } else if name != "name" {
9788 t.Errorf("UnmarshalDecode(name) = %q, want %q", name, "name")
9789 }
9790
9791 var value jsontext.Value
9792 if err := UnmarshalDecode(dec2, &value, jsontext.AllowDuplicateNames(true)); err != nil {
9793 t.Errorf("UnmarshalDecode(value) = %v, want nil", err)
9794 }
9795 const want = `{"dupe":"value","dupe":"value"}`
9796 if string(value) != string(want) {
9797 t.Errorf("UnmarshalDecode(value) = %s, want %s", value, want)
9798 }
9799 }
9800 }
9801
9802 func TestUnmarshalDecodeStream(t *testing.T) {
9803 tests := []struct {
9804 in string
9805 want []any
9806 err error
9807 }{
9808 {in: ``, err: io.EOF},
9809 {in: `{`, err: &jsontext.SyntacticError{ByteOffset: len64(`{`), Err: io.ErrUnexpectedEOF}},
9810 {in: `{"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"`), Err: io.ErrUnexpectedEOF}},
9811 {in: `{"k"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9812 {in: `{"k":`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k":`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9813 {in: `{"k",`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError(",", "after object name (expecting ':')")}},
9814 {in: `{"k"}`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError("}", "after object name (expecting ':')")}},
9815 {in: `[`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), Err: io.ErrUnexpectedEOF}},
9816 {in: `[0`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: io.ErrUnexpectedEOF}},
9817 {in: ` [0`, err: &jsontext.SyntacticError{ByteOffset: len64(` [0`), Err: io.ErrUnexpectedEOF}},
9818 {in: `[0.`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), JSONPointer: "/0", Err: io.ErrUnexpectedEOF}},
9819 {in: `[0. `, err: &jsontext.SyntacticError{ByteOffset: len64(`[0.`), JSONPointer: "/0", Err: jsonwire.NewInvalidCharacterError(" ", "in number (expecting digit)")}},
9820 {in: `[0,`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0,`), Err: io.ErrUnexpectedEOF}},
9821 {in: `[0:`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: jsonwire.NewInvalidCharacterError(":", "after array element (expecting ',' or ']')")}},
9822 {in: `n`, err: &jsontext.SyntacticError{ByteOffset: len64(`n`), Err: io.ErrUnexpectedEOF}},
9823 {in: `nul`, err: &jsontext.SyntacticError{ByteOffset: len64(`nul`), Err: io.ErrUnexpectedEOF}},
9824 {in: `fal `, err: &jsontext.SyntacticError{ByteOffset: len64(`fal`), Err: jsonwire.NewInvalidCharacterError(" ", "in literal false (expecting 's')")}},
9825 {in: `false`, want: []any{false}, err: io.EOF},
9826 {in: `false0.0[]null`, want: []any{false, 0.0, []any{}, nil}, err: io.EOF},
9827 }
9828 for _, tt := range tests {
9829 d := jsontext.NewDecoder(strings.NewReader(tt.in))
9830 var got []any
9831 for {
9832 var v any
9833 if err := UnmarshalDecode(d, &v); err != nil {
9834 if !reflect.DeepEqual(err, tt.err) {
9835 t.Errorf("`%s`: UnmarshalDecode error = %v, want %v", tt.in, err, tt.err)
9836 }
9837 break
9838 }
9839 got = append(got, v)
9840 }
9841 if !reflect.DeepEqual(got, tt.want) {
9842 t.Errorf("`%s`: UnmarshalDecode = %v, want %v", tt.in, got, tt.want)
9843 }
9844 }
9845 }
9846
9847
9848
9849 func BenchmarkUnmarshalDecodeOptions(b *testing.B) {
9850 var i int
9851 in := new(bytes.Buffer)
9852 dec := jsontext.NewDecoder(in)
9853 makeBench := func(opts ...Options) func(*testing.B) {
9854 return func(b *testing.B) {
9855 for range b.N {
9856 in.WriteString("0 ")
9857 }
9858 dec.Reset(in)
9859 b.ResetTimer()
9860 for range b.N {
9861 UnmarshalDecode(dec, &i, opts...)
9862 }
9863 }
9864 }
9865 b.Run("None", makeBench())
9866 b.Run("Same", makeBench(&export.Decoder(dec).Struct))
9867 b.Run("New", makeBench(DefaultOptionsV2()))
9868 }
9869
9870 func TestMarshalEncodeOptions(t *testing.T) {
9871 var calledFuncs int
9872 var calledOptions Options
9873 out := new(bytes.Buffer)
9874 enc := jsontext.NewEncoder(
9875 out,
9876 jsontext.AllowInvalidUTF8(true),
9877 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9878 opts := enc.Options()
9879 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9880 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9881 }
9882 calledFuncs++
9883 calledOptions = opts
9884 return errors.ErrUnsupported
9885 })),
9886 )
9887
9888 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9889 t.Fatalf("MarshalEncode: %v", err)
9890 }
9891 if calledFuncs != 1 {
9892 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9893 }
9894 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", calledOptions); err != nil {
9895 t.Fatalf("MarshalEncode: %v", err)
9896 }
9897 if calledFuncs != 2 {
9898 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9899 }
9900 if err := MarshalEncode(enc, "\xde\xad\xbe\xef",
9901 jsontext.AllowInvalidUTF8(false),
9902 WithMarshalers(nil),
9903 ); !errors.Is(err, jsonwire.ErrInvalidUTF8) {
9904 t.Fatalf("MarshalEncode = %v, want %v", err, jsonwire.ErrInvalidUTF8)
9905 }
9906 if err := MarshalEncode(enc, "\xde\xad\xbe\xef",
9907 WithMarshalers(nil),
9908 ); err != nil {
9909 t.Fatalf("MarshalEncode: %v", err)
9910 }
9911 if calledFuncs != 2 {
9912 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9913 }
9914 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9915 t.Fatalf("MarshalEncode: %v", err)
9916 }
9917 if calledFuncs != 3 {
9918 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9919 }
9920 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", JoinOptions(
9921 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9922 opts := enc.Options()
9923 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9924 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9925 }
9926 calledFuncs = math.MaxInt
9927 return errors.ErrUnsupported
9928 })),
9929 )); err != nil {
9930 t.Fatalf("MarshalEncode: %v", err)
9931 }
9932 if calledFuncs != math.MaxInt {
9933 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9934 }
9935 if out.String() != strings.Repeat("\"\xde\xad\ufffd\ufffd\"\n", 5) {
9936 t.Fatalf("output mismatch:\n\tgot: %s\n\twant: %s", out.String(), strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9937 }
9938
9939
9940
9941 opts := enc.Options()
9942 enc.Reset(out, jsontext.AllowInvalidUTF8(false), opts)
9943 if v, _ := GetOption(enc.Options(), jsontext.AllowInvalidUTF8); v == false {
9944 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9945 }
9946
9947
9948
9949 {
9950 var buf2 bytes.Buffer
9951 enc2 := jsontext.NewEncoder(&buf2)
9952 if err := enc2.WriteToken(jsontext.BeginObject); err != nil {
9953 t.Fatalf("WriteToken(BeginObject) = %v, want nil", err)
9954 }
9955
9956
9957 if err := MarshalEncode(enc2, "name", jsontext.AllowDuplicateNames(true)); !errors.Is(err, errChangingDuplicateNames) {
9958 t.Errorf("MarshalEncode(name) = %v, want %v", err, errChangingDuplicateNames)
9959 }
9960 if err := MarshalEncode(enc2, "name", jsontext.AllowInvalidUTF8(true)); !errors.Is(err, errChangingInvalidUTF8) {
9961 t.Errorf("MarshalEncode(name) = %v, want %v", err, errChangingInvalidUTF8)
9962 }
9963
9964 if err := MarshalEncode(enc2, "name", jsontext.AllowDuplicateNames(false)); err != nil {
9965 t.Errorf("MarshalEncode(name) = %v, want nil", err)
9966 }
9967
9968 if err := MarshalEncode(enc2, jsontext.Value(`{"dupe":"value","dupe":"value"}`), jsontext.AllowDuplicateNames(true)); err != nil {
9969 t.Errorf("MarshalEncode(value) = %v, want nil", err)
9970 }
9971
9972
9973 if err := MarshalEncode(enc2, "name2"); err != nil {
9974 t.Errorf("MarshalEncode(name) = %v, want nil", err)
9975 }
9976 if err := MarshalEncode(enc2, "value\xde\xad\xbe\xef"); !errors.Is(err, jsonwire.ErrInvalidUTF8) {
9977 t.Errorf("MarshalEncode(value) = %v, want %v", err, jsonwire.ErrInvalidUTF8)
9978 }
9979 if err := MarshalEncode(enc2, "value\xde\xad\xbe\xef", jsontext.AllowInvalidUTF8(true)); err != nil {
9980 t.Errorf("MarshalEncode(value) = %v, want nil", err)
9981 }
9982
9983 if err := enc2.WriteToken(jsontext.EndObject); err != nil {
9984 t.Errorf("WriteToken(EndObject) = %v, want nil", err)
9985 }
9986 }
9987
9988
9989
9990 {
9991 var buf3 bytes.Buffer
9992 enc3 := jsontext.NewEncoder(&buf3, jsontext.WithIndent("\t"))
9993 if err := MarshalEncode(enc3, "value", jsontext.Multiline(false)); !errors.Is(err, errChangingWhitespace) {
9994 t.Errorf("MarshalEncode = %v, want %v", err, errChangingWhitespace)
9995 }
9996 if err := MarshalEncode(enc3, "value", jsontext.WithIndent(" ")); !errors.Is(err, errChangingWhitespace) {
9997 t.Errorf("MarshalEncode = %v, want %v", err, errChangingWhitespace)
9998 }
9999
10000 if err := MarshalEncode(enc3, "value", enc3.Options()); err != nil {
10001 t.Errorf("MarshalEncode = %v, want nil", err)
10002 }
10003 }
10004 }
10005
10006
10007
10008 func BenchmarkMarshalEncodeOptions(b *testing.B) {
10009 var i int
10010 out := new(bytes.Buffer)
10011 enc := jsontext.NewEncoder(out)
10012 makeBench := func(opts ...Options) func(*testing.B) {
10013 return func(b *testing.B) {
10014 out.Reset()
10015 enc.Reset(out)
10016 b.ResetTimer()
10017 for range b.N {
10018 MarshalEncode(enc, &i, opts...)
10019 }
10020 }
10021 }
10022 b.Run("None", makeBench())
10023 b.Run("Same", makeBench(&export.Encoder(enc).Struct))
10024 b.Run("New", makeBench(DefaultOptionsV2()))
10025 }
10026
10027 func TestNilPanic(t *testing.T) {
10028 checkPanic := func(name string, want any, f func()) {
10029 t.Run(name, func(t *testing.T) {
10030 defer func() {
10031 got := recover()
10032 if got != want {
10033 t.Errorf("panic: got %v, want %v", got, want)
10034 }
10035 }()
10036 f()
10037 })
10038 }
10039
10040 checkPanic("MarshalWrite", "nil io.Writer", func() { MarshalWrite(nil, new(any)) })
10041 checkPanic("MarshalEncode", "nil jsontext.Encoder", func() { MarshalEncode(nil, new(any)) })
10042 checkPanic("UnmarshalRead", "nil io.Reader", func() { UnmarshalRead(nil, new(any)) })
10043 checkPanic("UnmarshalDecode", "nil jsontext.Decoder", func() { UnmarshalDecode(nil, new(any)) })
10044 }
10045
View as plain text