1
2
3
4
5
6
7 package json
8
9 import (
10 "bytes"
11 "encoding"
12 "encoding/base32"
13 "encoding/base64"
14 "encoding/hex"
15 "errors"
16 "fmt"
17 "io"
18 "math"
19 "net"
20 "net/netip"
21 "reflect"
22 "strconv"
23 "strings"
24 "testing"
25 "time"
26
27 "encoding/json/internal"
28 "encoding/json/internal/jsonflags"
29 "encoding/json/internal/jsonopts"
30 "encoding/json/internal/jsontest"
31 "encoding/json/internal/jsonwire"
32 "encoding/json/jsontext"
33 )
34
35 func newNonStringNameError(offset int64, pointer jsontext.Pointer) error {
36 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsontext.ErrNonStringName}
37 }
38
39 func newInvalidCharacterError(prefix, where string, offset int64, pointer jsontext.Pointer) error {
40 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.NewInvalidCharacterError(prefix, where)}
41 }
42
43 func newInvalidUTF8Error(offset int64, pointer jsontext.Pointer) error {
44 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.ErrInvalidUTF8}
45 }
46
47 func newParseTimeError(layout, value, layoutElem, valueElem, message string) error {
48 return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message}
49 }
50
51 func EM(err error) *SemanticError {
52 return &SemanticError{action: "marshal", Err: err}
53 }
54
55 func EU(err error) *SemanticError {
56 return &SemanticError{action: "unmarshal", Err: err}
57 }
58
59 func (e *SemanticError) withVal(val string) *SemanticError {
60 e.JSONValue = jsontext.Value(val)
61 return e
62 }
63
64 func (e *SemanticError) withPos(prefix string, pointer jsontext.Pointer) *SemanticError {
65 e.ByteOffset = int64(len(prefix))
66 e.JSONPointer = pointer
67 return e
68 }
69
70 func (e *SemanticError) withType(k jsontext.Kind, t reflect.Type) *SemanticError {
71 e.JSONKind = k
72 e.GoType = t
73 return e
74 }
75
76 var (
77 errInvalidFormatFlag = errors.New(`invalid format flag "invalid"`)
78 errSomeError = errors.New("some error")
79 errMustNotCall = errors.New("must not call")
80 )
81
82 func T[T any]() reflect.Type { return reflect.TypeFor[T]() }
83
84 type (
85 jsonObject = map[string]any
86 jsonArray = []any
87
88 namedAny any
89 namedBool bool
90 namedString string
91 NamedString string
92 namedBytes []byte
93 namedInt64 int64
94 namedUint64 uint64
95 namedFloat64 float64
96 namedByte byte
97 netipAddr = netip.Addr
98
99 recursiveMap map[string]recursiveMap
100 recursiveSlice []recursiveSlice
101 recursivePointer struct{ P *recursivePointer }
102
103 structEmpty struct{}
104 structConflicting struct {
105 A string `json:"conflict"`
106 B string `json:"conflict"`
107 }
108 structNoneExported struct {
109 unexported string
110 }
111 structUnexportedIgnored struct {
112 ignored string `json:"-"`
113 }
114 structMalformedTag struct {
115 Malformed string `json:"\""`
116 }
117 structUnexportedTag struct {
118 unexported string `json:"name"`
119 }
120 structExportedEmbedded struct {
121 NamedString
122 }
123 structExportedEmbeddedTag struct {
124 NamedString `json:"name"`
125 }
126 structUnexportedEmbedded struct {
127 namedString
128 }
129 structUnexportedEmbeddedTag struct {
130 namedString `json:"name"`
131 }
132 structUnexportedEmbeddedMethodTag struct {
133
134
135 netipAddr `json:"name"`
136
137
138
139
140 }
141 structUnexportedEmbeddedStruct struct {
142 structOmitZeroAll
143 FizzBuzz int
144 structNestedAddr
145 }
146 structUnexportedEmbeddedStructPointer struct {
147 *structOmitZeroAll
148 FizzBuzz int
149 *structNestedAddr
150 }
151 structNestedAddr struct {
152 Addr netip.Addr
153 }
154 structIgnoredUnexportedEmbedded struct {
155 namedString `json:"-"`
156 }
157 structWeirdNames struct {
158 Empty string `json:"''"`
159 Comma string `json:"','"`
160 Quote string `json:"'\"'"`
161 }
162 structNoCase struct {
163 Aaa string `json:",case:strict"`
164 AA_A string
165 AaA string `json:",case:ignore"`
166 AAa string `json:",case:ignore"`
167 AAA string
168 }
169 structScalars struct {
170 unexported bool
171 Ignored bool `json:"-"`
172
173 Bool bool
174 String string
175 Bytes []byte
176 Int int64
177 Uint uint64
178 Float float64
179 }
180 structSlices struct {
181 unexported bool
182 Ignored bool `json:"-"`
183
184 SliceBool []bool
185 SliceString []string
186 SliceBytes [][]byte
187 SliceInt []int64
188 SliceUint []uint64
189 SliceFloat []float64
190 }
191 structMaps struct {
192 unexported bool
193 Ignored bool `json:"-"`
194
195 MapBool map[string]bool
196 MapString map[string]string
197 MapBytes map[string][]byte
198 MapInt map[string]int64
199 MapUint map[string]uint64
200 MapFloat map[string]float64
201 }
202 structAll struct {
203 Bool bool
204 String string
205 Bytes []byte
206 Int int64
207 Uint uint64
208 Float float64
209 Map map[string]string
210 StructScalars structScalars
211 StructMaps structMaps
212 StructSlices structSlices
213 Slice []string
214 Array [1]string
215 Pointer *structAll
216 Interface any
217 }
218 structStringifiedAll struct {
219 Bool bool `json:",string"`
220 String string `json:",string"`
221 Bytes []byte `json:",string"`
222 Int int64 `json:",string"`
223 Uint uint64 `json:",string"`
224 Float float64 `json:",string"`
225 Map map[string]string `json:",string"`
226 StructScalars structScalars `json:",string"`
227 StructMaps structMaps `json:",string"`
228 StructSlices structSlices `json:",string"`
229 Slice []string `json:",string"`
230 Array [1]string `json:",string"`
231 Pointer *structStringifiedAll `json:",string"`
232 Interface any `json:",string"`
233 }
234 structOmitZeroAll struct {
235 Bool bool `json:",omitzero"`
236 String string `json:",omitzero"`
237 Bytes []byte `json:",omitzero"`
238 Int int64 `json:",omitzero"`
239 Uint uint64 `json:",omitzero"`
240 Float float64 `json:",omitzero"`
241 Map map[string]string `json:",omitzero"`
242 StructScalars structScalars `json:",omitzero"`
243 StructMaps structMaps `json:",omitzero"`
244 StructSlices structSlices `json:",omitzero"`
245 Slice []string `json:",omitzero"`
246 Array [1]string `json:",omitzero"`
247 Pointer *structOmitZeroAll `json:",omitzero"`
248 Interface any `json:",omitzero"`
249 }
250 structOmitZeroMethodAll struct {
251 ValueAlwaysZero valueAlwaysZero `json:",omitzero"`
252 ValueNeverZero valueNeverZero `json:",omitzero"`
253 PointerAlwaysZero pointerAlwaysZero `json:",omitzero"`
254 PointerNeverZero pointerNeverZero `json:",omitzero"`
255 PointerValueAlwaysZero *valueAlwaysZero `json:",omitzero"`
256 PointerValueNeverZero *valueNeverZero `json:",omitzero"`
257 PointerPointerAlwaysZero *pointerAlwaysZero `json:",omitzero"`
258 PointerPointerNeverZero *pointerNeverZero `json:",omitzero"`
259 PointerPointerValueAlwaysZero **valueAlwaysZero `json:",omitzero"`
260 PointerPointerValueNeverZero **valueNeverZero `json:",omitzero"`
261 PointerPointerPointerAlwaysZero **pointerAlwaysZero `json:",omitzero"`
262 PointerPointerPointerNeverZero **pointerNeverZero `json:",omitzero"`
263 }
264 structOmitZeroMethodInterfaceAll struct {
265 ValueAlwaysZero isZeroer `json:",omitzero"`
266 ValueNeverZero isZeroer `json:",omitzero"`
267 PointerValueAlwaysZero isZeroer `json:",omitzero"`
268 PointerValueNeverZero isZeroer `json:",omitzero"`
269 PointerPointerAlwaysZero isZeroer `json:",omitzero"`
270 PointerPointerNeverZero isZeroer `json:",omitzero"`
271 }
272 structOmitEmptyAll struct {
273 Bool bool `json:",omitempty"`
274 PointerBool *bool `json:",omitempty"`
275 String string `json:",omitempty"`
276 StringEmpty stringMarshalEmpty `json:",omitempty"`
277 StringNonEmpty stringMarshalNonEmpty `json:",omitempty"`
278 PointerString *string `json:",omitempty"`
279 PointerStringEmpty *stringMarshalEmpty `json:",omitempty"`
280 PointerStringNonEmpty *stringMarshalNonEmpty `json:",omitempty"`
281 Bytes []byte `json:",omitempty"`
282 BytesEmpty bytesMarshalEmpty `json:",omitempty"`
283 BytesNonEmpty bytesMarshalNonEmpty `json:",omitempty"`
284 PointerBytes *[]byte `json:",omitempty"`
285 PointerBytesEmpty *bytesMarshalEmpty `json:",omitempty"`
286 PointerBytesNonEmpty *bytesMarshalNonEmpty `json:",omitempty"`
287 Float float64 `json:",omitempty"`
288 PointerFloat *float64 `json:",omitempty"`
289 Map map[string]string `json:",omitempty"`
290 MapEmpty mapMarshalEmpty `json:",omitempty"`
291 MapNonEmpty mapMarshalNonEmpty `json:",omitempty"`
292 PointerMap *map[string]string `json:",omitempty"`
293 PointerMapEmpty *mapMarshalEmpty `json:",omitempty"`
294 PointerMapNonEmpty *mapMarshalNonEmpty `json:",omitempty"`
295 Slice []string `json:",omitempty"`
296 SliceEmpty sliceMarshalEmpty `json:",omitempty"`
297 SliceNonEmpty sliceMarshalNonEmpty `json:",omitempty"`
298 PointerSlice *[]string `json:",omitempty"`
299 PointerSliceEmpty *sliceMarshalEmpty `json:",omitempty"`
300 PointerSliceNonEmpty *sliceMarshalNonEmpty `json:",omitempty"`
301 Pointer *structOmitZeroEmptyAll `json:",omitempty"`
302 Interface any `json:",omitempty"`
303 }
304 structOmitZeroEmptyAll struct {
305 Bool bool `json:",omitzero,omitempty"`
306 String string `json:",omitzero,omitempty"`
307 Bytes []byte `json:",omitzero,omitempty"`
308 Int int64 `json:",omitzero,omitempty"`
309 Uint uint64 `json:",omitzero,omitempty"`
310 Float float64 `json:",omitzero,omitempty"`
311 Map map[string]string `json:",omitzero,omitempty"`
312 Slice []string `json:",omitzero,omitempty"`
313 Array [1]string `json:",omitzero,omitempty"`
314 Pointer *structOmitZeroEmptyAll `json:",omitzero,omitempty"`
315 Interface any `json:",omitzero,omitempty"`
316 }
317 structFormatBytes struct {
318 Base16 []byte `json:",format:base16"`
319 Base32 []byte `json:",format:base32"`
320 Base32Hex []byte `json:",format:base32hex"`
321 Base64 []byte `json:",format:base64"`
322 Base64URL []byte `json:",format:base64url"`
323 Array []byte `json:",format:array"`
324 }
325 structFormatArrayBytes struct {
326 Base16 [4]byte `json:",format:base16"`
327 Base32 [4]byte `json:",format:base32"`
328 Base32Hex [4]byte `json:",format:base32hex"`
329 Base64 [4]byte `json:",format:base64"`
330 Base64URL [4]byte `json:",format:base64url"`
331 Array [4]byte `json:",format:array"`
332 Default [4]byte
333 }
334 structFormatFloats struct {
335 NonFinite float64 `json:",format:nonfinite"`
336 PointerNonFinite *float64 `json:",format:nonfinite"`
337 }
338 structFormatMaps struct {
339 EmitNull map[string]string `json:",format:emitnull"`
340 PointerEmitNull *map[string]string `json:",format:emitnull"`
341 EmitEmpty map[string]string `json:",format:emitempty"`
342 PointerEmitEmpty *map[string]string `json:",format:emitempty"`
343 EmitDefault map[string]string
344 PointerEmitDefault *map[string]string
345 }
346 structFormatSlices struct {
347 EmitNull []string `json:",format:emitnull"`
348 PointerEmitNull *[]string `json:",format:emitnull"`
349 EmitEmpty []string `json:",format:emitempty"`
350 PointerEmitEmpty *[]string `json:",format:emitempty"`
351 EmitDefault []string
352 PointerEmitDefault *[]string
353 }
354 structFormatInvalid struct {
355 Bool bool `json:",omitzero,format:invalid"`
356 String string `json:",omitzero,format:invalid"`
357 Bytes []byte `json:",omitzero,format:invalid"`
358 Int int64 `json:",omitzero,format:invalid"`
359 Uint uint64 `json:",omitzero,format:invalid"`
360 Float float64 `json:",omitzero,format:invalid"`
361 Map map[string]string `json:",omitzero,format:invalid"`
362 Struct structAll `json:",omitzero,format:invalid"`
363 Slice []string `json:",omitzero,format:invalid"`
364 Array [1]string `json:",omitzero,format:invalid"`
365 Interface any `json:",omitzero,format:invalid"`
366 }
367 structDurationFormat struct {
368 D1 time.Duration `json:",format:units"`
369 D2 time.Duration `json:",format:units"`
370 D3 time.Duration `json:",format:sec"`
371 D4 time.Duration `json:",string,format:sec"`
372 D5 time.Duration `json:",format:milli"`
373 D6 time.Duration `json:",string,format:milli"`
374 D7 time.Duration `json:",format:micro"`
375 D8 time.Duration `json:",string,format:micro"`
376 D9 time.Duration `json:",format:nano"`
377 D10 time.Duration `json:",string,format:nano"`
378 D11 time.Duration `json:",format:iso8601"`
379 }
380 structTimeFormat struct {
381 T1 time.Time
382 T2 time.Time `json:",format:ANSIC"`
383 T3 time.Time `json:",format:UnixDate"`
384 T4 time.Time `json:",format:RubyDate"`
385 T5 time.Time `json:",format:RFC822"`
386 T6 time.Time `json:",format:RFC822Z"`
387 T7 time.Time `json:",format:RFC850"`
388 T8 time.Time `json:",format:RFC1123"`
389 T9 time.Time `json:",format:RFC1123Z"`
390 T10 time.Time `json:",format:RFC3339"`
391 T11 time.Time `json:",format:RFC3339Nano"`
392 T12 time.Time `json:",format:Kitchen"`
393 T13 time.Time `json:",format:Stamp"`
394 T14 time.Time `json:",format:StampMilli"`
395 T15 time.Time `json:",format:StampMicro"`
396 T16 time.Time `json:",format:StampNano"`
397 T17 time.Time `json:",format:DateTime"`
398 T18 time.Time `json:",format:DateOnly"`
399 T19 time.Time `json:",format:TimeOnly"`
400 T20 time.Time `json:",format:'2006-01-02'"`
401 T21 time.Time `json:",format:'\"weird\"2006'"`
402 T22 time.Time `json:",format:unix"`
403 T23 time.Time `json:",string,format:unix"`
404 T24 time.Time `json:",format:unixmilli"`
405 T25 time.Time `json:",string,format:unixmilli"`
406 T26 time.Time `json:",format:unixmicro"`
407 T27 time.Time `json:",string,format:unixmicro"`
408 T28 time.Time `json:",format:unixnano"`
409 T29 time.Time `json:",string,format:unixnano"`
410 }
411 structInlined struct {
412 X structInlinedL1 `json:",inline"`
413 *StructEmbed2
414 }
415 structInlinedL1 struct {
416 X *structInlinedL2 `json:",inline"`
417 StructEmbed1 `json:",inline"`
418 }
419 structInlinedL2 struct{ A, B, C string }
420 StructEmbed1 struct{ C, D, E string }
421 StructEmbed2 struct{ E, F, G string }
422 structInlineTextValue struct {
423 A int `json:",omitzero"`
424 X jsontext.Value `json:",inline"`
425 B int `json:",omitzero"`
426 }
427 structInlinePointerTextValue struct {
428 A int `json:",omitzero"`
429 X *jsontext.Value `json:",inline"`
430 B int `json:",omitzero"`
431 }
432 structInlinePointerInlineTextValue struct {
433 X *struct {
434 A int
435 X jsontext.Value `json:",inline"`
436 } `json:",inline"`
437 }
438 structInlineInlinePointerTextValue struct {
439 X struct {
440 X *jsontext.Value `json:",inline"`
441 } `json:",inline"`
442 }
443 structInlineMapStringAny struct {
444 A int `json:",omitzero"`
445 X jsonObject `json:",inline"`
446 B int `json:",omitzero"`
447 }
448 structInlinePointerMapStringAny struct {
449 A int `json:",omitzero"`
450 X *jsonObject `json:",inline"`
451 B int `json:",omitzero"`
452 }
453 structInlinePointerInlineMapStringAny struct {
454 X *struct {
455 A int
456 X jsonObject `json:",inline"`
457 } `json:",inline"`
458 }
459 structInlineInlinePointerMapStringAny struct {
460 X struct {
461 X *jsonObject `json:",inline"`
462 } `json:",inline"`
463 }
464 structInlineMapStringInt struct {
465 X map[string]int `json:",inline"`
466 }
467 structInlineMapNamedStringInt struct {
468 X map[namedString]int `json:",inline"`
469 }
470 structInlineMapNamedStringAny struct {
471 A int `json:",omitzero"`
472 X map[namedString]any `json:",inline"`
473 B int `json:",omitzero"`
474 }
475 structNoCaseInlineTextValue struct {
476 AAA string `json:",omitempty,case:strict"`
477 AA_b string `json:",omitempty"`
478 AaA string `json:",omitempty,case:ignore"`
479 AAa string `json:",omitempty,case:ignore"`
480 Aaa string `json:",omitempty"`
481 X jsontext.Value `json:",inline"`
482 }
483 structNoCaseInlineMapStringAny struct {
484 AAA string `json:",omitempty"`
485 AaA string `json:",omitempty,case:ignore"`
486 AAa string `json:",omitempty,case:ignore"`
487 Aaa string `json:",omitempty"`
488 X jsonObject `json:",inline"`
489 }
490
491 allMethods struct {
492 method string
493 value []byte
494 }
495 allMethodsExceptJSONv2 struct {
496 allMethods
497 MarshalJSONTo struct{}
498 UnmarshalJSONFrom struct{}
499 }
500 allMethodsExceptJSONv1 struct {
501 allMethods
502 MarshalJSON struct{}
503 UnmarshalJSON struct{}
504 }
505 allMethodsExceptText struct {
506 allMethods
507 MarshalText struct{}
508 UnmarshalText struct{}
509 }
510 onlyMethodJSONv2 struct {
511 allMethods
512 MarshalJSON struct{}
513 UnmarshalJSON struct{}
514 MarshalText struct{}
515 UnmarshalText struct{}
516 }
517 onlyMethodJSONv1 struct {
518 allMethods
519 MarshalJSONTo struct{}
520 UnmarshalJSONFrom struct{}
521 MarshalText struct{}
522 UnmarshalText struct{}
523 }
524 onlyMethodText struct {
525 allMethods
526 MarshalJSONTo struct{}
527 UnmarshalJSONFrom struct{}
528 MarshalJSON struct{}
529 UnmarshalJSON struct{}
530 }
531
532 unsupportedMethodJSONv2 map[string]int
533
534 structMethodJSONv2 struct{ value string }
535 structMethodJSONv1 struct{ value string }
536 structMethodText struct{ value string }
537
538 marshalJSONv2Func func(*jsontext.Encoder) error
539 marshalJSONv1Func func() ([]byte, error)
540 appendTextFunc func([]byte) ([]byte, error)
541 marshalTextFunc func() ([]byte, error)
542 unmarshalJSONv2Func func(*jsontext.Decoder) error
543 unmarshalJSONv1Func func([]byte) error
544 unmarshalTextFunc func([]byte) error
545
546 nocaseString string
547
548 stringMarshalEmpty string
549 stringMarshalNonEmpty string
550 bytesMarshalEmpty []byte
551 bytesMarshalNonEmpty []byte
552 mapMarshalEmpty map[string]string
553 mapMarshalNonEmpty map[string]string
554 sliceMarshalEmpty []string
555 sliceMarshalNonEmpty []string
556
557 valueAlwaysZero string
558 valueNeverZero string
559 pointerAlwaysZero string
560 pointerNeverZero string
561
562 valueStringer struct{}
563 pointerStringer struct{}
564
565 cyclicA struct {
566 B1 cyclicB `json:",inline"`
567 B2 cyclicB `json:",inline"`
568 }
569 cyclicB struct {
570 F int
571 A *cyclicA `json:",inline"`
572 }
573 )
574
575 func (structUnexportedEmbeddedMethodTag) MarshalText() {}
576 func (structUnexportedEmbeddedMethodTag) AppendText() {}
577
578 func (p *allMethods) MarshalJSONTo(enc *jsontext.Encoder) error {
579 if got, want := "MarshalJSONTo", p.method; got != want {
580 return fmt.Errorf("called wrong method: got %v, want %v", got, want)
581 }
582 return enc.WriteValue(p.value)
583 }
584 func (p *allMethods) MarshalJSON() ([]byte, error) {
585 if got, want := "MarshalJSON", p.method; got != want {
586 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
587 }
588 return p.value, nil
589 }
590 func (p *allMethods) MarshalText() ([]byte, error) {
591 if got, want := "MarshalText", p.method; got != want {
592 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
593 }
594 return p.value, nil
595 }
596
597 func (p *allMethods) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
598 p.method = "UnmarshalJSONFrom"
599 val, err := dec.ReadValue()
600 p.value = val
601 return err
602 }
603 func (p *allMethods) UnmarshalJSON(val []byte) error {
604 p.method = "UnmarshalJSON"
605 p.value = val
606 return nil
607 }
608 func (p *allMethods) UnmarshalText(val []byte) error {
609 p.method = "UnmarshalText"
610 p.value = val
611 return nil
612 }
613
614 func (s *unsupportedMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
615 (*s)["called"] += 1
616 return errors.ErrUnsupported
617 }
618 func (s *unsupportedMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
619 (*s)["called"] += 1
620 return errors.ErrUnsupported
621 }
622
623 func (s structMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
624 return enc.WriteToken(jsontext.String(s.value))
625 }
626 func (s *structMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
627 tok, err := dec.ReadToken()
628 if err != nil {
629 return err
630 }
631 if k := tok.Kind(); k != '"' {
632 return EU(nil).withType(k, T[structMethodJSONv2]())
633 }
634 s.value = tok.String()
635 return nil
636 }
637
638 func (s structMethodJSONv1) MarshalJSON() ([]byte, error) {
639 return jsontext.AppendQuote(nil, s.value)
640 }
641 func (s *structMethodJSONv1) UnmarshalJSON(b []byte) error {
642 if k := jsontext.Value(b).Kind(); k != '"' {
643 return EU(nil).withType(k, T[structMethodJSONv1]())
644 }
645 b, _ = jsontext.AppendUnquote(nil, b)
646 s.value = string(b)
647 return nil
648 }
649
650 func (s structMethodText) MarshalText() ([]byte, error) {
651 return []byte(s.value), nil
652 }
653 func (s *structMethodText) UnmarshalText(b []byte) error {
654 s.value = string(b)
655 return nil
656 }
657
658 func (f marshalJSONv2Func) MarshalJSONTo(enc *jsontext.Encoder) error {
659 return f(enc)
660 }
661 func (f marshalJSONv1Func) MarshalJSON() ([]byte, error) {
662 return f()
663 }
664 func (f appendTextFunc) AppendText(b []byte) ([]byte, error) {
665 return f(b)
666 }
667 func (f marshalTextFunc) MarshalText() ([]byte, error) {
668 return f()
669 }
670 func (f unmarshalJSONv2Func) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
671 return f(dec)
672 }
673 func (f unmarshalJSONv1Func) UnmarshalJSON(b []byte) error {
674 return f(b)
675 }
676 func (f unmarshalTextFunc) UnmarshalText(b []byte) error {
677 return f(b)
678 }
679
680 func (k nocaseString) MarshalText() ([]byte, error) {
681 return []byte(strings.ToLower(string(k))), nil
682 }
683 func (k *nocaseString) UnmarshalText(b []byte) error {
684 *k = nocaseString(strings.ToLower(string(b)))
685 return nil
686 }
687
688 func (stringMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`""`), nil }
689 func (stringMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`"value"`), nil }
690 func (bytesMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
691 func (bytesMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
692 func (mapMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`{}`), nil }
693 func (mapMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`{"key":"value"}`), nil }
694 func (sliceMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
695 func (sliceMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
696
697 func (valueAlwaysZero) IsZero() bool { return true }
698 func (valueNeverZero) IsZero() bool { return false }
699 func (*pointerAlwaysZero) IsZero() bool { return true }
700 func (*pointerNeverZero) IsZero() bool { return false }
701
702 func (valueStringer) String() string { return "" }
703 func (*pointerStringer) String() string { return "" }
704
705 func addr[T any](v T) *T {
706 return &v
707 }
708
709 func mustParseTime(layout, value string) time.Time {
710 t, err := time.Parse(layout, value)
711 if err != nil {
712 panic(err)
713 }
714 return t
715 }
716
717 var invalidFormatOption = &jsonopts.Struct{
718 ArshalValues: jsonopts.ArshalValues{FormatDepth: 1000, Format: "invalid"},
719 }
720
721 func TestMarshal(t *testing.T) {
722 tests := []struct {
723 name jsontest.CaseName
724 opts []Options
725 in any
726 want string
727 wantErr error
728
729 canonicalize bool
730 useWriter bool
731 }{{
732 name: jsontest.Name("Nil"),
733 in: nil,
734 want: `null`,
735 }, {
736 name: jsontest.Name("Bools"),
737 in: []bool{false, true},
738 want: `[false,true]`,
739 }, {
740 name: jsontest.Name("Bools/Named"),
741 in: []namedBool{false, true},
742 want: `[false,true]`,
743 }, {
744 name: jsontest.Name("Bools/NotStringified"),
745 opts: []Options{StringifyNumbers(true)},
746 in: []bool{false, true},
747 want: `[false,true]`,
748 }, {
749 name: jsontest.Name("Bools/StringifiedBool"),
750 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
751 in: []bool{false, true},
752 want: `["false","true"]`,
753 }, {
754 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
755 opts: []Options{invalidFormatOption},
756 in: true,
757 want: `true`,
758 }, {
759 name: jsontest.Name("Strings"),
760 in: []string{"", "hello", "世界"},
761 want: `["","hello","世界"]`,
762 }, {
763 name: jsontest.Name("Strings/Named"),
764 in: []namedString{"", "hello", "世界"},
765 want: `["","hello","世界"]`,
766 }, {
767 name: jsontest.Name("Strings/StringifiedBool"),
768 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
769 in: []string{"", "hello", "世界"},
770 want: `["\"\"","\"hello\"","\"世界\""]`,
771 }, {
772 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
773 opts: []Options{invalidFormatOption},
774 in: "string",
775 want: `"string"`,
776 }, {
777 name: jsontest.Name("Bytes"),
778 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
779 want: `["","","AQ==","AQI=","AQID"]`,
780 }, {
781 name: jsontest.Name("Bytes/FormatNilSliceAsNull"),
782 opts: []Options{FormatNilSliceAsNull(true)},
783 in: [][]byte{nil, {}},
784 want: `[null,""]`,
785 }, {
786 name: jsontest.Name("Bytes/Large"),
787 in: []byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on."),
788 want: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
789 }, {
790 name: jsontest.Name("Bytes/Named"),
791 in: []namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}},
792 want: `["","","AQ==","AQI=","AQID"]`,
793 }, {
794 name: jsontest.Name("Bytes/NotStringified"),
795 opts: []Options{StringifyNumbers(true)},
796 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
797 want: `["","","AQ==","AQI=","AQID"]`,
798 }, {
799
800
801 name: jsontest.Name("Bytes/Invariant"),
802 in: [][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
803 want: `[[],[],[1],[1,2],[1,2,3]]`,
804 }, {
805
806
807 name: jsontest.Name("Bytes/ByteArray"),
808 in: [5]byte{'h', 'e', 'l', 'l', 'o'},
809 want: `"aGVsbG8="`,
810 }, {
811
812
813 name: jsontest.Name("Bytes/NamedByteArray"),
814 in: [5]namedByte{'h', 'e', 'l', 'l', 'o'},
815 want: `[104,101,108,108,111]`,
816 }, {
817 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
818 opts: []Options{invalidFormatOption},
819 in: []byte("hello"),
820 want: `"aGVsbG8="`,
821 }, {
822 name: jsontest.Name("Ints"),
823 in: []any{
824 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
825 },
826 want: `[0,-128,-32768,-2147483648,-9223372036854775808,-6464]`,
827 }, {
828 name: jsontest.Name("Ints/Stringified"),
829 opts: []Options{StringifyNumbers(true)},
830 in: []any{
831 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
832 },
833 want: `["0","-128","-32768","-2147483648","-9223372036854775808","-6464"]`,
834 }, {
835 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
836 opts: []Options{invalidFormatOption},
837 in: int(0),
838 want: `0`,
839 }, {
840 name: jsontest.Name("Uints"),
841 in: []any{
842 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464), uintptr(1234),
843 },
844 want: `[0,255,65535,4294967295,18446744073709551615,6464,1234]`,
845 }, {
846 name: jsontest.Name("Uints/Stringified"),
847 opts: []Options{StringifyNumbers(true)},
848 in: []any{
849 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464),
850 },
851 want: `["0","255","65535","4294967295","18446744073709551615","6464"]`,
852 }, {
853 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
854 opts: []Options{invalidFormatOption},
855 in: uint(0),
856 want: `0`,
857 }, {
858 name: jsontest.Name("Floats"),
859 in: []any{
860 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
861 },
862 want: `[3.4028235e+38,1.7976931348623157e+308,64.64]`,
863 }, {
864 name: jsontest.Name("Floats/Stringified"),
865 opts: []Options{StringifyNumbers(true)},
866 in: []any{
867 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
868 },
869 want: `["3.4028235e+38","1.7976931348623157e+308","64.64"]`,
870 }, {
871 name: jsontest.Name("Floats/Invalid/NaN"),
872 opts: []Options{StringifyNumbers(true)},
873 in: math.NaN(),
874 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, float64Type),
875 }, {
876 name: jsontest.Name("Floats/Invalid/PositiveInfinity"),
877 in: math.Inf(+1),
878 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(+1))).withType(0, float64Type),
879 }, {
880 name: jsontest.Name("Floats/Invalid/NegativeInfinity"),
881 in: math.Inf(-1),
882 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(-1))).withType(0, float64Type),
883 }, {
884 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
885 opts: []Options{invalidFormatOption},
886 in: float64(0),
887 want: `0`,
888 }, {
889 name: jsontest.Name("Maps/InvalidKey/Bool"),
890 in: map[bool]string{false: "value"},
891 want: `{`,
892 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, boolType),
893 }, {
894 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
895 in: map[namedBool]string{false: "value"},
896 want: `{`,
897 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[namedBool]()),
898 }, {
899 name: jsontest.Name("Maps/InvalidKey/Array"),
900 in: map[[1]string]string{{"key"}: "value"},
901 want: `{`,
902 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[[1]string]()),
903 }, {
904 name: jsontest.Name("Maps/InvalidKey/Channel"),
905 in: map[chan string]string{make(chan string): "value"},
906 want: `{`,
907 wantErr: EM(nil).withPos(`{`, "").withType(0, T[chan string]()),
908 }, {
909 name: jsontest.Name("Maps/ValidKey/Int"),
910 in: map[int64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
911 canonicalize: true,
912 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
913 }, {
914 name: jsontest.Name("Maps/ValidKey/PointerInt"),
915 in: map[*int64]string{addr(int64(math.MinInt64)): "MinInt64", addr(int64(0)): "Zero", addr(int64(math.MaxInt64)): "MaxInt64"},
916 canonicalize: true,
917 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
918 }, {
919 name: jsontest.Name("Maps/DuplicateName/PointerInt"),
920 in: map[*int64]string{addr(int64(0)): "0", addr(int64(0)): "0"},
921 canonicalize: true,
922 want: `{"0":"0"`,
923 wantErr: newDuplicateNameError("", []byte(`"0"`), len64(`{"0":"0",`)),
924 }, {
925 name: jsontest.Name("Maps/ValidKey/NamedInt"),
926 in: map[namedInt64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
927 canonicalize: true,
928 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
929 }, {
930 name: jsontest.Name("Maps/ValidKey/Uint"),
931 in: map[uint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
932 canonicalize: true,
933 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
934 }, {
935 name: jsontest.Name("Maps/ValidKey/NamedUint"),
936 in: map[namedUint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
937 canonicalize: true,
938 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
939 }, {
940 name: jsontest.Name("Maps/ValidKey/Float"),
941 in: map[float64]string{3.14159: "value"},
942 want: `{"3.14159":"value"}`,
943 }, {
944 name: jsontest.Name("Maps/InvalidKey/Float/NaN"),
945 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
946 want: `{`,
947 wantErr: EM(errors.New("unsupported value: NaN")).withPos(`{`, "").withType(0, float64Type),
948 }, {
949 name: jsontest.Name("Maps/ValidKey/Interface"),
950 in: map[any]any{
951 "key": "key",
952 namedInt64(-64): int32(-32),
953 namedUint64(+64): uint32(+32),
954 namedFloat64(64.64): float32(32.32),
955 },
956 canonicalize: true,
957 want: `{"-64":-32,"64":32,"64.64":32.32,"key":"key"}`,
958 }, {
959 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8+AllowDuplicateNames"),
960 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
961 in: map[string]string{"\x80": "", "\x81": ""},
962 want: `{"�":"","�":""}`,
963 }, {
964 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8"),
965 opts: []Options{jsontext.AllowInvalidUTF8(true)},
966 in: map[string]string{"\x80": "", "\x81": ""},
967 want: `{"�":""`,
968 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":"",`)),
969 }, {
970 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
971 opts: []Options{jsontext.AllowDuplicateNames(true)},
972 in: map[nocaseString]string{"hello": "", "HELLO": ""},
973 want: `{"hello":"","hello":""}`,
974 }, {
975 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
976 in: map[nocaseString]string{"hello": "", "HELLO": ""},
977 want: `{"hello":""`,
978 wantErr: EM(newDuplicateNameError("", []byte(`"hello"`), len64(`{"hello":"",`))).withPos(`{"hello":"",`, "").withType(0, T[nocaseString]()),
979 }, {
980 name: jsontest.Name("Maps/DuplicateName/NaNs/Deterministic+AllowDuplicateNames"),
981 opts: []Options{
982 WithMarshalers(
983 MarshalFunc(func(v float64) ([]byte, error) { return []byte(`"NaN"`), nil }),
984 ),
985 Deterministic(true),
986 jsontext.AllowDuplicateNames(true),
987 },
988 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
989 want: `{"NaN":"NaN","NaN":"NaN"}`,
990 }, {
991 name: jsontest.Name("Maps/InvalidValue/Channel"),
992 in: map[string]chan string{
993 "key": nil,
994 },
995 want: `{"key"`,
996 wantErr: EM(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
997 }, {
998 name: jsontest.Name("Maps/String/Deterministic"),
999 opts: []Options{Deterministic(true)},
1000 in: map[string]int{"a": 0, "b": 1, "c": 2},
1001 want: `{"a":0,"b":1,"c":2}`,
1002 }, {
1003 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
1004 opts: []Options{
1005 Deterministic(true),
1006 jsontext.AllowInvalidUTF8(true),
1007 jsontext.AllowDuplicateNames(false),
1008 },
1009 in: map[string]int{"\xff": 0, "\xfe": 1},
1010 want: `{"�":1`,
1011 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1,`)),
1012 }, {
1013 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
1014 opts: []Options{
1015 Deterministic(true),
1016 jsontext.AllowInvalidUTF8(true),
1017 jsontext.AllowDuplicateNames(true),
1018 },
1019 in: map[string]int{"\xff": 0, "\xfe": 1},
1020 want: `{"�":1,"�":0}`,
1021 }, {
1022 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs"),
1023 opts: []Options{
1024 Deterministic(true),
1025 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1026 if p := enc.StackPointer(); p != "/X" {
1027 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1028 }
1029 switch v {
1030 case "a":
1031 return enc.WriteToken(jsontext.String("b"))
1032 case "b":
1033 return enc.WriteToken(jsontext.String("a"))
1034 default:
1035 return fmt.Errorf("invalid value: %q", v)
1036 }
1037 })),
1038 },
1039 in: map[namedString]map[string]int{"X": {"a": -1, "b": 1}},
1040 want: `{"X":{"a":1,"b":-1}}`,
1041 }, {
1042 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+RejectDuplicateNames"),
1043 opts: []Options{
1044 Deterministic(true),
1045 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1046 if p := enc.StackPointer(); p != "/X" {
1047 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1048 }
1049 switch v {
1050 case "a", "b":
1051 return enc.WriteToken(jsontext.String("x"))
1052 default:
1053 return fmt.Errorf("invalid value: %q", v)
1054 }
1055 })),
1056 jsontext.AllowDuplicateNames(false),
1057 },
1058 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1059 want: `{"X":{"x":1`,
1060 wantErr: newDuplicateNameError("/X/x", nil, len64(`{"X":{"x":1,`)),
1061 }, {
1062 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+AllowDuplicateNames"),
1063 opts: []Options{
1064 Deterministic(true),
1065 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1066 if p := enc.StackPointer(); p != "/X" {
1067 return fmt.Errorf("invalid stack pointer: got %s, want /0", p)
1068 }
1069 switch v {
1070 case "a", "b":
1071 return enc.WriteToken(jsontext.String("x"))
1072 default:
1073 return fmt.Errorf("invalid value: %q", v)
1074 }
1075 })),
1076 jsontext.AllowDuplicateNames(true),
1077 },
1078 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1079
1080
1081 want: `{"X":{"x":1,"x":1}}`,
1082 }, {
1083 name: jsontest.Name("Maps/RecursiveMap"),
1084 in: recursiveMap{
1085 "fizz": {
1086 "foo": {},
1087 "bar": nil,
1088 },
1089 "buzz": nil,
1090 },
1091 canonicalize: true,
1092 want: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
1093 }, {
1094 name: jsontest.Name("Maps/CyclicMap"),
1095 in: func() recursiveMap {
1096 m := recursiveMap{"k": nil}
1097 m["k"] = m
1098 return m
1099 }(),
1100 want: strings.Repeat(`{"k":`, startDetectingCyclesAfter) + `{"k"`,
1101 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"k":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/k", startDetectingCyclesAfter+1))).withType(0, T[recursiveMap]()),
1102 }, {
1103 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
1104 opts: []Options{invalidFormatOption},
1105 in: map[string]string{},
1106 want: `{}`,
1107 }, {
1108 name: jsontest.Name("Structs/Empty"),
1109 in: structEmpty{},
1110 want: `{}`,
1111 }, {
1112 name: jsontest.Name("Structs/UnexportedIgnored"),
1113 in: structUnexportedIgnored{ignored: "ignored"},
1114 want: `{}`,
1115 }, {
1116 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
1117 in: structIgnoredUnexportedEmbedded{namedString: "ignored"},
1118 want: `{}`,
1119 }, {
1120 name: jsontest.Name("Structs/WeirdNames"),
1121 in: structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"},
1122 want: `{"":"empty",",":"comma","\"":"quote"}`,
1123 }, {
1124 name: jsontest.Name("Structs/EscapedNames"),
1125 opts: []Options{jsontext.EscapeForHTML(true), jsontext.EscapeForJS(true)},
1126 in: struct {
1127 S string "json:\"'abc<>&\u2028\u2029xyz'\""
1128 M any
1129 I structInlineTextValue
1130 }{
1131 S: "abc<>&\u2028\u2029xyz",
1132 M: map[string]string{"abc<>&\u2028\u2029xyz": "abc<>&\u2028\u2029xyz"},
1133 I: structInlineTextValue{X: jsontext.Value(`{"abc<>&` + "\u2028\u2029" + `xyz":"abc<>&` + "\u2028\u2029" + `xyz"}`)},
1134 },
1135 want: `{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz","M":{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz"},"I":{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz"}}`,
1136 }, {
1137 name: jsontest.Name("Structs/NoCase"),
1138 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1139 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1140 }, {
1141 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames"),
1142 opts: []Options{MatchCaseInsensitiveNames(true)},
1143 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1144 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1145 }, {
1146 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
1147 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
1148 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1149 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1150 }, {
1151 name: jsontest.Name("Structs/Normal"),
1152 opts: []Options{jsontext.Multiline(true)},
1153 in: structAll{
1154 Bool: true,
1155 String: "hello",
1156 Bytes: []byte{1, 2, 3},
1157 Int: -64,
1158 Uint: +64,
1159 Float: 3.14159,
1160 Map: map[string]string{"key": "value"},
1161 StructScalars: structScalars{
1162 Bool: true,
1163 String: "hello",
1164 Bytes: []byte{1, 2, 3},
1165 Int: -64,
1166 Uint: +64,
1167 Float: 3.14159,
1168 },
1169 StructMaps: structMaps{
1170 MapBool: map[string]bool{"": true},
1171 MapString: map[string]string{"": "hello"},
1172 MapBytes: map[string][]byte{"": {1, 2, 3}},
1173 MapInt: map[string]int64{"": -64},
1174 MapUint: map[string]uint64{"": +64},
1175 MapFloat: map[string]float64{"": 3.14159},
1176 },
1177 StructSlices: structSlices{
1178 SliceBool: []bool{true},
1179 SliceString: []string{"hello"},
1180 SliceBytes: [][]byte{{1, 2, 3}},
1181 SliceInt: []int64{-64},
1182 SliceUint: []uint64{+64},
1183 SliceFloat: []float64{3.14159},
1184 },
1185 Slice: []string{"fizz", "buzz"},
1186 Array: [1]string{"goodbye"},
1187 Pointer: new(structAll),
1188 Interface: (*structAll)(nil),
1189 },
1190 want: `{
1191 "Bool": true,
1192 "String": "hello",
1193 "Bytes": "AQID",
1194 "Int": -64,
1195 "Uint": 64,
1196 "Float": 3.14159,
1197 "Map": {
1198 "key": "value"
1199 },
1200 "StructScalars": {
1201 "Bool": true,
1202 "String": "hello",
1203 "Bytes": "AQID",
1204 "Int": -64,
1205 "Uint": 64,
1206 "Float": 3.14159
1207 },
1208 "StructMaps": {
1209 "MapBool": {
1210 "": true
1211 },
1212 "MapString": {
1213 "": "hello"
1214 },
1215 "MapBytes": {
1216 "": "AQID"
1217 },
1218 "MapInt": {
1219 "": -64
1220 },
1221 "MapUint": {
1222 "": 64
1223 },
1224 "MapFloat": {
1225 "": 3.14159
1226 }
1227 },
1228 "StructSlices": {
1229 "SliceBool": [
1230 true
1231 ],
1232 "SliceString": [
1233 "hello"
1234 ],
1235 "SliceBytes": [
1236 "AQID"
1237 ],
1238 "SliceInt": [
1239 -64
1240 ],
1241 "SliceUint": [
1242 64
1243 ],
1244 "SliceFloat": [
1245 3.14159
1246 ]
1247 },
1248 "Slice": [
1249 "fizz",
1250 "buzz"
1251 ],
1252 "Array": [
1253 "goodbye"
1254 ],
1255 "Pointer": {
1256 "Bool": false,
1257 "String": "",
1258 "Bytes": "",
1259 "Int": 0,
1260 "Uint": 0,
1261 "Float": 0,
1262 "Map": {},
1263 "StructScalars": {
1264 "Bool": false,
1265 "String": "",
1266 "Bytes": "",
1267 "Int": 0,
1268 "Uint": 0,
1269 "Float": 0
1270 },
1271 "StructMaps": {
1272 "MapBool": {},
1273 "MapString": {},
1274 "MapBytes": {},
1275 "MapInt": {},
1276 "MapUint": {},
1277 "MapFloat": {}
1278 },
1279 "StructSlices": {
1280 "SliceBool": [],
1281 "SliceString": [],
1282 "SliceBytes": [],
1283 "SliceInt": [],
1284 "SliceUint": [],
1285 "SliceFloat": []
1286 },
1287 "Slice": [],
1288 "Array": [
1289 ""
1290 ],
1291 "Pointer": null,
1292 "Interface": null
1293 },
1294 "Interface": null
1295 }`,
1296 }, {
1297 name: jsontest.Name("Structs/SpaceAfterColonAndComma"),
1298 opts: []Options{jsontext.SpaceAfterColon(true), jsontext.SpaceAfterComma(true)},
1299 in: structOmitZeroAll{Int: 1, Uint: 1},
1300 want: `{"Int": 1, "Uint": 1}`,
1301 }, {
1302 name: jsontest.Name("Structs/SpaceAfterColon"),
1303 opts: []Options{jsontext.SpaceAfterColon(true)},
1304 in: structOmitZeroAll{Int: 1, Uint: 1},
1305 want: `{"Int": 1,"Uint": 1}`,
1306 }, {
1307 name: jsontest.Name("Structs/SpaceAfterComma"),
1308 opts: []Options{jsontext.SpaceAfterComma(true)},
1309 in: structOmitZeroAll{Int: 1, Uint: 1, Slice: []string{"a", "b"}},
1310 want: `{"Int":1, "Uint":1, "Slice":["a", "b"]}`,
1311 }, {
1312 name: jsontest.Name("Structs/Stringified"),
1313 opts: []Options{jsontext.Multiline(true)},
1314 in: structStringifiedAll{
1315 Bool: true,
1316 String: "hello",
1317 Bytes: []byte{1, 2, 3},
1318 Int: -64,
1319 Uint: +64,
1320 Float: 3.14159,
1321 Map: map[string]string{"key": "value"},
1322 StructScalars: structScalars{
1323 Bool: true,
1324 String: "hello",
1325 Bytes: []byte{1, 2, 3},
1326 Int: -64,
1327 Uint: +64,
1328 Float: 3.14159,
1329 },
1330 StructMaps: structMaps{
1331 MapBool: map[string]bool{"": true},
1332 MapString: map[string]string{"": "hello"},
1333 MapBytes: map[string][]byte{"": {1, 2, 3}},
1334 MapInt: map[string]int64{"": -64},
1335 MapUint: map[string]uint64{"": +64},
1336 MapFloat: map[string]float64{"": 3.14159},
1337 },
1338 StructSlices: structSlices{
1339 SliceBool: []bool{true},
1340 SliceString: []string{"hello"},
1341 SliceBytes: [][]byte{{1, 2, 3}},
1342 SliceInt: []int64{-64},
1343 SliceUint: []uint64{+64},
1344 SliceFloat: []float64{3.14159},
1345 },
1346 Slice: []string{"fizz", "buzz"},
1347 Array: [1]string{"goodbye"},
1348 Pointer: new(structStringifiedAll),
1349 Interface: (*structStringifiedAll)(nil),
1350 },
1351 want: `{
1352 "Bool": true,
1353 "String": "hello",
1354 "Bytes": "AQID",
1355 "Int": "-64",
1356 "Uint": "64",
1357 "Float": "3.14159",
1358 "Map": {
1359 "key": "value"
1360 },
1361 "StructScalars": {
1362 "Bool": true,
1363 "String": "hello",
1364 "Bytes": "AQID",
1365 "Int": "-64",
1366 "Uint": "64",
1367 "Float": "3.14159"
1368 },
1369 "StructMaps": {
1370 "MapBool": {
1371 "": true
1372 },
1373 "MapString": {
1374 "": "hello"
1375 },
1376 "MapBytes": {
1377 "": "AQID"
1378 },
1379 "MapInt": {
1380 "": "-64"
1381 },
1382 "MapUint": {
1383 "": "64"
1384 },
1385 "MapFloat": {
1386 "": "3.14159"
1387 }
1388 },
1389 "StructSlices": {
1390 "SliceBool": [
1391 true
1392 ],
1393 "SliceString": [
1394 "hello"
1395 ],
1396 "SliceBytes": [
1397 "AQID"
1398 ],
1399 "SliceInt": [
1400 "-64"
1401 ],
1402 "SliceUint": [
1403 "64"
1404 ],
1405 "SliceFloat": [
1406 "3.14159"
1407 ]
1408 },
1409 "Slice": [
1410 "fizz",
1411 "buzz"
1412 ],
1413 "Array": [
1414 "goodbye"
1415 ],
1416 "Pointer": {
1417 "Bool": false,
1418 "String": "",
1419 "Bytes": "",
1420 "Int": "0",
1421 "Uint": "0",
1422 "Float": "0",
1423 "Map": {},
1424 "StructScalars": {
1425 "Bool": false,
1426 "String": "",
1427 "Bytes": "",
1428 "Int": "0",
1429 "Uint": "0",
1430 "Float": "0"
1431 },
1432 "StructMaps": {
1433 "MapBool": {},
1434 "MapString": {},
1435 "MapBytes": {},
1436 "MapInt": {},
1437 "MapUint": {},
1438 "MapFloat": {}
1439 },
1440 "StructSlices": {
1441 "SliceBool": [],
1442 "SliceString": [],
1443 "SliceBytes": [],
1444 "SliceInt": [],
1445 "SliceUint": [],
1446 "SliceFloat": []
1447 },
1448 "Slice": [],
1449 "Array": [
1450 ""
1451 ],
1452 "Pointer": null,
1453 "Interface": null
1454 },
1455 "Interface": null
1456 }`,
1457 }, {
1458 name: jsontest.Name("Structs/LegacyStringified"),
1459 opts: []Options{jsontext.Multiline(true), jsonflags.StringifyWithLegacySemantics | 1},
1460 in: structStringifiedAll{
1461 Bool: true,
1462 String: "hello",
1463 Bytes: []byte{1, 2, 3},
1464 Int: -64,
1465 Uint: +64,
1466 Float: 3.14159,
1467 Map: map[string]string{"key": "value"},
1468 StructScalars: structScalars{
1469 Bool: true,
1470 String: "hello",
1471 Bytes: []byte{1, 2, 3},
1472 Int: -64,
1473 Uint: +64,
1474 Float: 3.14159,
1475 },
1476 StructMaps: structMaps{
1477 MapBool: map[string]bool{"": true},
1478 MapString: map[string]string{"": "hello"},
1479 MapBytes: map[string][]byte{"": {1, 2, 3}},
1480 MapInt: map[string]int64{"": -64},
1481 MapUint: map[string]uint64{"": +64},
1482 MapFloat: map[string]float64{"": 3.14159},
1483 },
1484 StructSlices: structSlices{
1485 SliceBool: []bool{true},
1486 SliceString: []string{"hello"},
1487 SliceBytes: [][]byte{{1, 2, 3}},
1488 SliceInt: []int64{-64},
1489 SliceUint: []uint64{+64},
1490 SliceFloat: []float64{3.14159},
1491 },
1492 Slice: []string{"fizz", "buzz"},
1493 Array: [1]string{"goodbye"},
1494 Pointer: new(structStringifiedAll),
1495 Interface: (*structStringifiedAll)(nil),
1496 },
1497 want: `{
1498 "Bool": "true",
1499 "String": "\"hello\"",
1500 "Bytes": "AQID",
1501 "Int": "-64",
1502 "Uint": "64",
1503 "Float": "3.14159",
1504 "Map": {
1505 "key": "value"
1506 },
1507 "StructScalars": {
1508 "Bool": true,
1509 "String": "hello",
1510 "Bytes": "AQID",
1511 "Int": -64,
1512 "Uint": 64,
1513 "Float": 3.14159
1514 },
1515 "StructMaps": {
1516 "MapBool": {
1517 "": true
1518 },
1519 "MapString": {
1520 "": "hello"
1521 },
1522 "MapBytes": {
1523 "": "AQID"
1524 },
1525 "MapInt": {
1526 "": -64
1527 },
1528 "MapUint": {
1529 "": 64
1530 },
1531 "MapFloat": {
1532 "": 3.14159
1533 }
1534 },
1535 "StructSlices": {
1536 "SliceBool": [
1537 true
1538 ],
1539 "SliceString": [
1540 "hello"
1541 ],
1542 "SliceBytes": [
1543 "AQID"
1544 ],
1545 "SliceInt": [
1546 -64
1547 ],
1548 "SliceUint": [
1549 64
1550 ],
1551 "SliceFloat": [
1552 3.14159
1553 ]
1554 },
1555 "Slice": [
1556 "fizz",
1557 "buzz"
1558 ],
1559 "Array": [
1560 "goodbye"
1561 ],
1562 "Pointer": {
1563 "Bool": "false",
1564 "String": "\"\"",
1565 "Bytes": "",
1566 "Int": "0",
1567 "Uint": "0",
1568 "Float": "0",
1569 "Map": {},
1570 "StructScalars": {
1571 "Bool": false,
1572 "String": "",
1573 "Bytes": "",
1574 "Int": 0,
1575 "Uint": 0,
1576 "Float": 0
1577 },
1578 "StructMaps": {
1579 "MapBool": {},
1580 "MapString": {},
1581 "MapBytes": {},
1582 "MapInt": {},
1583 "MapUint": {},
1584 "MapFloat": {}
1585 },
1586 "StructSlices": {
1587 "SliceBool": [],
1588 "SliceString": [],
1589 "SliceBytes": [],
1590 "SliceInt": [],
1591 "SliceUint": [],
1592 "SliceFloat": []
1593 },
1594 "Slice": [],
1595 "Array": [
1596 ""
1597 ],
1598 "Pointer": null,
1599 "Interface": null
1600 },
1601 "Interface": null
1602 }`,
1603 }, {
1604 name: jsontest.Name("Structs/OmitZero/Zero"),
1605 in: structOmitZeroAll{},
1606 want: `{}`,
1607 }, {
1608 name: jsontest.Name("Structs/OmitZeroOption/Zero"),
1609 opts: []Options{OmitZeroStructFields(true)},
1610 in: structAll{},
1611 want: `{}`,
1612 }, {
1613 name: jsontest.Name("Structs/OmitZero/NonZero"),
1614 opts: []Options{jsontext.Multiline(true)},
1615 in: structOmitZeroAll{
1616 Bool: true,
1617 String: " ",
1618 Bytes: []byte{},
1619 Int: 1,
1620 Uint: 1,
1621 Float: math.SmallestNonzeroFloat64,
1622 Map: map[string]string{},
1623 StructScalars: structScalars{unexported: true},
1624 StructSlices: structSlices{Ignored: true},
1625 StructMaps: structMaps{MapBool: map[string]bool{}},
1626 Slice: []string{},
1627 Array: [1]string{" "},
1628 Pointer: new(structOmitZeroAll),
1629 Interface: (*structOmitZeroAll)(nil),
1630 },
1631 want: `{
1632 "Bool": true,
1633 "String": " ",
1634 "Bytes": "",
1635 "Int": 1,
1636 "Uint": 1,
1637 "Float": 5e-324,
1638 "Map": {},
1639 "StructScalars": {
1640 "Bool": false,
1641 "String": "",
1642 "Bytes": "",
1643 "Int": 0,
1644 "Uint": 0,
1645 "Float": 0
1646 },
1647 "StructMaps": {
1648 "MapBool": {},
1649 "MapString": {},
1650 "MapBytes": {},
1651 "MapInt": {},
1652 "MapUint": {},
1653 "MapFloat": {}
1654 },
1655 "StructSlices": {
1656 "SliceBool": [],
1657 "SliceString": [],
1658 "SliceBytes": [],
1659 "SliceInt": [],
1660 "SliceUint": [],
1661 "SliceFloat": []
1662 },
1663 "Slice": [],
1664 "Array": [
1665 " "
1666 ],
1667 "Pointer": {},
1668 "Interface": null
1669 }`,
1670 }, {
1671 name: jsontest.Name("Structs/OmitZeroOption/NonZero"),
1672 opts: []Options{OmitZeroStructFields(true), jsontext.Multiline(true)},
1673 in: structAll{
1674 Bool: true,
1675 String: " ",
1676 Bytes: []byte{},
1677 Int: 1,
1678 Uint: 1,
1679 Float: math.SmallestNonzeroFloat64,
1680 Map: map[string]string{},
1681 StructScalars: structScalars{unexported: true},
1682 StructSlices: structSlices{Ignored: true},
1683 StructMaps: structMaps{MapBool: map[string]bool{}},
1684 Slice: []string{},
1685 Array: [1]string{" "},
1686 Pointer: new(structAll),
1687 Interface: (*structAll)(nil),
1688 },
1689 want: `{
1690 "Bool": true,
1691 "String": " ",
1692 "Bytes": "",
1693 "Int": 1,
1694 "Uint": 1,
1695 "Float": 5e-324,
1696 "Map": {},
1697 "StructScalars": {},
1698 "StructMaps": {
1699 "MapBool": {}
1700 },
1701 "StructSlices": {},
1702 "Slice": [],
1703 "Array": [
1704 " "
1705 ],
1706 "Pointer": {},
1707 "Interface": null
1708 }`,
1709 }, {
1710 name: jsontest.Name("Structs/OmitZeroMethod/Zero"),
1711 in: structOmitZeroMethodAll{},
1712 want: `{"ValueNeverZero":"","PointerNeverZero":""}`,
1713 }, {
1714 name: jsontest.Name("Structs/OmitZeroMethod/NonZero"),
1715 opts: []Options{jsontext.Multiline(true)},
1716 in: structOmitZeroMethodAll{
1717 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1718 ValueNeverZero: valueNeverZero("nonzero"),
1719 PointerAlwaysZero: pointerAlwaysZero("nonzero"),
1720 PointerNeverZero: pointerNeverZero("nonzero"),
1721 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1722 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1723 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1724 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1725 PointerPointerValueAlwaysZero: addr(addr(valueAlwaysZero("nonzero"))),
1726 PointerPointerValueNeverZero: addr(addr(valueNeverZero("nonzero"))),
1727 PointerPointerPointerAlwaysZero: addr(addr(pointerAlwaysZero("nonzero"))),
1728 PointerPointerPointerNeverZero: addr(addr(pointerNeverZero("nonzero"))),
1729 },
1730 want: `{
1731 "ValueNeverZero": "nonzero",
1732 "PointerNeverZero": "nonzero",
1733 "PointerValueNeverZero": "nonzero",
1734 "PointerPointerNeverZero": "nonzero",
1735 "PointerPointerValueAlwaysZero": "nonzero",
1736 "PointerPointerValueNeverZero": "nonzero",
1737 "PointerPointerPointerAlwaysZero": "nonzero",
1738 "PointerPointerPointerNeverZero": "nonzero"
1739 }`,
1740 }, {
1741 name: jsontest.Name("Structs/OmitZeroMethod/Interface/Zero"),
1742 opts: []Options{jsontext.Multiline(true)},
1743 in: structOmitZeroMethodInterfaceAll{},
1744 want: `{}`,
1745 }, {
1746 name: jsontest.Name("Structs/OmitZeroMethod/Interface/PartialZero"),
1747 opts: []Options{jsontext.Multiline(true)},
1748 in: structOmitZeroMethodInterfaceAll{
1749 ValueAlwaysZero: valueAlwaysZero(""),
1750 ValueNeverZero: valueNeverZero(""),
1751 PointerValueAlwaysZero: (*valueAlwaysZero)(nil),
1752 PointerValueNeverZero: (*valueNeverZero)(nil),
1753 PointerPointerAlwaysZero: (*pointerAlwaysZero)(nil),
1754 PointerPointerNeverZero: (*pointerNeverZero)(nil),
1755 },
1756 want: `{
1757 "ValueNeverZero": ""
1758 }`,
1759 }, {
1760 name: jsontest.Name("Structs/OmitZeroMethod/Interface/NonZero"),
1761 opts: []Options{jsontext.Multiline(true)},
1762 in: structOmitZeroMethodInterfaceAll{
1763 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1764 ValueNeverZero: valueNeverZero("nonzero"),
1765 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1766 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1767 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1768 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1769 },
1770 want: `{
1771 "ValueNeverZero": "nonzero",
1772 "PointerValueNeverZero": "nonzero",
1773 "PointerPointerNeverZero": "nonzero"
1774 }`,
1775 }, {
1776 name: jsontest.Name("Structs/OmitEmpty/Zero"),
1777 opts: []Options{jsontext.Multiline(true)},
1778 in: structOmitEmptyAll{},
1779 want: `{
1780 "Bool": false,
1781 "StringNonEmpty": "value",
1782 "BytesNonEmpty": [
1783 "value"
1784 ],
1785 "Float": 0,
1786 "MapNonEmpty": {
1787 "key": "value"
1788 },
1789 "SliceNonEmpty": [
1790 "value"
1791 ]
1792 }`,
1793 }, {
1794 name: jsontest.Name("Structs/OmitEmpty/EmptyNonZero"),
1795 opts: []Options{jsontext.Multiline(true)},
1796 in: structOmitEmptyAll{
1797 String: string(""),
1798 StringEmpty: stringMarshalEmpty(""),
1799 StringNonEmpty: stringMarshalNonEmpty(""),
1800 PointerString: addr(string("")),
1801 PointerStringEmpty: addr(stringMarshalEmpty("")),
1802 PointerStringNonEmpty: addr(stringMarshalNonEmpty("")),
1803 Bytes: []byte(""),
1804 BytesEmpty: bytesMarshalEmpty([]byte("")),
1805 BytesNonEmpty: bytesMarshalNonEmpty([]byte("")),
1806 PointerBytes: addr([]byte("")),
1807 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte(""))),
1808 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte(""))),
1809 Map: map[string]string{},
1810 MapEmpty: mapMarshalEmpty{},
1811 MapNonEmpty: mapMarshalNonEmpty{},
1812 PointerMap: addr(map[string]string{}),
1813 PointerMapEmpty: addr(mapMarshalEmpty{}),
1814 PointerMapNonEmpty: addr(mapMarshalNonEmpty{}),
1815 Slice: []string{},
1816 SliceEmpty: sliceMarshalEmpty{},
1817 SliceNonEmpty: sliceMarshalNonEmpty{},
1818 PointerSlice: addr([]string{}),
1819 PointerSliceEmpty: addr(sliceMarshalEmpty{}),
1820 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{}),
1821 Pointer: &structOmitZeroEmptyAll{},
1822 Interface: []string{},
1823 },
1824 want: `{
1825 "Bool": false,
1826 "StringNonEmpty": "value",
1827 "PointerStringNonEmpty": "value",
1828 "BytesNonEmpty": [
1829 "value"
1830 ],
1831 "PointerBytesNonEmpty": [
1832 "value"
1833 ],
1834 "Float": 0,
1835 "MapNonEmpty": {
1836 "key": "value"
1837 },
1838 "PointerMapNonEmpty": {
1839 "key": "value"
1840 },
1841 "SliceNonEmpty": [
1842 "value"
1843 ],
1844 "PointerSliceNonEmpty": [
1845 "value"
1846 ]
1847 }`,
1848 }, {
1849 name: jsontest.Name("Structs/OmitEmpty/NonEmpty"),
1850 opts: []Options{jsontext.Multiline(true)},
1851 in: structOmitEmptyAll{
1852 Bool: true,
1853 PointerBool: addr(true),
1854 String: string("value"),
1855 StringEmpty: stringMarshalEmpty("value"),
1856 StringNonEmpty: stringMarshalNonEmpty("value"),
1857 PointerString: addr(string("value")),
1858 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1859 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1860 Bytes: []byte("value"),
1861 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1862 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1863 PointerBytes: addr([]byte("value")),
1864 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1865 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1866 Float: math.Copysign(0, -1),
1867 PointerFloat: addr(math.Copysign(0, -1)),
1868 Map: map[string]string{"": ""},
1869 MapEmpty: mapMarshalEmpty{"key": "value"},
1870 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1871 PointerMap: addr(map[string]string{"": ""}),
1872 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1873 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1874 Slice: []string{""},
1875 SliceEmpty: sliceMarshalEmpty{"value"},
1876 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1877 PointerSlice: addr([]string{""}),
1878 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1879 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1880 Pointer: &structOmitZeroEmptyAll{Float: math.SmallestNonzeroFloat64},
1881 Interface: []string{""},
1882 },
1883 want: `{
1884 "Bool": true,
1885 "PointerBool": true,
1886 "String": "value",
1887 "StringNonEmpty": "value",
1888 "PointerString": "value",
1889 "PointerStringNonEmpty": "value",
1890 "Bytes": "dmFsdWU=",
1891 "BytesNonEmpty": [
1892 "value"
1893 ],
1894 "PointerBytes": "dmFsdWU=",
1895 "PointerBytesNonEmpty": [
1896 "value"
1897 ],
1898 "Float": -0,
1899 "PointerFloat": -0,
1900 "Map": {
1901 "": ""
1902 },
1903 "MapNonEmpty": {
1904 "key": "value"
1905 },
1906 "PointerMap": {
1907 "": ""
1908 },
1909 "PointerMapNonEmpty": {
1910 "key": "value"
1911 },
1912 "Slice": [
1913 ""
1914 ],
1915 "SliceNonEmpty": [
1916 "value"
1917 ],
1918 "PointerSlice": [
1919 ""
1920 ],
1921 "PointerSliceNonEmpty": [
1922 "value"
1923 ],
1924 "Pointer": {
1925 "Float": 5e-324
1926 },
1927 "Interface": [
1928 ""
1929 ]
1930 }`,
1931 }, {
1932 name: jsontest.Name("Structs/OmitEmpty/Legacy/Zero"),
1933 opts: []Options{jsonflags.OmitEmptyWithLegacySemantics | 1},
1934 in: structOmitEmptyAll{},
1935 want: `{}`,
1936 }, {
1937 name: jsontest.Name("Structs/OmitEmpty/Legacy/NonEmpty"),
1938 opts: []Options{jsontext.Multiline(true), jsonflags.OmitEmptyWithLegacySemantics | 1},
1939 in: structOmitEmptyAll{
1940 Bool: true,
1941 PointerBool: addr(true),
1942 String: string("value"),
1943 StringEmpty: stringMarshalEmpty("value"),
1944 StringNonEmpty: stringMarshalNonEmpty("value"),
1945 PointerString: addr(string("value")),
1946 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1947 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1948 Bytes: []byte("value"),
1949 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1950 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1951 PointerBytes: addr([]byte("value")),
1952 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1953 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1954 Float: math.Copysign(0, -1),
1955 PointerFloat: addr(math.Copysign(0, -1)),
1956 Map: map[string]string{"": ""},
1957 MapEmpty: mapMarshalEmpty{"key": "value"},
1958 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1959 PointerMap: addr(map[string]string{"": ""}),
1960 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1961 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1962 Slice: []string{""},
1963 SliceEmpty: sliceMarshalEmpty{"value"},
1964 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1965 PointerSlice: addr([]string{""}),
1966 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1967 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1968 Pointer: &structOmitZeroEmptyAll{Float: math.Copysign(0, -1)},
1969 Interface: []string{""},
1970 },
1971 want: `{
1972 "Bool": true,
1973 "PointerBool": true,
1974 "String": "value",
1975 "StringEmpty": "",
1976 "StringNonEmpty": "value",
1977 "PointerString": "value",
1978 "PointerStringEmpty": "",
1979 "PointerStringNonEmpty": "value",
1980 "Bytes": "dmFsdWU=",
1981 "BytesEmpty": [],
1982 "BytesNonEmpty": [
1983 "value"
1984 ],
1985 "PointerBytes": "dmFsdWU=",
1986 "PointerBytesEmpty": [],
1987 "PointerBytesNonEmpty": [
1988 "value"
1989 ],
1990 "PointerFloat": -0,
1991 "Map": {
1992 "": ""
1993 },
1994 "MapEmpty": {},
1995 "MapNonEmpty": {
1996 "key": "value"
1997 },
1998 "PointerMap": {
1999 "": ""
2000 },
2001 "PointerMapEmpty": {},
2002 "PointerMapNonEmpty": {
2003 "key": "value"
2004 },
2005 "Slice": [
2006 ""
2007 ],
2008 "SliceEmpty": [],
2009 "SliceNonEmpty": [
2010 "value"
2011 ],
2012 "PointerSlice": [
2013 ""
2014 ],
2015 "PointerSliceEmpty": [],
2016 "PointerSliceNonEmpty": [
2017 "value"
2018 ],
2019 "Pointer": {},
2020 "Interface": [
2021 ""
2022 ]
2023 }`,
2024 }, {
2025 name: jsontest.Name("Structs/OmitEmpty/NonEmptyString"),
2026 in: struct {
2027 X string `json:",omitempty"`
2028 }{`"`},
2029 want: `{"X":"\""}`,
2030 }, {
2031 name: jsontest.Name("Structs/OmitZeroEmpty/Zero"),
2032 in: structOmitZeroEmptyAll{},
2033 want: `{}`,
2034 }, {
2035 name: jsontest.Name("Structs/OmitZeroEmpty/Empty"),
2036 in: structOmitZeroEmptyAll{
2037 Bytes: []byte{},
2038 Map: map[string]string{},
2039 Slice: []string{},
2040 Pointer: &structOmitZeroEmptyAll{},
2041 Interface: []string{},
2042 },
2043 want: `{}`,
2044 }, {
2045 name: jsontest.Name("Structs/OmitEmpty/PathologicalDepth"),
2046 in: func() any {
2047 type X struct {
2048 X *X `json:",omitempty"`
2049 }
2050 var make func(int) *X
2051 make = func(n int) *X {
2052 if n == 0 {
2053 return nil
2054 }
2055 return &X{make(n - 1)}
2056 }
2057 return make(100)
2058 }(),
2059 want: `{}`,
2060 useWriter: true,
2061 }, {
2062 name: jsontest.Name("Structs/OmitEmpty/PathologicalBreadth"),
2063 in: func() any {
2064 var fields []reflect.StructField
2065 for i := range 100 {
2066 fields = append(fields, reflect.StructField{
2067 Name: fmt.Sprintf("X%d", i),
2068 Type: T[stringMarshalEmpty](),
2069 Tag: `json:",omitempty"`,
2070 })
2071 }
2072 return reflect.New(reflect.StructOf(fields)).Interface()
2073 }(),
2074 want: `{}`,
2075 useWriter: true,
2076 }, {
2077 name: jsontest.Name("Structs/OmitEmpty/PathologicalTree"),
2078 in: func() any {
2079 type X struct {
2080 XL, XR *X `json:",omitempty"`
2081 }
2082 var make func(int) *X
2083 make = func(n int) *X {
2084 if n == 0 {
2085 return nil
2086 }
2087 return &X{make(n - 1), make(n - 1)}
2088 }
2089 return make(8)
2090 }(),
2091 want: `{}`,
2092 useWriter: true,
2093 }, {
2094 name: jsontest.Name("Structs/OmitZeroEmpty/NonEmpty"),
2095 in: structOmitZeroEmptyAll{
2096 Bytes: []byte("value"),
2097 Map: map[string]string{"": ""},
2098 Slice: []string{""},
2099 Pointer: &structOmitZeroEmptyAll{Bool: true},
2100 Interface: []string{""},
2101 },
2102 want: `{"Bytes":"dmFsdWU=","Map":{"":""},"Slice":[""],"Pointer":{"Bool":true},"Interface":[""]}`,
2103 }, {
2104 name: jsontest.Name("Structs/Format/Bytes"),
2105 opts: []Options{jsontext.Multiline(true)},
2106 in: structFormatBytes{
2107 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
2108 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2109 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2110 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߿"),
2111 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߿"),
2112 Array: []byte{1, 2, 3, 4},
2113 },
2114 want: `{
2115 "Base16": "0123456789abcdef",
2116 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
2117 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
2118 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
2119 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
2120 "Array": [
2121 1,
2122 2,
2123 3,
2124 4
2125 ]
2126 }`}, {
2127 name: jsontest.Name("Structs/Format/ArrayBytes"),
2128 opts: []Options{jsontext.Multiline(true)},
2129 in: structFormatArrayBytes{
2130 Base16: [4]byte{1, 2, 3, 4},
2131 Base32: [4]byte{1, 2, 3, 4},
2132 Base32Hex: [4]byte{1, 2, 3, 4},
2133 Base64: [4]byte{1, 2, 3, 4},
2134 Base64URL: [4]byte{1, 2, 3, 4},
2135 Array: [4]byte{1, 2, 3, 4},
2136 Default: [4]byte{1, 2, 3, 4},
2137 },
2138 want: `{
2139 "Base16": "01020304",
2140 "Base32": "AEBAGBA=",
2141 "Base32Hex": "0410610=",
2142 "Base64": "AQIDBA==",
2143 "Base64URL": "AQIDBA==",
2144 "Array": [
2145 1,
2146 2,
2147 3,
2148 4
2149 ],
2150 "Default": "AQIDBA=="
2151 }`}, {
2152 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
2153 opts: []Options{jsontext.Multiline(true), jsonflags.FormatByteArrayAsArray | jsonflags.FormatBytesWithLegacySemantics | 1},
2154 in: structFormatArrayBytes{
2155 Base16: [4]byte{1, 2, 3, 4},
2156 Base32: [4]byte{1, 2, 3, 4},
2157 Base32Hex: [4]byte{1, 2, 3, 4},
2158 Base64: [4]byte{1, 2, 3, 4},
2159 Base64URL: [4]byte{1, 2, 3, 4},
2160 Array: [4]byte{1, 2, 3, 4},
2161 Default: [4]byte{1, 2, 3, 4},
2162 },
2163 want: `{
2164 "Base16": "01020304",
2165 "Base32": "AEBAGBA=",
2166 "Base32Hex": "0410610=",
2167 "Base64": "AQIDBA==",
2168 "Base64URL": "AQIDBA==",
2169 "Array": [
2170 1,
2171 2,
2172 3,
2173 4
2174 ],
2175 "Default": [
2176 1,
2177 2,
2178 3,
2179 4
2180 ]
2181 }`}, {
2182 name: jsontest.Name("Structs/Format/Bytes/Array"),
2183 opts: []Options{
2184 WithMarshalers(MarshalFunc(func(in byte) ([]byte, error) {
2185 if in > 3 {
2186 return []byte("true"), nil
2187 } else {
2188 return []byte("false"), nil
2189 }
2190 })),
2191 },
2192 in: struct {
2193 Array []byte `json:",format:array"`
2194 }{
2195 Array: []byte{1, 6, 2, 5, 3, 4},
2196 },
2197 want: `{"Array":[false,true,false,true,false,true]}`,
2198 }, {
2199 name: jsontest.Name("Structs/Format/Floats"),
2200 opts: []Options{jsontext.Multiline(true)},
2201 in: []structFormatFloats{
2202 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
2203 {NonFinite: math.NaN(), PointerNonFinite: addr(math.NaN())},
2204 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
2205 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
2206 },
2207 want: `[
2208 {
2209 "NonFinite": 3.141592653589793,
2210 "PointerNonFinite": 3.141592653589793
2211 },
2212 {
2213 "NonFinite": "NaN",
2214 "PointerNonFinite": "NaN"
2215 },
2216 {
2217 "NonFinite": "-Infinity",
2218 "PointerNonFinite": "-Infinity"
2219 },
2220 {
2221 "NonFinite": "Infinity",
2222 "PointerNonFinite": "Infinity"
2223 }
2224 ]`,
2225 }, {
2226 name: jsontest.Name("Structs/Format/Maps"),
2227 opts: []Options{jsontext.Multiline(true)},
2228 in: []structFormatMaps{{
2229 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2230 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2231 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2232 }, {
2233 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2234 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2235 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2236 }, {
2237 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2238 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2239 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2240 }},
2241 want: `[
2242 {
2243 "EmitNull": null,
2244 "PointerEmitNull": null,
2245 "EmitEmpty": {},
2246 "PointerEmitEmpty": {},
2247 "EmitDefault": {},
2248 "PointerEmitDefault": {}
2249 },
2250 {
2251 "EmitNull": {},
2252 "PointerEmitNull": {},
2253 "EmitEmpty": {},
2254 "PointerEmitEmpty": {},
2255 "EmitDefault": {},
2256 "PointerEmitDefault": {}
2257 },
2258 {
2259 "EmitNull": {
2260 "k": "v"
2261 },
2262 "PointerEmitNull": {
2263 "k": "v"
2264 },
2265 "EmitEmpty": {
2266 "k": "v"
2267 },
2268 "PointerEmitEmpty": {
2269 "k": "v"
2270 },
2271 "EmitDefault": {
2272 "k": "v"
2273 },
2274 "PointerEmitDefault": {
2275 "k": "v"
2276 }
2277 }
2278 ]`,
2279 }, {
2280 name: jsontest.Name("Structs/Format/Maps/FormatNilMapAsNull"),
2281 opts: []Options{
2282 FormatNilMapAsNull(true),
2283 jsontext.Multiline(true),
2284 },
2285 in: []structFormatMaps{{
2286 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2287 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2288 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2289 }, {
2290 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2291 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2292 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2293 }, {
2294 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2295 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2296 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2297 }},
2298 want: `[
2299 {
2300 "EmitNull": null,
2301 "PointerEmitNull": null,
2302 "EmitEmpty": {},
2303 "PointerEmitEmpty": {},
2304 "EmitDefault": null,
2305 "PointerEmitDefault": null
2306 },
2307 {
2308 "EmitNull": {},
2309 "PointerEmitNull": {},
2310 "EmitEmpty": {},
2311 "PointerEmitEmpty": {},
2312 "EmitDefault": {},
2313 "PointerEmitDefault": {}
2314 },
2315 {
2316 "EmitNull": {
2317 "k": "v"
2318 },
2319 "PointerEmitNull": {
2320 "k": "v"
2321 },
2322 "EmitEmpty": {
2323 "k": "v"
2324 },
2325 "PointerEmitEmpty": {
2326 "k": "v"
2327 },
2328 "EmitDefault": {
2329 "k": "v"
2330 },
2331 "PointerEmitDefault": {
2332 "k": "v"
2333 }
2334 }
2335 ]`,
2336 }, {
2337 name: jsontest.Name("Structs/Format/Slices"),
2338 opts: []Options{jsontext.Multiline(true)},
2339 in: []structFormatSlices{{
2340 EmitNull: []string(nil), PointerEmitNull: addr([]string(nil)),
2341 EmitEmpty: []string(nil), PointerEmitEmpty: addr([]string(nil)),
2342 EmitDefault: []string(nil), PointerEmitDefault: addr([]string(nil)),
2343 }, {
2344 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
2345 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
2346 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
2347 }, {
2348 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
2349 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
2350 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
2351 }},
2352 want: `[
2353 {
2354 "EmitNull": null,
2355 "PointerEmitNull": null,
2356 "EmitEmpty": [],
2357 "PointerEmitEmpty": [],
2358 "EmitDefault": [],
2359 "PointerEmitDefault": []
2360 },
2361 {
2362 "EmitNull": [],
2363 "PointerEmitNull": [],
2364 "EmitEmpty": [],
2365 "PointerEmitEmpty": [],
2366 "EmitDefault": [],
2367 "PointerEmitDefault": []
2368 },
2369 {
2370 "EmitNull": [
2371 "v"
2372 ],
2373 "PointerEmitNull": [
2374 "v"
2375 ],
2376 "EmitEmpty": [
2377 "v"
2378 ],
2379 "PointerEmitEmpty": [
2380 "v"
2381 ],
2382 "EmitDefault": [
2383 "v"
2384 ],
2385 "PointerEmitDefault": [
2386 "v"
2387 ]
2388 }
2389 ]`,
2390 }, {
2391 name: jsontest.Name("Structs/Format/Invalid/Bool"),
2392 in: structFormatInvalid{Bool: true},
2393 want: `{"Bool"`,
2394 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, boolType),
2395 }, {
2396 name: jsontest.Name("Structs/Format/Invalid/String"),
2397 in: structFormatInvalid{String: "string"},
2398 want: `{"String"`,
2399 wantErr: EM(errInvalidFormatFlag).withPos(`{"String":`, "/String").withType(0, stringType),
2400 }, {
2401 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
2402 in: structFormatInvalid{Bytes: []byte("bytes")},
2403 want: `{"Bytes"`,
2404 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bytes":`, "/Bytes").withType(0, bytesType),
2405 }, {
2406 name: jsontest.Name("Structs/Format/Invalid/Int"),
2407 in: structFormatInvalid{Int: 1},
2408 want: `{"Int"`,
2409 wantErr: EM(errInvalidFormatFlag).withPos(`{"Int":`, "/Int").withType(0, T[int64]()),
2410 }, {
2411 name: jsontest.Name("Structs/Format/Invalid/Uint"),
2412 in: structFormatInvalid{Uint: 1},
2413 want: `{"Uint"`,
2414 wantErr: EM(errInvalidFormatFlag).withPos(`{"Uint":`, "/Uint").withType(0, T[uint64]()),
2415 }, {
2416 name: jsontest.Name("Structs/Format/Invalid/Float"),
2417 in: structFormatInvalid{Float: 1},
2418 want: `{"Float"`,
2419 wantErr: EM(errInvalidFormatFlag).withPos(`{"Float":`, "/Float").withType(0, T[float64]()),
2420 }, {
2421 name: jsontest.Name("Structs/Format/Invalid/Map"),
2422 in: structFormatInvalid{Map: map[string]string{}},
2423 want: `{"Map"`,
2424 wantErr: EM(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
2425 }, {
2426 name: jsontest.Name("Structs/Format/Invalid/Struct"),
2427 in: structFormatInvalid{Struct: structAll{Bool: true}},
2428 want: `{"Struct"`,
2429 wantErr: EM(errInvalidFormatFlag).withPos(`{"Struct":`, "/Struct").withType(0, T[structAll]()),
2430 }, {
2431 name: jsontest.Name("Structs/Format/Invalid/Slice"),
2432 in: structFormatInvalid{Slice: []string{}},
2433 want: `{"Slice"`,
2434 wantErr: EM(errInvalidFormatFlag).withPos(`{"Slice":`, "/Slice").withType(0, T[[]string]()),
2435 }, {
2436 name: jsontest.Name("Structs/Format/Invalid/Array"),
2437 in: structFormatInvalid{Array: [1]string{"string"}},
2438 want: `{"Array"`,
2439 wantErr: EM(errInvalidFormatFlag).withPos(`{"Array":`, "/Array").withType(0, T[[1]string]()),
2440 }, {
2441 name: jsontest.Name("Structs/Format/Invalid/Interface"),
2442 in: structFormatInvalid{Interface: "anything"},
2443 want: `{"Interface"`,
2444 wantErr: EM(errInvalidFormatFlag).withPos(`{"Interface":`, "/Interface").withType(0, T[any]()),
2445 }, {
2446 name: jsontest.Name("Structs/Inline/Zero"),
2447 in: structInlined{},
2448 want: `{"D":""}`,
2449 }, {
2450 name: jsontest.Name("Structs/Inline/Alloc"),
2451 in: structInlined{
2452 X: structInlinedL1{
2453 X: &structInlinedL2{},
2454 StructEmbed1: StructEmbed1{},
2455 },
2456 StructEmbed2: &StructEmbed2{},
2457 },
2458 want: `{"A":"","B":"","D":"","E":"","F":"","G":""}`,
2459 }, {
2460 name: jsontest.Name("Structs/Inline/NonZero"),
2461 in: structInlined{
2462 X: structInlinedL1{
2463 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
2464 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
2465 },
2466 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
2467 },
2468 want: `{"A":"A1","B":"B1","D":"D2","E":"E3","F":"F3","G":"G3"}`,
2469 }, {
2470 name: jsontest.Name("Structs/Inline/DualCycle"),
2471 in: cyclicA{
2472 B1: cyclicB{F: 1},
2473 B2: cyclicB{F: 2},
2474 },
2475 want: `{}`,
2476 }, {
2477 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nil"),
2478 in: structInlineTextValue{X: jsontext.Value(nil)},
2479 want: `{}`,
2480 }, {
2481 name: jsontest.Name("Structs/InlinedFallback/TextValue/Empty"),
2482 in: structInlineTextValue{X: jsontext.Value("")},
2483 want: `{}`,
2484 }, {
2485 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN1"),
2486 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)},
2487 want: `{"fizz":"buzz"}`,
2488 }, {
2489 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN2"),
2490 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `)},
2491 want: `{"fizz":"buzz","foo":"bar"}`,
2492 }, {
2493 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyWithOthers"),
2494 in: structInlineTextValue{
2495 A: 1,
2496 X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `),
2497 B: 2,
2498 },
2499
2500 want: `{"A":1,"B":2,"fizz":"buzz","foo":"bar"}`,
2501 }, {
2502 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
2503 opts: []Options{jsontext.AllowDuplicateNames(false)},
2504 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2505 want: `{"fizz":"buzz"`,
2506 wantErr: newDuplicateNameError("/fizz", nil, len64(`{"fizz":"buzz"`)),
2507 }, {
2508 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
2509 opts: []Options{jsontext.AllowDuplicateNames(true)},
2510 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2511 want: `{"fizz":"buzz","fizz":"buzz"}`,
2512 }, {
2513 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectInvalidUTF8"),
2514 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2515 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2516 want: `{`,
2517 wantErr: newInvalidUTF8Error(len64(`{"`+"\xde\xad"), ""),
2518 }, {
2519 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowInvalidUTF8"),
2520 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2521 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2522 want: `{"ޭ��":"value"}`,
2523 }, {
2524 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidWhitespace"),
2525 in: structInlineTextValue{X: jsontext.Value("\n\r\t ")},
2526 want: `{`,
2527 wantErr: EM(io.ErrUnexpectedEOF).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2528 }, {
2529 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObject"),
2530 in: structInlineTextValue{X: jsontext.Value(` true `)},
2531 want: `{`,
2532 wantErr: EM(errRawInlinedNotObject).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2533 }, {
2534 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObjectName"),
2535 in: structInlineTextValue{X: jsontext.Value(` { true : false } `)},
2536 want: `{`,
2537 wantErr: EM(newNonStringNameError(len64(" { "), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2538 }, {
2539 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidEndObject"),
2540 in: structInlineTextValue{X: jsontext.Value(` { "name" : false , } `)},
2541 want: `{"name":false`,
2542 wantErr: EM(newInvalidCharacterError(",", "at start of value", len64(` { "name" : false `), "")).withPos(`{"name":false,`, "").withType(0, T[jsontext.Value]()),
2543 }, {
2544 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidDualObject"),
2545 in: structInlineTextValue{X: jsontext.Value(`{}{}`)},
2546 want: `{`,
2547 wantErr: EM(newInvalidCharacterError("{", "after top-level value", len64(`{}`), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2548 }, {
2549 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Nil"),
2550 in: structInlinePointerInlineTextValue{},
2551 want: `{}`,
2552 }, {
2553 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nil"),
2554 in: structInlinePointerTextValue{},
2555 want: `{}`,
2556 }, {
2557 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/NonEmpty"),
2558 in: structInlinePointerTextValue{X: addr(jsontext.Value(` { "fizz" : "buzz" } `))},
2559 want: `{"fizz":"buzz"}`,
2560 }, {
2561 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
2562 in: structInlineInlinePointerTextValue{},
2563 want: `{}`,
2564 }, {
2565 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nil"),
2566 in: structInlineMapStringAny{X: nil},
2567 want: `{}`,
2568 }, {
2569 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Empty"),
2570 in: structInlineMapStringAny{X: make(jsonObject)},
2571 want: `{}`,
2572 }, {
2573 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN1"),
2574 in: structInlineMapStringAny{X: jsonObject{"fizz": nil}},
2575 want: `{"fizz":null}`,
2576 }, {
2577 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN2"),
2578 in: structInlineMapStringAny{X: jsonObject{"fizz": time.Time{}, "buzz": math.Pi}},
2579 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2580 canonicalize: true,
2581 }, {
2582 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyWithOthers"),
2583 in: structInlineMapStringAny{
2584 A: 1,
2585 X: jsonObject{"fizz": nil},
2586 B: 2,
2587 },
2588
2589 want: `{"A":1,"B":2,"fizz":null}`,
2590 }, {
2591 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectInvalidUTF8"),
2592 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2593 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2594 want: `{`,
2595 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, stringType),
2596 }, {
2597 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowInvalidUTF8"),
2598 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2599 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2600 want: `{"ޭ��":null}`,
2601 }, {
2602 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/InvalidValue"),
2603 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2604 in: structInlineMapStringAny{X: jsonObject{"name": make(chan string)}},
2605 want: `{"name"`,
2606 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2607 }, {
2608 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Nil"),
2609 in: structInlinePointerInlineMapStringAny{},
2610 want: `{}`,
2611 }, {
2612 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MarshalFunc"),
2613 opts: []Options{
2614 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2615 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2616 })),
2617 },
2618 in: structInlineMapStringAny{X: jsonObject{"fizz": 3.14159}},
2619 want: `{"fizz":"3.14159"}`,
2620 }, {
2621 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nil"),
2622 in: structInlinePointerMapStringAny{X: nil},
2623 want: `{}`,
2624 }, {
2625 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/NonEmpty"),
2626 in: structInlinePointerMapStringAny{X: addr(jsonObject{"name": "value"})},
2627 want: `{"name":"value"}`,
2628 }, {
2629 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
2630 in: structInlineInlinePointerMapStringAny{},
2631 want: `{}`,
2632 }, {
2633 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
2634 in: structInlineMapStringInt{
2635 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2636 },
2637 want: `{"one":1,"two":2,"zero":0}`,
2638 canonicalize: true,
2639 }, {
2640 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic"),
2641 opts: []Options{Deterministic(true)},
2642 in: structInlineMapStringInt{
2643 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2644 },
2645 want: `{"one":1,"two":2,"zero":0}`,
2646 }, {
2647 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
2648 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
2649 in: structInlineMapStringInt{
2650 X: map[string]int{"\xff": 0, "\xfe": 1},
2651 },
2652 want: `{"�":1`,
2653 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1`)),
2654 }, {
2655 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
2656 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
2657 in: structInlineMapStringInt{
2658 X: map[string]int{"\xff": 0, "\xfe": 1},
2659 },
2660 want: `{"�":1,"�":0}`,
2661 }, {
2662 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
2663 opts: []Options{StringifyNumbers(true)},
2664 in: structInlineMapStringInt{
2665 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2666 },
2667 want: `{"one":"1","two":"2","zero":"0"}`,
2668 canonicalize: true,
2669 }, {
2670 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/MarshalFunc"),
2671 opts: []Options{
2672 WithMarshalers(JoinMarshalers(
2673
2674 MarshalFunc(func(v string) ([]byte, error) {
2675 return []byte(fmt.Sprintf(`"%q"`, strings.ToUpper(v))), nil
2676 }),
2677 MarshalFunc(func(v int) ([]byte, error) {
2678 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2679 }),
2680 )),
2681 },
2682 in: structInlineMapStringInt{
2683 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2684 },
2685 want: `{"one":"1","two":"2","zero":"0"}`,
2686 canonicalize: true,
2687 }, {
2688 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
2689 in: structInlineMapNamedStringInt{
2690 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2691 },
2692 want: `{"one":1,"two":2,"zero":0}`,
2693 canonicalize: true,
2694 }, {
2695 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Deterministic"),
2696 opts: []Options{Deterministic(true)},
2697 in: structInlineMapNamedStringInt{
2698 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2699 },
2700 want: `{"one":1,"two":2,"zero":0}`,
2701 }, {
2702 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Nil"),
2703 in: structInlineMapNamedStringAny{X: nil},
2704 want: `{}`,
2705 }, {
2706 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Empty"),
2707 in: structInlineMapNamedStringAny{X: make(map[namedString]any)},
2708 want: `{}`,
2709 }, {
2710 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN1"),
2711 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": nil}},
2712 want: `{"fizz":null}`,
2713 }, {
2714 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN2"),
2715 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": time.Time{}, "buzz": math.Pi}},
2716 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2717 canonicalize: true,
2718 }, {
2719 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyWithOthers"),
2720 in: structInlineMapNamedStringAny{
2721 A: 1,
2722 X: map[namedString]any{"fizz": nil},
2723 B: 2,
2724 },
2725
2726 want: `{"A":1,"B":2,"fizz":null}`,
2727 }, {
2728 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectInvalidUTF8"),
2729 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2730 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2731 want: `{`,
2732 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, T[namedString]()),
2733 }, {
2734 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowInvalidUTF8"),
2735 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2736 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2737 want: `{"ޭ��":null}`,
2738 }, {
2739 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/InvalidValue"),
2740 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2741 in: structInlineMapNamedStringAny{X: map[namedString]any{"name": make(chan string)}},
2742 want: `{"name"`,
2743 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2744 }, {
2745 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MarshalFunc"),
2746 opts: []Options{
2747 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2748 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2749 })),
2750 },
2751 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": 3.14159}},
2752 want: `{"fizz":"3.14159"}`,
2753 }, {
2754 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other"),
2755 in: structNoCaseInlineTextValue{
2756 X: jsontext.Value(`{"dupe":"","dupe":""}`),
2757 },
2758 want: `{"dupe":""`,
2759 wantErr: newDuplicateNameError("", []byte(`"dupe"`), len64(`{"dupe":""`)),
2760 }, {
2761 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other/AllowDuplicateNames"),
2762 opts: []Options{jsontext.AllowDuplicateNames(true)},
2763 in: structNoCaseInlineTextValue{
2764 X: jsontext.Value(`{"dupe": "", "dupe": ""}`),
2765 },
2766 want: `{"dupe":"","dupe":""}`,
2767 }, {
2768 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferent"),
2769 in: structNoCaseInlineTextValue{
2770 X: jsontext.Value(`{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""}`),
2771 },
2772 want: `{"Aaa":"","AaA":"","AAa":"","AAA":""}`,
2773 }, {
2774 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict"),
2775 in: structNoCaseInlineTextValue{
2776 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2777 },
2778 want: `{"Aaa":""`,
2779 wantErr: newDuplicateNameError("", []byte(`"Aaa"`), len64(`{"Aaa":""`)),
2780 }, {
2781 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict/AllowDuplicateNames"),
2782 opts: []Options{jsontext.AllowDuplicateNames(true)},
2783 in: structNoCaseInlineTextValue{
2784 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2785 },
2786 want: `{"Aaa":"","Aaa":""}`,
2787 }, {
2788 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict"),
2789 in: structNoCaseInlineTextValue{
2790 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2791 },
2792 want: `{"Aaa":"","AaA":""`,
2793 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"Aaa":"","AaA":""`)),
2794 }, {
2795 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict/AllowDuplicateNames"),
2796 opts: []Options{jsontext.AllowDuplicateNames(true)},
2797 in: structNoCaseInlineTextValue{
2798 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2799 },
2800 want: `{"Aaa":"","AaA":"","aaa":""}`,
2801 }, {
2802 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferentWithField"),
2803 in: structNoCaseInlineTextValue{
2804 AAA: "x",
2805 AaA: "x",
2806 X: jsontext.Value(`{"Aaa": ""}`),
2807 },
2808 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2809 }, {
2810 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflictWithField"),
2811 in: structNoCaseInlineTextValue{
2812 AAA: "x",
2813 AaA: "x",
2814 X: jsontext.Value(`{"AAA": ""}`),
2815 },
2816 want: `{"AAA":"x","AaA":"x"`,
2817 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2818 }, {
2819 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflictWithField"),
2820 in: structNoCaseInlineTextValue{
2821 AAA: "x",
2822 AaA: "x",
2823 X: jsontext.Value(`{"aaa": ""}`),
2824 },
2825 want: `{"AAA":"x","AaA":"x"`,
2826 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2827 }, {
2828 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveDelimiter"),
2829 in: structNoCaseInlineTextValue{
2830 AaA: "x",
2831 X: jsontext.Value(`{"aa_a": ""}`),
2832 },
2833 want: `{"AaA":"x"`,
2834 wantErr: newDuplicateNameError("", []byte(`"aa_a"`), len64(`{"AaA":"x"`)),
2835 }, {
2836 name: jsontest.Name("Structs/DuplicateName/MatchCaseSensitiveDelimiter"),
2837 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
2838 in: structNoCaseInlineTextValue{
2839 AaA: "x",
2840 X: jsontext.Value(`{"aa_a": ""}`),
2841 },
2842 want: `{"AaA":"x","aa_a":""}`,
2843 }, {
2844 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2845 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2846 in: structNoCaseInlineTextValue{
2847 AaA: "x",
2848 X: jsontext.Value(`{"aa_a": ""}`),
2849 },
2850 want: `{"AaA":"x","aa_a":""}`,
2851 }, {
2852 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2853 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2854 in: structNoCaseInlineTextValue{
2855 AA_b: "x",
2856 X: jsontext.Value(`{"aa_b": ""}`),
2857 },
2858 want: `{"AA_b":"x"`,
2859 wantErr: newDuplicateNameError("", []byte(`"aa_b"`), len64(`{"AA_b":"x"`)),
2860 }, {
2861 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferent"),
2862 in: structNoCaseInlineMapStringAny{
2863 X: jsonObject{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""},
2864 },
2865 want: `{"AAA":"","AAa":"","AaA":"","Aaa":""}`,
2866 canonicalize: true,
2867 }, {
2868 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferentWithField"),
2869 in: structNoCaseInlineMapStringAny{
2870 AAA: "x",
2871 AaA: "x",
2872 X: jsonObject{"Aaa": ""},
2873 },
2874 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2875 }, {
2876 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactConflictWithField"),
2877 in: structNoCaseInlineMapStringAny{
2878 AAA: "x",
2879 AaA: "x",
2880 X: jsonObject{"AAA": ""},
2881 },
2882 want: `{"AAA":"x","AaA":"x"`,
2883 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2884 }, {
2885 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/NoCaseConflictWithField"),
2886 in: structNoCaseInlineMapStringAny{
2887 AAA: "x",
2888 AaA: "x",
2889 X: jsonObject{"aaa": ""},
2890 },
2891 want: `{"AAA":"x","AaA":"x"`,
2892 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2893 }, {
2894 name: jsontest.Name("Structs/Invalid/Conflicting"),
2895 in: structConflicting{},
2896 want: ``,
2897 wantErr: EM(errors.New("Go struct fields A and B conflict over JSON object name \"conflict\"")).withType(0, T[structConflicting]()),
2898 }, {
2899 name: jsontest.Name("Structs/Invalid/NoneExported"),
2900 in: structNoneExported{},
2901 want: ``,
2902 wantErr: EM(errNoExportedFields).withType(0, T[structNoneExported]()),
2903 }, {
2904 name: jsontest.Name("Structs/Invalid/MalformedTag"),
2905 in: structMalformedTag{},
2906 want: ``,
2907 wantErr: EM(errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter or single quote)")).withType(0, T[structMalformedTag]()),
2908 }, {
2909 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
2910 in: structUnexportedTag{},
2911 want: ``,
2912 wantErr: EM(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType(0, T[structUnexportedTag]()),
2913 }, {
2914 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
2915 in: structExportedEmbedded{"hello"},
2916 want: ``,
2917 wantErr: EM(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structExportedEmbedded]()),
2918 }, {
2919 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
2920 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2921 in: structExportedEmbedded{"hello"},
2922 want: `{"NamedString":"hello"}`,
2923 }, {
2924 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
2925 in: structExportedEmbeddedTag{"hello"},
2926 want: `{"name":"hello"}`,
2927 }, {
2928 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
2929 in: structUnexportedEmbedded{},
2930 want: ``,
2931 wantErr: EM(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structUnexportedEmbedded]()),
2932 }, {
2933 name: jsontest.Name("Structs/Valid/UnexportedEmbedded"),
2934 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2935 in: structUnexportedEmbedded{},
2936 want: `{}`,
2937 }, {
2938 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedTag"),
2939 in: structUnexportedEmbeddedTag{},
2940 wantErr: EM(errors.New("Go struct field namedString is not exported")).withType(0, T[structUnexportedEmbeddedTag]()),
2941 }, {
2942 name: jsontest.Name("Structs/Valid/UnexportedEmbeddedTag"),
2943 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2944 in: structUnexportedEmbeddedTag{},
2945 want: `{}`,
2946 }, {
2947 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedMethodTag"),
2948 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2949 in: structUnexportedEmbeddedMethodTag{},
2950 want: `{}`,
2951 }, {
2952 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/Zero"),
2953 in: structUnexportedEmbeddedStruct{},
2954 want: `{"FizzBuzz":0,"Addr":""}`,
2955 }, {
2956 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/NonZero"),
2957 in: structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2958 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2959 }, {
2960 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
2961 in: structUnexportedEmbeddedStructPointer{},
2962 want: `{"FizzBuzz":0}`,
2963 }, {
2964 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Zero"),
2965 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{}, 0, &structNestedAddr{}},
2966 want: `{"FizzBuzz":0,"Addr":""}`,
2967 }, {
2968 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/NonZero"),
2969 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2970 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2971 }, {
2972 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
2973 opts: []Options{invalidFormatOption},
2974 in: struct{}{},
2975 want: `{}`,
2976 }, {
2977 name: jsontest.Name("Slices/Interface"),
2978 in: []any{
2979 false, true,
2980 "hello", []byte("world"),
2981 int32(-32), namedInt64(-64),
2982 uint32(+32), namedUint64(+64),
2983 float32(32.32), namedFloat64(64.64),
2984 },
2985 want: `[false,true,"hello","d29ybGQ=",-32,-64,32,64,32.32,64.64]`,
2986 }, {
2987 name: jsontest.Name("Slices/Invalid/Channel"),
2988 in: [](chan string){nil},
2989 want: `[`,
2990 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
2991 }, {
2992 name: jsontest.Name("Slices/RecursiveSlice"),
2993 in: recursiveSlice{
2994 nil,
2995 {},
2996 {nil},
2997 {nil, {}},
2998 },
2999 want: `[[],[],[[]],[[],[]]]`,
3000 }, {
3001 name: jsontest.Name("Slices/CyclicSlice"),
3002 in: func() recursiveSlice {
3003 s := recursiveSlice{{}}
3004 s[0] = s
3005 return s
3006 }(),
3007 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[`,
3008 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat("[", startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter+1))).withType(0, T[recursiveSlice]()),
3009 }, {
3010 name: jsontest.Name("Slices/NonCyclicSlice"),
3011 in: func() []any {
3012 v := []any{nil, nil}
3013 v[1] = v[:1]
3014 for i := 1000; i > 0; i-- {
3015 v = []any{v}
3016 }
3017 return v
3018 }(),
3019 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[null,[null]]` + strings.Repeat(`]`, startDetectingCyclesAfter),
3020 }, {
3021 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
3022 opts: []Options{invalidFormatOption},
3023 in: []string{"hello", "goodbye"},
3024 want: `["hello","goodbye"]`,
3025 }, {
3026 name: jsontest.Name("Arrays/Empty"),
3027 in: [0]struct{}{},
3028 want: `[]`,
3029 }, {
3030 name: jsontest.Name("Arrays/Bool"),
3031 in: [2]bool{false, true},
3032 want: `[false,true]`,
3033 }, {
3034 name: jsontest.Name("Arrays/String"),
3035 in: [2]string{"hello", "goodbye"},
3036 want: `["hello","goodbye"]`,
3037 }, {
3038 name: jsontest.Name("Arrays/Bytes"),
3039 in: [2][]byte{[]byte("hello"), []byte("goodbye")},
3040 want: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
3041 }, {
3042 name: jsontest.Name("Arrays/Int"),
3043 in: [2]int64{math.MinInt64, math.MaxInt64},
3044 want: `[-9223372036854775808,9223372036854775807]`,
3045 }, {
3046 name: jsontest.Name("Arrays/Uint"),
3047 in: [2]uint64{0, math.MaxUint64},
3048 want: `[0,18446744073709551615]`,
3049 }, {
3050 name: jsontest.Name("Arrays/Float"),
3051 in: [2]float64{-math.MaxFloat64, +math.MaxFloat64},
3052 want: `[-1.7976931348623157e+308,1.7976931348623157e+308]`,
3053 }, {
3054 name: jsontest.Name("Arrays/Invalid/Channel"),
3055 in: new([1]chan string),
3056 want: `[`,
3057 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3058 }, {
3059 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
3060 opts: []Options{invalidFormatOption},
3061 in: [2]string{"hello", "goodbye"},
3062 want: `["hello","goodbye"]`,
3063 }, {
3064 name: jsontest.Name("Pointers/NilL0"),
3065 in: (*int)(nil),
3066 want: `null`,
3067 }, {
3068 name: jsontest.Name("Pointers/NilL1"),
3069 in: new(*int),
3070 want: `null`,
3071 }, {
3072 name: jsontest.Name("Pointers/Bool"),
3073 in: addr(addr(bool(true))),
3074 want: `true`,
3075 }, {
3076 name: jsontest.Name("Pointers/String"),
3077 in: addr(addr(string("string"))),
3078 want: `"string"`,
3079 }, {
3080 name: jsontest.Name("Pointers/Bytes"),
3081 in: addr(addr([]byte("bytes"))),
3082 want: `"Ynl0ZXM="`,
3083 }, {
3084 name: jsontest.Name("Pointers/Int"),
3085 in: addr(addr(int(-100))),
3086 want: `-100`,
3087 }, {
3088 name: jsontest.Name("Pointers/Uint"),
3089 in: addr(addr(uint(100))),
3090 want: `100`,
3091 }, {
3092 name: jsontest.Name("Pointers/Float"),
3093 in: addr(addr(float64(3.14159))),
3094 want: `3.14159`,
3095 }, {
3096 name: jsontest.Name("Pointers/CyclicPointer"),
3097 in: func() *recursivePointer {
3098 p := new(recursivePointer)
3099 p.P = p
3100 return p
3101 }(),
3102 want: strings.Repeat(`{"P":`, startDetectingCyclesAfter) + `{"P"`,
3103 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"P":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/P", startDetectingCyclesAfter+1))).withType(0, T[*recursivePointer]()),
3104 }, {
3105 name: jsontest.Name("Pointers/IgnoreInvalidFormat"),
3106 opts: []Options{invalidFormatOption},
3107 in: addr(addr(bool(true))),
3108 want: `true`,
3109 }, {
3110 name: jsontest.Name("Interfaces/Nil/Empty"),
3111 in: [1]any{nil},
3112 want: `[null]`,
3113 }, {
3114 name: jsontest.Name("Interfaces/Nil/NonEmpty"),
3115 in: [1]io.Reader{nil},
3116 want: `[null]`,
3117 }, {
3118 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
3119 opts: []Options{invalidFormatOption},
3120 in: [1]io.Reader{nil},
3121 want: `[null]`,
3122 }, {
3123 name: jsontest.Name("Interfaces/Any"),
3124 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}, [8]byte{}}},
3125 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3126 }, {
3127 name: jsontest.Name("Interfaces/Any/Named"),
3128 in: struct{ X namedAny }{[]namedAny{nil, false, "", 0.0, map[string]namedAny{}, []namedAny{}, [8]byte{}}},
3129 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3130 }, {
3131 name: jsontest.Name("Interfaces/Any/Stringified"),
3132 opts: []Options{StringifyNumbers(true)},
3133 in: struct{ X any }{0.0},
3134 want: `{"X":"0"}`,
3135 }, {
3136 name: jsontest.Name("Interfaces/Any/MarshalFunc/Any"),
3137 opts: []Options{
3138 WithMarshalers(MarshalFunc(func(v any) ([]byte, error) {
3139 return []byte(`"called"`), nil
3140 })),
3141 },
3142 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3143 want: `"called"`,
3144 }, {
3145 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bool"),
3146 opts: []Options{
3147 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3148 return []byte(`"called"`), nil
3149 })),
3150 },
3151 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3152 want: `{"X":[null,"called","",0,{},[]]}`,
3153 }, {
3154 name: jsontest.Name("Interfaces/Any/MarshalFunc/String"),
3155 opts: []Options{
3156 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3157 return []byte(`"called"`), nil
3158 })),
3159 },
3160 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3161 want: `{"X":[null,false,"called",0,{},[]]}`,
3162 }, {
3163 name: jsontest.Name("Interfaces/Any/MarshalFunc/Float64"),
3164 opts: []Options{
3165 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
3166 return []byte(`"called"`), nil
3167 })),
3168 },
3169 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3170 want: `{"X":[null,false,"","called",{},[]]}`,
3171 }, {
3172 name: jsontest.Name("Interfaces/Any/MarshalFunc/MapStringAny"),
3173 opts: []Options{
3174 WithMarshalers(MarshalFunc(func(v map[string]any) ([]byte, error) {
3175 return []byte(`"called"`), nil
3176 })),
3177 },
3178 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3179 want: `{"X":[null,false,"",0,"called",[]]}`,
3180 }, {
3181 name: jsontest.Name("Interfaces/Any/MarshalFunc/SliceAny"),
3182 opts: []Options{
3183 WithMarshalers(MarshalFunc(func(v []any) ([]byte, error) {
3184 return []byte(`"called"`), nil
3185 })),
3186 },
3187 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3188 want: `{"X":"called"}`,
3189 }, {
3190 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bytes"),
3191 opts: []Options{
3192 WithMarshalers(MarshalFunc(func(v [8]byte) ([]byte, error) {
3193 return []byte(`"called"`), nil
3194 })),
3195 },
3196 in: struct{ X any }{[8]byte{}},
3197 want: `{"X":"called"}`,
3198 }, {
3199 name: jsontest.Name("Interfaces/Any/Float/NaN"),
3200 in: struct{ X any }{math.NaN()},
3201 want: `{"X"`,
3202 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, reflect.TypeFor[float64]()).withPos(`{"X":`, "/X"),
3203 }, {
3204 name: jsontest.Name("Interfaces/Any/Maps/Nil"),
3205 in: struct{ X any }{map[string]any(nil)},
3206 want: `{"X":{}}`,
3207 }, {
3208 name: jsontest.Name("Interfaces/Any/Maps/Nil/FormatNilMapAsNull"),
3209 opts: []Options{FormatNilMapAsNull(true)},
3210 in: struct{ X any }{map[string]any(nil)},
3211 want: `{"X":null}`,
3212 }, {
3213 name: jsontest.Name("Interfaces/Any/Maps/Empty"),
3214 in: struct{ X any }{map[string]any{}},
3215 want: `{"X":{}}`,
3216 }, {
3217 name: jsontest.Name("Interfaces/Any/Maps/Empty/Multiline"),
3218 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3219 in: struct{ X any }{map[string]any{}},
3220 want: "{\n\"X\": {}\n}",
3221 }, {
3222 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
3223 in: struct{ X any }{map[string]any{"fizz": "buzz"}},
3224 want: `{"X":{"fizz":"buzz"}}`,
3225 }, {
3226 name: jsontest.Name("Interfaces/Any/Maps/Deterministic"),
3227 opts: []Options{Deterministic(true)},
3228 in: struct{ X any }{map[string]any{"alpha": "", "bravo": ""}},
3229 want: `{"X":{"alpha":"","bravo":""}}`,
3230 }, {
3231 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
3232 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
3233 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3234 want: `{"X":{"�":""`,
3235 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3236 }, {
3237 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
3238 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3239 in: struct{ X any }{map[string]any{"\xff": "alpha", "\xfe": "bravo"}},
3240 want: `{"X":{"�":"bravo","�":"alpha"}}`,
3241 }, {
3242 name: jsontest.Name("Interfaces/Any/Maps/RejectInvalidUTF8"),
3243 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3244 want: `{"X":{`,
3245 wantErr: newInvalidUTF8Error(len64(`{"X":{`), "/X"),
3246 }, {
3247 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+RejectDuplicateNames"),
3248 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3249 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3250 want: `{"X":{"�":""`,
3251 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3252 }, {
3253 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+AllowDuplicateNames"),
3254 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3255 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3256 want: `{"X":{"�":"","�":""}}`,
3257 }, {
3258 name: jsontest.Name("Interfaces/Any/Maps/Cyclic"),
3259 in: func() any {
3260 m := map[string]any{}
3261 m[""] = m
3262 return struct{ X any }{m}
3263 }(),
3264 want: `{"X"` + strings.Repeat(`:{""`, startDetectingCyclesAfter),
3265 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`{"":`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/", startDetectingCyclesAfter))).withType(0, T[map[string]any]()),
3266 }, {
3267 name: jsontest.Name("Interfaces/Any/Slices/Nil"),
3268 in: struct{ X any }{[]any(nil)},
3269 want: `{"X":[]}`,
3270 }, {
3271 name: jsontest.Name("Interfaces/Any/Slices/Nil/FormatNilSliceAsNull"),
3272 opts: []Options{FormatNilSliceAsNull(true)},
3273 in: struct{ X any }{[]any(nil)},
3274 want: `{"X":null}`,
3275 }, {
3276 name: jsontest.Name("Interfaces/Any/Slices/Empty"),
3277 in: struct{ X any }{[]any{}},
3278 want: `{"X":[]}`,
3279 }, {
3280 name: jsontest.Name("Interfaces/Any/Slices/Empty/Multiline"),
3281 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3282 in: struct{ X any }{[]any{}},
3283 want: "{\n\"X\": []\n}",
3284 }, {
3285 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
3286 in: struct{ X any }{[]any{"fizz", "buzz"}},
3287 want: `{"X":["fizz","buzz"]}`,
3288 }, {
3289 name: jsontest.Name("Interfaces/Any/Slices/Cyclic"),
3290 in: func() any {
3291 s := make([]any, 1)
3292 s[0] = s
3293 return struct{ X any }{s}
3294 }(),
3295 want: `{"X":` + strings.Repeat(`[`, startDetectingCyclesAfter),
3296 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`[`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter))).withType(0, T[[]any]()),
3297 }, {
3298 name: jsontest.Name("Methods/NilPointer"),
3299 in: struct{ X *allMethods }{X: (*allMethods)(nil)},
3300 want: `{"X":null}`,
3301 }, {
3302
3303 name: jsontest.Name("Methods/NilInterface"),
3304 in: struct{ X MarshalerTo }{X: (*allMethods)(nil)},
3305 want: `{"X":null}`,
3306 }, {
3307 name: jsontest.Name("Methods/AllMethods"),
3308 in: struct{ X *allMethods }{X: &allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3309 want: `{"X":"hello"}`,
3310 }, {
3311 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
3312 in: struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3313 want: `{"X":"hello"}`,
3314 }, {
3315 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
3316 in: struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3317 want: `{"X":"hello"}`,
3318 }, {
3319 name: jsontest.Name("Methods/AllMethodsExceptText"),
3320 in: struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3321 want: `{"X":"hello"}`,
3322 }, {
3323 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
3324 in: struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3325 want: `{"X":"hello"}`,
3326 }, {
3327 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
3328 in: struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3329 want: `{"X":"hello"}`,
3330 }, {
3331 name: jsontest.Name("Methods/OnlyMethodText"),
3332 in: struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "MarshalText", value: []byte(`hello`)}}},
3333 want: `{"X":"hello"}`,
3334 }, {
3335 name: jsontest.Name("Methods/IP"),
3336 in: net.IPv4(192, 168, 0, 100),
3337 want: `"192.168.0.100"`,
3338 }, {
3339 name: jsontest.Name("Methods/NetIP"),
3340 in: struct {
3341 Addr netip.Addr
3342 AddrPort netip.AddrPort
3343 Prefix netip.Prefix
3344 }{
3345 Addr: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
3346 AddrPort: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 1234),
3347 Prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
3348 },
3349 want: `{"Addr":"1.2.3.4","AddrPort":"1.2.3.4:1234","Prefix":"1.2.3.4/24"}`,
3350 }, {
3351
3352 name: jsontest.Name("Methods/Anonymous"),
3353 in: struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3354 want: `{"X":"hello"}`,
3355 }, {
3356
3357 name: jsontest.Name("Methods/Addressable"),
3358 in: struct {
3359 V allMethods
3360 M map[string]allMethods
3361 I any
3362 }{
3363 V: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3364 M: map[string]allMethods{"K": {method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3365 I: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3366 },
3367 want: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
3368 }, {
3369
3370 name: jsontest.Name("Methods/MapKey/JSONv2"),
3371 in: map[structMethodJSONv2]string{{"k1"}: "v1", {"k2"}: "v2"},
3372 want: `{"k1":"v1","k2":"v2"}`,
3373 canonicalize: true,
3374 }, {
3375
3376 name: jsontest.Name("Methods/MapKey/JSONv1"),
3377 in: map[structMethodJSONv1]string{{"k1"}: "v1", {"k2"}: "v2"},
3378 want: `{"k1":"v1","k2":"v2"}`,
3379 canonicalize: true,
3380 }, {
3381 name: jsontest.Name("Methods/MapKey/Text"),
3382 in: map[structMethodText]string{{"k1"}: "v1", {"k2"}: "v2"},
3383 want: `{"k1":"v1","k2":"v2"}`,
3384 canonicalize: true,
3385 }, {
3386 name: jsontest.Name("Methods/JSONv2/ErrUnsupported"),
3387 opts: []Options{Deterministic(true)},
3388 in: unsupportedMethodJSONv2{"fizz": 123},
3389 want: `{"called":1,"fizz":123}`,
3390 }, {
3391 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
3392 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3393 return errSomeError
3394 }),
3395 wantErr: EM(errSomeError).withType(0, T[marshalJSONv2Func]()),
3396 }, {
3397 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
3398 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3399 return nil
3400 }),
3401 wantErr: EM(errNonSingularValue).withType(0, T[marshalJSONv2Func]()),
3402 }, {
3403 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
3404 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3405 enc.WriteToken(jsontext.Null)
3406 enc.WriteToken(jsontext.Null)
3407 return nil
3408 }),
3409 want: `nullnull`,
3410 wantErr: EM(errNonSingularValue).withPos(`nullnull`, "").withType(0, T[marshalJSONv2Func]()),
3411 }, {
3412 name: jsontest.Name("Methods/Invalid/JSONv2/ErrUnsupported"),
3413 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3414 return errors.ErrUnsupported
3415 }),
3416 wantErr: EM(nil).withType(0, T[marshalJSONv2Func]()),
3417 }, {
3418 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
3419 in: marshalJSONv1Func(func() ([]byte, error) {
3420 return nil, errSomeError
3421 }),
3422 wantErr: EM(errSomeError).withType(0, T[marshalJSONv1Func]()),
3423 }, {
3424 name: jsontest.Name("Methods/Invalid/JSONv1/Syntax"),
3425 in: marshalJSONv1Func(func() ([]byte, error) {
3426 return []byte("invalid"), nil
3427 }),
3428 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[marshalJSONv1Func]()),
3429 }, {
3430 name: jsontest.Name("Methods/Invalid/JSONv1/ErrUnsupported"),
3431 in: marshalJSONv1Func(func() ([]byte, error) {
3432 return nil, errors.ErrUnsupported
3433 }),
3434 wantErr: EM(errors.New("MarshalJSON method may not return errors.ErrUnsupported")).withType(0, T[marshalJSONv1Func]()),
3435 }, {
3436 name: jsontest.Name("Methods/AppendText"),
3437 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), nil }),
3438 want: `"hello"`,
3439 }, {
3440 name: jsontest.Name("Methods/AppendText/Error"),
3441 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), errSomeError }),
3442 wantErr: EM(errSomeError).withType(0, T[appendTextFunc]()),
3443 }, {
3444 name: jsontest.Name("Methods/AppendText/NeedEscape"),
3445 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, `"`...), nil }),
3446 want: `"\""`,
3447 }, {
3448 name: jsontest.Name("Methods/AppendText/RejectInvalidUTF8"),
3449 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3450 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[appendTextFunc]()),
3451 }, {
3452 name: jsontest.Name("Methods/AppendText/AllowInvalidUTF8"),
3453 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3454 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3455 want: "\"\xde\xad\ufffd\ufffd\"",
3456 }, {
3457 name: jsontest.Name("Methods/Invalid/Text/Error"),
3458 in: marshalTextFunc(func() ([]byte, error) {
3459 return nil, errSomeError
3460 }),
3461 wantErr: EM(errSomeError).withType(0, T[marshalTextFunc]()),
3462 }, {
3463 name: jsontest.Name("Methods/Text/RejectInvalidUTF8"),
3464 in: marshalTextFunc(func() ([]byte, error) {
3465 return []byte("\xde\xad\xbe\xef"), nil
3466 }),
3467 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[marshalTextFunc]()),
3468 }, {
3469 name: jsontest.Name("Methods/Text/AllowInvalidUTF8"),
3470 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3471 in: marshalTextFunc(func() ([]byte, error) {
3472 return []byte("\xde\xad\xbe\xef"), nil
3473 }),
3474 want: "\"\xde\xad\ufffd\ufffd\"",
3475 }, {
3476 name: jsontest.Name("Methods/Invalid/Text/ErrUnsupported"),
3477 in: marshalTextFunc(func() ([]byte, error) {
3478 return nil, errors.ErrUnsupported
3479 }),
3480 wantErr: EM(wrapErrUnsupported(errors.ErrUnsupported, "MarshalText method")).withType(0, T[marshalTextFunc]()),
3481 }, {
3482 name: jsontest.Name("Methods/Invalid/MapKey/JSONv2/Syntax"),
3483 in: map[any]string{
3484 addr(marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3485 return enc.WriteToken(jsontext.Null)
3486 })): "invalid",
3487 },
3488 want: `{`,
3489 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv2Func]()),
3490 }, {
3491 name: jsontest.Name("Methods/Invalid/MapKey/JSONv1/Syntax"),
3492 in: map[any]string{
3493 addr(marshalJSONv1Func(func() ([]byte, error) {
3494 return []byte(`null`), nil
3495 })): "invalid",
3496 },
3497 want: `{`,
3498 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv1Func]()),
3499 }, {
3500 name: jsontest.Name("Functions/Bool/V1"),
3501 opts: []Options{
3502 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3503 return []byte(`"called"`), nil
3504 })),
3505 },
3506 in: true,
3507 want: `"called"`,
3508 }, {
3509 name: jsontest.Name("Functions/Bool/Empty"),
3510 opts: []Options{WithMarshalers(nil)},
3511 in: true,
3512 want: `true`,
3513 }, {
3514 name: jsontest.Name("Functions/NamedBool/V1/NoMatch"),
3515 opts: []Options{
3516 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3517 return nil, errMustNotCall
3518 })),
3519 },
3520 in: true,
3521 want: `true`,
3522 }, {
3523 name: jsontest.Name("Functions/NamedBool/V1/Match"),
3524 opts: []Options{
3525 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3526 return []byte(`"called"`), nil
3527 })),
3528 },
3529 in: namedBool(true),
3530 want: `"called"`,
3531 }, {
3532 name: jsontest.Name("Functions/PointerBool/V1/Match"),
3533 opts: []Options{
3534 WithMarshalers(MarshalFunc(func(v *bool) ([]byte, error) {
3535 _ = *v
3536 return []byte(`"called"`), nil
3537 })),
3538 },
3539 in: true,
3540 want: `"called"`,
3541 }, {
3542 name: jsontest.Name("Functions/Bool/V2"),
3543 opts: []Options{
3544 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3545 return enc.WriteToken(jsontext.String("called"))
3546 })),
3547 },
3548 in: true,
3549 want: `"called"`,
3550 }, {
3551 name: jsontest.Name("Functions/NamedBool/V2/NoMatch"),
3552 opts: []Options{
3553 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3554 return errMustNotCall
3555 })),
3556 },
3557 in: true,
3558 want: `true`,
3559 }, {
3560 name: jsontest.Name("Functions/NamedBool/V2/Match"),
3561 opts: []Options{
3562 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3563 return enc.WriteToken(jsontext.String("called"))
3564 })),
3565 },
3566 in: namedBool(true),
3567 want: `"called"`,
3568 }, {
3569 name: jsontest.Name("Functions/PointerBool/V2/Match"),
3570 opts: []Options{
3571 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3572 _ = *v
3573 return enc.WriteToken(jsontext.String("called"))
3574 })),
3575 },
3576 in: true,
3577 want: `"called"`,
3578 }, {
3579 name: jsontest.Name("Functions/Bool/Empty1/NoMatch"),
3580 opts: []Options{
3581 WithMarshalers(new(Marshalers)),
3582 },
3583 in: true,
3584 want: `true`,
3585 }, {
3586 name: jsontest.Name("Functions/Bool/Empty2/NoMatch"),
3587 opts: []Options{
3588 WithMarshalers(JoinMarshalers()),
3589 },
3590 in: true,
3591 want: `true`,
3592 }, {
3593 name: jsontest.Name("Functions/Bool/V1/DirectError"),
3594 opts: []Options{
3595 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3596 return nil, errSomeError
3597 })),
3598 },
3599 in: true,
3600 wantErr: EM(errSomeError).withType(0, T[bool]()),
3601 }, {
3602 name: jsontest.Name("Functions/Bool/V1/SkipError"),
3603 opts: []Options{
3604 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3605 return nil, errors.ErrUnsupported
3606 })),
3607 },
3608 in: true,
3609 wantErr: EM(wrapErrUnsupported(errors.ErrUnsupported, "marshal function of type func(T) ([]byte, error)")).withType(0, T[bool]()),
3610 }, {
3611 name: jsontest.Name("Functions/Bool/V1/InvalidValue"),
3612 opts: []Options{
3613 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3614 return []byte("invalid"), nil
3615 })),
3616 },
3617 in: true,
3618 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[bool]()),
3619 }, {
3620 name: jsontest.Name("Functions/Bool/V2/DirectError"),
3621 opts: []Options{
3622 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3623 return errSomeError
3624 })),
3625 },
3626 in: true,
3627 wantErr: EM(errSomeError).withType(0, T[bool]()),
3628 }, {
3629 name: jsontest.Name("Functions/Bool/V2/TooFew"),
3630 opts: []Options{
3631 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3632 return nil
3633 })),
3634 },
3635 in: true,
3636 wantErr: EM(errNonSingularValue).withType(0, T[bool]()),
3637 }, {
3638 name: jsontest.Name("Functions/Bool/V2/TooMany"),
3639 opts: []Options{
3640 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3641 enc.WriteValue([]byte(`"hello"`))
3642 enc.WriteValue([]byte(`"world"`))
3643 return nil
3644 })),
3645 },
3646 in: true,
3647 want: `"hello""world"`,
3648 wantErr: EM(errNonSingularValue).withPos(`"hello""world"`, "").withType(0, T[bool]()),
3649 }, {
3650 name: jsontest.Name("Functions/Bool/V2/Skipped"),
3651 opts: []Options{
3652 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3653 return errors.ErrUnsupported
3654 })),
3655 },
3656 in: true,
3657 want: `true`,
3658 }, {
3659 name: jsontest.Name("Functions/Bool/V2/ProcessBeforeSkip"),
3660 opts: []Options{
3661 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3662 enc.WriteValue([]byte(`"hello"`))
3663 return errors.ErrUnsupported
3664 })),
3665 },
3666 in: true,
3667 want: `"hello"`,
3668 wantErr: EM(errUnsupportedMutation).withPos(`"hello"`, "").withType(0, T[bool]()),
3669 }, {
3670 name: jsontest.Name("Functions/Bool/V2/WrappedUnsupportedError"),
3671 opts: []Options{
3672 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3673 return fmt.Errorf("wrap: %w", errors.ErrUnsupported)
3674 })),
3675 },
3676 in: true,
3677 want: `true`,
3678 }, {
3679 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
3680 opts: []Options{
3681 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3682 return []byte(`"called"`), nil
3683 })),
3684 },
3685 in: map[nocaseString]string{"hello": "world"},
3686 want: `{"called":"world"}`,
3687 }, {
3688 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V1"),
3689 opts: []Options{
3690 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3691 _ = *v
3692 return []byte(`"called"`), nil
3693 })),
3694 },
3695 in: map[nocaseString]string{"hello": "world"},
3696 want: `{"called":"world"}`,
3697 }, {
3698 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
3699 opts: []Options{
3700 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3701 _ = *v.(*nocaseString)
3702 return []byte(`"called"`), nil
3703 })),
3704 },
3705 in: map[nocaseString]string{"hello": "world"},
3706 want: `{"called":"world"}`,
3707 }, {
3708 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1/InvalidValue"),
3709 opts: []Options{
3710 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3711 return []byte(`null`), nil
3712 })),
3713 },
3714 in: map[nocaseString]string{"hello": "world"},
3715 want: `{`,
3716 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3717 }, {
3718 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidKind"),
3719 opts: []Options{
3720 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3721 return []byte(`null`), nil
3722 })),
3723 },
3724 in: map[nocaseString]string{"hello": "world"},
3725 want: `{`,
3726 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3727 }, {
3728 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
3729 opts: []Options{
3730 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3731 return []byte(`"name"`), nil
3732 })),
3733 },
3734 in: map[string]string{"name1": "value", "name2": "value"},
3735 want: `{"name":"name"`,
3736 wantErr: EM(newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"name",`))).
3737 withPos(`{"name":"name",`, "").withType(0, T[string]()),
3738 }, {
3739 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
3740 opts: []Options{
3741 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3742 return enc.WriteValue([]byte(`"called"`))
3743 })),
3744 },
3745 in: map[nocaseString]string{"hello": "world"},
3746 want: `{"called":"world"}`,
3747 }, {
3748 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V2"),
3749 opts: []Options{
3750 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3751 _ = *v
3752 return enc.WriteValue([]byte(`"called"`))
3753 })),
3754 },
3755 in: map[nocaseString]string{"hello": "world"},
3756 want: `{"called":"world"}`,
3757 }, {
3758 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
3759 opts: []Options{
3760 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3761 _ = *v.(*nocaseString)
3762 return enc.WriteValue([]byte(`"called"`))
3763 })),
3764 },
3765 in: map[nocaseString]string{"hello": "world"},
3766 want: `{"called":"world"}`,
3767 }, {
3768 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidToken"),
3769 opts: []Options{
3770 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3771 return enc.WriteToken(jsontext.Null)
3772 })),
3773 },
3774 in: map[nocaseString]string{"hello": "world"},
3775 want: `{`,
3776 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3777 }, {
3778 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidValue"),
3779 opts: []Options{
3780 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3781 return enc.WriteValue([]byte(`null`))
3782 })),
3783 },
3784 in: map[nocaseString]string{"hello": "world"},
3785 want: `{`,
3786 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3787 }, {
3788 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
3789 opts: []Options{
3790 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3791 return []byte(`"called"`), nil
3792 })),
3793 },
3794 in: map[string]nocaseString{"hello": "world"},
3795 want: `{"hello":"called"}`,
3796 }, {
3797 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V1"),
3798 opts: []Options{
3799 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3800 _ = *v
3801 return []byte(`"called"`), nil
3802 })),
3803 },
3804 in: map[string]nocaseString{"hello": "world"},
3805 want: `{"hello":"called"}`,
3806 }, {
3807 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
3808 opts: []Options{
3809 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3810 _ = *v.(*nocaseString)
3811 return []byte(`"called"`), nil
3812 })),
3813 },
3814 in: map[string]nocaseString{"hello": "world"},
3815 want: `{"hello":"called"}`,
3816 }, {
3817 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
3818 opts: []Options{
3819 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3820 return enc.WriteValue([]byte(`"called"`))
3821 })),
3822 },
3823 in: map[string]nocaseString{"hello": "world"},
3824 want: `{"hello":"called"}`,
3825 }, {
3826 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V2"),
3827 opts: []Options{
3828 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3829 _ = *v
3830 return enc.WriteValue([]byte(`"called"`))
3831 })),
3832 },
3833 in: map[string]nocaseString{"hello": "world"},
3834 want: `{"hello":"called"}`,
3835 }, {
3836 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
3837 opts: []Options{
3838 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3839 _ = *v.(*nocaseString)
3840 return enc.WriteValue([]byte(`"called"`))
3841 })),
3842 },
3843 in: map[string]nocaseString{"hello": "world"},
3844 want: `{"hello":"called"}`,
3845 }, {
3846 name: jsontest.Name("Funtions/Struct/Fields"),
3847 opts: []Options{
3848 WithMarshalers(JoinMarshalers(
3849 MarshalFunc(func(v bool) ([]byte, error) {
3850 return []byte(`"called1"`), nil
3851 }),
3852 MarshalFunc(func(v *string) ([]byte, error) {
3853 return []byte(`"called2"`), nil
3854 }),
3855 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3856 return enc.WriteValue([]byte(`"called3"`))
3857 }),
3858 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3859 return enc.WriteValue([]byte(`"called4"`))
3860 }),
3861 )),
3862 },
3863 in: structScalars{},
3864 want: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":0,"Float":0}`,
3865 }, {
3866 name: jsontest.Name("Functions/Struct/OmitEmpty"),
3867 opts: []Options{
3868 WithMarshalers(JoinMarshalers(
3869 MarshalFunc(func(v bool) ([]byte, error) {
3870 return []byte(`null`), nil
3871 }),
3872 MarshalFunc(func(v string) ([]byte, error) {
3873 return []byte(`"called1"`), nil
3874 }),
3875 MarshalFunc(func(v *stringMarshalNonEmpty) ([]byte, error) {
3876 return []byte(`""`), nil
3877 }),
3878 MarshalToFunc(func(enc *jsontext.Encoder, v bytesMarshalNonEmpty) error {
3879 return enc.WriteValue([]byte(`{}`))
3880 }),
3881 MarshalToFunc(func(enc *jsontext.Encoder, v *float64) error {
3882 return enc.WriteValue([]byte(`[]`))
3883 }),
3884 MarshalFunc(func(v mapMarshalNonEmpty) ([]byte, error) {
3885 return []byte(`"called2"`), nil
3886 }),
3887 MarshalFunc(func(v []string) ([]byte, error) {
3888 return []byte(`"called3"`), nil
3889 }),
3890 MarshalToFunc(func(enc *jsontext.Encoder, v *sliceMarshalNonEmpty) error {
3891 return enc.WriteValue([]byte(`"called4"`))
3892 }),
3893 )),
3894 },
3895 in: structOmitEmptyAll{},
3896 want: `{"String":"called1","MapNonEmpty":"called2","Slice":"called3","SliceNonEmpty":"called4"}`,
3897 }, {
3898 name: jsontest.Name("Functions/Struct/OmitZero"),
3899 opts: []Options{
3900 WithMarshalers(JoinMarshalers(
3901 MarshalFunc(func(v bool) ([]byte, error) {
3902 panic("should not be called")
3903 }),
3904 MarshalFunc(func(v *string) ([]byte, error) {
3905 panic("should not be called")
3906 }),
3907 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3908 panic("should not be called")
3909 }),
3910 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3911 panic("should not be called")
3912 }),
3913 )),
3914 },
3915 in: structOmitZeroAll{},
3916 want: `{}`,
3917 }, {
3918 name: jsontest.Name("Functions/Struct/Inlined"),
3919 opts: []Options{
3920 WithMarshalers(JoinMarshalers(
3921 MarshalFunc(func(v structInlinedL1) ([]byte, error) {
3922 panic("should not be called")
3923 }),
3924 MarshalToFunc(func(enc *jsontext.Encoder, v *StructEmbed2) error {
3925 panic("should not be called")
3926 }),
3927 )),
3928 },
3929 in: structInlined{},
3930 want: `{"D":""}`,
3931 }, {
3932 name: jsontest.Name("Functions/Slice/Elem"),
3933 opts: []Options{
3934 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3935 return []byte(`"` + strconv.FormatBool(v) + `"`), nil
3936 })),
3937 },
3938 in: []bool{true, false},
3939 want: `["true","false"]`,
3940 }, {
3941 name: jsontest.Name("Functions/Array/Elem"),
3942 opts: []Options{
3943 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3944 return enc.WriteValue([]byte(`"` + strconv.FormatBool(*v) + `"`))
3945 })),
3946 },
3947 in: [2]bool{true, false},
3948 want: `["true","false"]`,
3949 }, {
3950 name: jsontest.Name("Functions/Pointer/Nil"),
3951 opts: []Options{
3952 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3953 panic("should not be called")
3954 })),
3955 },
3956 in: struct{ X *bool }{nil},
3957 want: `{"X":null}`,
3958 }, {
3959 name: jsontest.Name("Functions/Pointer/NonNil"),
3960 opts: []Options{
3961 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3962 return enc.WriteValue([]byte(`"called"`))
3963 })),
3964 },
3965 in: struct{ X *bool }{addr(false)},
3966 want: `{"X":"called"}`,
3967 }, {
3968 name: jsontest.Name("Functions/Interface/Nil"),
3969 opts: []Options{
3970 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
3971 panic("should not be called")
3972 })),
3973 },
3974 in: struct{ X fmt.Stringer }{nil},
3975 want: `{"X":null}`,
3976 }, {
3977 name: jsontest.Name("Functions/Interface/NonNil/MatchInterface"),
3978 opts: []Options{
3979 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
3980 return enc.WriteValue([]byte(`"called"`))
3981 })),
3982 },
3983 in: struct{ X fmt.Stringer }{valueStringer{}},
3984 want: `{"X":"called"}`,
3985 }, {
3986 name: jsontest.Name("Functions/Interface/NonNil/MatchConcrete"),
3987 opts: []Options{
3988 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
3989 return enc.WriteValue([]byte(`"called"`))
3990 })),
3991 },
3992 in: struct{ X fmt.Stringer }{valueStringer{}},
3993 want: `{"X":"called"}`,
3994 }, {
3995 name: jsontest.Name("Functions/Interface/NonNil/MatchPointer"),
3996 opts: []Options{
3997 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
3998 return enc.WriteValue([]byte(`"called"`))
3999 })),
4000 },
4001 in: struct{ X fmt.Stringer }{valueStringer{}},
4002 want: `{"X":"called"}`,
4003 }, {
4004 name: jsontest.Name("Functions/Interface/Any"),
4005 in: []any{
4006 nil,
4007 valueStringer{},
4008 (*valueStringer)(nil),
4009 addr(valueStringer{}),
4010 (**valueStringer)(nil),
4011 addr((*valueStringer)(nil)),
4012 addr(addr(valueStringer{})),
4013 pointerStringer{},
4014 (*pointerStringer)(nil),
4015 addr(pointerStringer{}),
4016 (**pointerStringer)(nil),
4017 addr((*pointerStringer)(nil)),
4018 addr(addr(pointerStringer{})),
4019 "LAST",
4020 },
4021 want: `[null,{},null,{},null,null,{},{},null,{},null,null,{},"LAST"]`,
4022 opts: []Options{
4023 WithMarshalers(func() *Marshalers {
4024 type P struct {
4025 D int
4026 N int64
4027 }
4028 type PV struct {
4029 P P
4030 V any
4031 }
4032
4033 var lastChecks []func() error
4034 checkLast := func() error {
4035 for _, fn := range lastChecks {
4036 if err := fn(); err != nil {
4037 return err
4038 }
4039 }
4040 return errors.ErrUnsupported
4041 }
4042 makeValueChecker := func(name string, want []PV) func(e *jsontext.Encoder, v any) error {
4043 checkNext := func(e *jsontext.Encoder, v any) error {
4044 xe := export.Encoder(e)
4045 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4046 rv := reflect.ValueOf(v)
4047 pv := PV{p, v}
4048 switch {
4049 case len(want) == 0:
4050 return fmt.Errorf("%s: %v: got more values than expected", name, p)
4051 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
4052 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
4053 case !reflect.DeepEqual(pv, want[0]):
4054 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
4055 default:
4056 want = want[1:]
4057 return errors.ErrUnsupported
4058 }
4059 }
4060 lastChecks = append(lastChecks, func() error {
4061 if len(want) > 0 {
4062 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4063 }
4064 return nil
4065 })
4066 return checkNext
4067 }
4068 makePositionChecker := func(name string, want []P) func(e *jsontext.Encoder, v any) error {
4069 checkNext := func(e *jsontext.Encoder, v any) error {
4070 xe := export.Encoder(e)
4071 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4072 switch {
4073 case len(want) == 0:
4074 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
4075 case p != want[0]:
4076 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
4077 default:
4078 want = want[1:]
4079 return errors.ErrUnsupported
4080 }
4081 }
4082 lastChecks = append(lastChecks, func() error {
4083 if len(want) > 0 {
4084 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4085 }
4086 return nil
4087 })
4088 return checkNext
4089 }
4090
4091 wantAny := []PV{
4092 {P{0, 0}, addr([]any{
4093 nil,
4094 valueStringer{},
4095 (*valueStringer)(nil),
4096 addr(valueStringer{}),
4097 (**valueStringer)(nil),
4098 addr((*valueStringer)(nil)),
4099 addr(addr(valueStringer{})),
4100 pointerStringer{},
4101 (*pointerStringer)(nil),
4102 addr(pointerStringer{}),
4103 (**pointerStringer)(nil),
4104 addr((*pointerStringer)(nil)),
4105 addr(addr(pointerStringer{})),
4106 "LAST",
4107 })},
4108 {P{1, 0}, addr(any(nil))},
4109 {P{1, 1}, addr(any(valueStringer{}))},
4110 {P{1, 1}, addr(valueStringer{})},
4111 {P{1, 2}, addr(any((*valueStringer)(nil)))},
4112 {P{1, 2}, addr((*valueStringer)(nil))},
4113 {P{1, 3}, addr(any(addr(valueStringer{})))},
4114 {P{1, 3}, addr(addr(valueStringer{}))},
4115 {P{1, 3}, addr(valueStringer{})},
4116 {P{1, 4}, addr(any((**valueStringer)(nil)))},
4117 {P{1, 4}, addr((**valueStringer)(nil))},
4118 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
4119 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
4120 {P{1, 5}, addr((*valueStringer)(nil))},
4121 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
4122 {P{1, 6}, addr(addr(addr(valueStringer{})))},
4123 {P{1, 6}, addr(addr(valueStringer{}))},
4124 {P{1, 6}, addr(valueStringer{})},
4125 {P{1, 7}, addr(any(pointerStringer{}))},
4126 {P{1, 7}, addr(pointerStringer{})},
4127 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
4128 {P{1, 8}, addr((*pointerStringer)(nil))},
4129 {P{1, 9}, addr(any(addr(pointerStringer{})))},
4130 {P{1, 9}, addr(addr(pointerStringer{}))},
4131 {P{1, 9}, addr(pointerStringer{})},
4132 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
4133 {P{1, 10}, addr((**pointerStringer)(nil))},
4134 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
4135 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
4136 {P{1, 11}, addr((*pointerStringer)(nil))},
4137 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
4138 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
4139 {P{1, 12}, addr(addr(pointerStringer{}))},
4140 {P{1, 12}, addr(pointerStringer{})},
4141 {P{1, 13}, addr(any("LAST"))},
4142 {P{1, 13}, addr("LAST")},
4143 }
4144 checkAny := makeValueChecker("any", wantAny)
4145 anyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v any) error {
4146 return checkAny(enc, v)
4147 })
4148
4149 var wantPointerAny []PV
4150 for _, v := range wantAny {
4151 if _, ok := v.V.(*any); ok {
4152 wantPointerAny = append(wantPointerAny, v)
4153 }
4154 }
4155 checkPointerAny := makeValueChecker("*any", wantPointerAny)
4156 pointerAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *any) error {
4157 return checkPointerAny(enc, v)
4158 })
4159
4160 checkNamedAny := makeValueChecker("namedAny", wantAny)
4161 namedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v namedAny) error {
4162 return checkNamedAny(enc, v)
4163 })
4164
4165 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
4166 pointerNamedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *namedAny) error {
4167 return checkPointerNamedAny(enc, v)
4168 })
4169
4170 type stringer = fmt.Stringer
4171 var wantStringer []PV
4172 for _, v := range wantAny {
4173 if _, ok := v.V.(stringer); ok {
4174 wantStringer = append(wantStringer, v)
4175 }
4176 }
4177 checkStringer := makeValueChecker("stringer", wantStringer)
4178 stringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v stringer) error {
4179 return checkStringer(enc, v)
4180 })
4181
4182 checkPointerStringer := makeValueChecker("*stringer", nil)
4183 pointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *stringer) error {
4184 return checkPointerStringer(enc, v)
4185 })
4186
4187 wantValueStringer := []P{{1, 1}, {1, 3}, {1, 6}}
4188 checkValueValueStringer := makePositionChecker("valueStringer", wantValueStringer)
4189 valueValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4190 return checkValueValueStringer(enc, v)
4191 })
4192
4193 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
4194 pointerValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4195 return checkPointerValueStringer(enc, v)
4196 })
4197
4198 wantPointerStringer := []P{{1, 7}, {1, 9}, {1, 12}}
4199 checkValuePointerStringer := makePositionChecker("pointerStringer", wantPointerStringer)
4200 valuePointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v pointerStringer) error {
4201 return checkValuePointerStringer(enc, v)
4202 })
4203
4204 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
4205 pointerPointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *pointerStringer) error {
4206 return checkPointerPointerStringer(enc, v)
4207 })
4208
4209 lastMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
4210 return checkLast()
4211 })
4212
4213 return JoinMarshalers(
4214 anyMarshaler,
4215 pointerAnyMarshaler,
4216 namedAnyMarshaler,
4217 pointerNamedAnyMarshaler,
4218 stringerMarshaler,
4219 pointerStringerMarshaler,
4220 valueValueStringerMarshaler,
4221 pointerValueStringerMarshaler,
4222 valuePointerStringerMarshaler,
4223 pointerPointerStringerMarshaler,
4224 lastMarshaler,
4225 )
4226 }()),
4227 },
4228 }, {
4229 name: jsontest.Name("Functions/Precedence/V1First"),
4230 opts: []Options{
4231 WithMarshalers(JoinMarshalers(
4232 MarshalFunc(func(bool) ([]byte, error) {
4233 return []byte(`"called"`), nil
4234 }),
4235 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4236 panic("should not be called")
4237 }),
4238 )),
4239 },
4240 in: true,
4241 want: `"called"`,
4242 }, {
4243 name: jsontest.Name("Functions/Precedence/V2First"),
4244 opts: []Options{
4245 WithMarshalers(JoinMarshalers(
4246 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4247 return enc.WriteToken(jsontext.String("called"))
4248 }),
4249 MarshalFunc(func(bool) ([]byte, error) {
4250 panic("should not be called")
4251 }),
4252 )),
4253 },
4254 in: true,
4255 want: `"called"`,
4256 }, {
4257 name: jsontest.Name("Functions/Precedence/V2Skipped"),
4258 opts: []Options{
4259 WithMarshalers(JoinMarshalers(
4260 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4261 return errors.ErrUnsupported
4262 }),
4263 MarshalFunc(func(bool) ([]byte, error) {
4264 return []byte(`"called"`), nil
4265 }),
4266 )),
4267 },
4268 in: true,
4269 want: `"called"`,
4270 }, {
4271 name: jsontest.Name("Functions/Precedence/NestedFirst"),
4272 opts: []Options{
4273 WithMarshalers(JoinMarshalers(
4274 JoinMarshalers(
4275 MarshalFunc(func(bool) ([]byte, error) {
4276 return []byte(`"called"`), nil
4277 }),
4278 ),
4279 MarshalFunc(func(bool) ([]byte, error) {
4280 panic("should not be called")
4281 }),
4282 )),
4283 },
4284 in: true,
4285 want: `"called"`,
4286 }, {
4287 name: jsontest.Name("Functions/Precedence/NestedLast"),
4288 opts: []Options{
4289 WithMarshalers(JoinMarshalers(
4290 MarshalFunc(func(bool) ([]byte, error) {
4291 return []byte(`"called"`), nil
4292 }),
4293 JoinMarshalers(
4294 MarshalFunc(func(bool) ([]byte, error) {
4295 panic("should not be called")
4296 }),
4297 ),
4298 )),
4299 },
4300 in: true,
4301 want: `"called"`,
4302 }, {
4303 name: jsontest.Name("Duration/Zero"),
4304 in: struct {
4305 D1 time.Duration `json:",format:units"`
4306 D2 time.Duration `json:",format:nano"`
4307 }{0, 0},
4308 want: `{"D1":"0s","D2":0}`,
4309 }, {
4310 name: jsontest.Name("Duration/Positive"),
4311 in: struct {
4312 D1 time.Duration `json:",format:units"`
4313 D2 time.Duration `json:",format:nano"`
4314 }{
4315 123456789123456789,
4316 123456789123456789,
4317 },
4318 want: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
4319 }, {
4320 name: jsontest.Name("Duration/Negative"),
4321 in: struct {
4322 D1 time.Duration `json:",format:units"`
4323 D2 time.Duration `json:",format:nano"`
4324 }{
4325 -123456789123456789,
4326 -123456789123456789,
4327 },
4328 want: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
4329 }, {
4330 name: jsontest.Name("Duration/Nanos/String"),
4331 in: struct {
4332 D1 time.Duration `json:",string,format:nano"`
4333 D2 time.Duration `json:",string,format:nano"`
4334 D3 time.Duration `json:",string,format:nano"`
4335 }{
4336 math.MinInt64,
4337 0,
4338 math.MaxInt64,
4339 },
4340 want: `{"D1":"-9223372036854775808","D2":"0","D3":"9223372036854775807"}`,
4341 }, {
4342 name: jsontest.Name("Duration/Format/Invalid"),
4343 in: struct {
4344 D time.Duration `json:",format:invalid"`
4345 }{},
4346 want: `{"D"`,
4347 wantErr: EM(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, T[time.Duration]()),
4348 }, {
4349
4355 name: jsontest.Name("Duration/Format"),
4356 opts: []Options{jsontext.Multiline(true)},
4357 in: structDurationFormat{
4358 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4359 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4360 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4361 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4362 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4363 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4364 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4365 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4366 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4367 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4368 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4369 },
4370 want: `{
4371 "D1": "12h34m56.078090012s",
4372 "D2": "12h34m56.078090012s",
4373 "D3": 45296.078090012,
4374 "D4": "45296.078090012",
4375 "D5": 45296078.090012,
4376 "D6": "45296078.090012",
4377 "D7": 45296078090.012,
4378 "D8": "45296078090.012",
4379 "D9": 45296078090012,
4380 "D10": "45296078090012",
4381 "D11": "PT12H34M56.078090012S"
4382 }`,
4383 }, {
4384
4393
4398 name: jsontest.Name("Duration/MapKey/Legacy"),
4399 opts: []Options{jsonflags.FormatDurationAsNano | 1},
4400 in: map[time.Duration]string{time.Second: ""},
4401 want: `{"1000000000":""}`,
4402 }, {
4403 name: jsontest.Name("Time/Zero"),
4404 in: struct {
4405 T1 time.Time
4406 T2 time.Time `json:",format:RFC822"`
4407 T3 time.Time `json:",format:'2006-01-02'"`
4408 T4 time.Time `json:",omitzero"`
4409 T5 time.Time `json:",omitempty"`
4410 }{
4411 time.Time{},
4412 time.Time{},
4413 time.Time{},
4414
4415
4416 time.Date(1, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC", 0)),
4417 time.Time{},
4418 },
4419 want: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T5":"0001-01-01T00:00:00Z"}`,
4420 }, {
4421 name: jsontest.Name("Time/Format"),
4422 opts: []Options{jsontext.Multiline(true)},
4423 in: structTimeFormat{
4424 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4425 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4426 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4427 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4428 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4429 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4430 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4431 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4432 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4433 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4434 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4435 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4436 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4437 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4438 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4439 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4440 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4441 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4442 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4443 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4444 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4445 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4446 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4447 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4448 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4449 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4450 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4451 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4452 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4453 },
4454 want: `{
4455 "T1": "1234-01-02T03:04:05.000000006Z",
4456 "T2": "Mon Jan 2 03:04:05 1234",
4457 "T3": "Mon Jan 2 03:04:05 UTC 1234",
4458 "T4": "Mon Jan 02 03:04:05 +0000 1234",
4459 "T5": "02 Jan 34 03:04 UTC",
4460 "T6": "02 Jan 34 03:04 +0000",
4461 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
4462 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
4463 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
4464 "T10": "1234-01-02T03:04:05Z",
4465 "T11": "1234-01-02T03:04:05.000000006Z",
4466 "T12": "3:04AM",
4467 "T13": "Jan 2 03:04:05",
4468 "T14": "Jan 2 03:04:05.000",
4469 "T15": "Jan 2 03:04:05.000000",
4470 "T16": "Jan 2 03:04:05.000000006",
4471 "T17": "1234-01-02 03:04:05",
4472 "T18": "1234-01-02",
4473 "T19": "03:04:05",
4474 "T20": "1234-01-02",
4475 "T21": "\"weird\"1234",
4476 "T22": -23225777754.999999994,
4477 "T23": "-23225777754.999999994",
4478 "T24": -23225777754999.999994,
4479 "T25": "-23225777754999.999994",
4480 "T26": -23225777754999999.994,
4481 "T27": "-23225777754999999.994",
4482 "T28": -23225777754999999994,
4483 "T29": "-23225777754999999994"
4484 }`,
4485 }, {
4486 name: jsontest.Name("Time/Format/Invalid"),
4487 in: struct {
4488 T time.Time `json:",format:UndefinedConstant"`
4489 }{},
4490 want: `{"T"`,
4491 wantErr: EM(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4492 }, {
4493 name: jsontest.Name("Time/Format/YearOverflow"),
4494 in: struct {
4495 T1 time.Time
4496 T2 time.Time
4497 }{
4498 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4499 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC),
4500 },
4501 want: `{"T1":"9999-12-31T23:59:59Z","T2"`,
4502 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"9999-12-31T23:59:59Z","T2":`, "/T2").withType(0, timeTimeType),
4503 }, {
4504 name: jsontest.Name("Time/Format/YearUnderflow"),
4505 in: struct {
4506 T1 time.Time
4507 T2 time.Time
4508 }{
4509 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
4510 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4511 },
4512 want: `{"T1":"0000-01-01T00:00:00Z","T2"`,
4513 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"0000-01-01T00:00:00Z","T2":`, "/T2").withType(0, timeTimeType),
4514 }, {
4515 name: jsontest.Name("Time/Format/YearUnderflow"),
4516 in: struct{ T time.Time }{time.Date(-998, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second)},
4517 want: `{"T"`,
4518 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4519 }, {
4520 name: jsontest.Name("Time/Format/ZoneExact"),
4521 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 23*60*60+59*60))},
4522 want: `{"T":"2020-01-01T00:00:00+23:59"}`,
4523 }, {
4524 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4525 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 24*60*60))},
4526 want: `{"T"`,
4527 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4528 }, {
4529 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4530 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 123*60*60))},
4531 want: `{"T"`,
4532 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4533 }, {
4534 name: jsontest.Name("Time/IgnoreInvalidFormat"),
4535 opts: []Options{invalidFormatOption},
4536 in: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
4537 want: `"2000-01-01T00:00:00Z"`,
4538 }}
4539
4540 for _, tt := range tests {
4541 t.Run(tt.name.Name, func(t *testing.T) {
4542 var got []byte
4543 var gotErr error
4544 if tt.useWriter {
4545 bb := new(struct{ bytes.Buffer })
4546 gotErr = MarshalWrite(bb, tt.in, tt.opts...)
4547 got = bb.Bytes()
4548 } else {
4549 got, gotErr = Marshal(tt.in, tt.opts...)
4550 }
4551 if tt.canonicalize {
4552 (*jsontext.Value)(&got).Canonicalize()
4553 }
4554 if string(got) != tt.want {
4555 t.Errorf("%s: Marshal output mismatch:\ngot %s\nwant %s", tt.name.Where, got, tt.want)
4556 }
4557 if !reflect.DeepEqual(gotErr, tt.wantErr) {
4558 t.Errorf("%s: Marshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
4559 }
4560 })
4561 }
4562 }
4563
4564 func TestUnmarshal(t *testing.T) {
4565 tests := []struct {
4566 name jsontest.CaseName
4567 opts []Options
4568 inBuf string
4569 inVal any
4570 want any
4571 wantErr error
4572 }{{
4573 name: jsontest.Name("Nil"),
4574 inBuf: `null`,
4575 wantErr: EU(internal.ErrNonNilReference),
4576 }, {
4577 name: jsontest.Name("NilPointer"),
4578 inBuf: `null`,
4579 inVal: (*string)(nil),
4580 want: (*string)(nil),
4581 wantErr: EU(internal.ErrNonNilReference).withType(0, T[*string]()),
4582 }, {
4583 name: jsontest.Name("NonPointer"),
4584 inBuf: `null`,
4585 inVal: "unchanged",
4586 want: "unchanged",
4587 wantErr: EU(internal.ErrNonNilReference).withType(0, T[string]()),
4588 }, {
4589 name: jsontest.Name("Bools/TrailingJunk"),
4590 inBuf: `falsetrue`,
4591 inVal: addr(true),
4592 want: addr(false),
4593 wantErr: newInvalidCharacterError("t", "after top-level value", len64(`false`), ""),
4594 }, {
4595 name: jsontest.Name("Bools/Null"),
4596 inBuf: `null`,
4597 inVal: addr(true),
4598 want: addr(false),
4599 }, {
4600 name: jsontest.Name("Bools"),
4601 inBuf: `[null,false,true]`,
4602 inVal: new([]bool),
4603 want: addr([]bool{false, false, true}),
4604 }, {
4605 name: jsontest.Name("Bools/Named"),
4606 inBuf: `[null,false,true]`,
4607 inVal: new([]namedBool),
4608 want: addr([]namedBool{false, false, true}),
4609 }, {
4610 name: jsontest.Name("Bools/Invalid/StringifiedFalse"),
4611 opts: []Options{StringifyNumbers(true)},
4612 inBuf: `"false"`,
4613 inVal: addr(true),
4614 want: addr(true),
4615 wantErr: EU(nil).withType('"', boolType),
4616 }, {
4617 name: jsontest.Name("Bools/Invalid/StringifiedTrue"),
4618 opts: []Options{StringifyNumbers(true)},
4619 inBuf: `"true"`,
4620 inVal: addr(true),
4621 want: addr(true),
4622 wantErr: EU(nil).withType('"', boolType),
4623 }, {
4624 name: jsontest.Name("Bools/StringifiedBool/True"),
4625 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4626 inBuf: `"true"`,
4627 inVal: addr(false),
4628 want: addr(true),
4629 }, {
4630 name: jsontest.Name("Bools/StringifiedBool/False"),
4631 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4632 inBuf: `"false"`,
4633 inVal: addr(true),
4634 want: addr(false),
4635 }, {
4636 name: jsontest.Name("Bools/StringifiedBool/InvalidWhitespace"),
4637 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4638 inBuf: `"false "`,
4639 inVal: addr(true),
4640 want: addr(true),
4641 wantErr: EU(strconv.ErrSyntax).withVal(`"false "`).withType('"', boolType),
4642 }, {
4643 name: jsontest.Name("Bools/StringifiedBool/InvalidBool"),
4644 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4645 inBuf: `false`,
4646 inVal: addr(true),
4647 want: addr(true),
4648 wantErr: EU(nil).withType('f', boolType),
4649 }, {
4650 name: jsontest.Name("Bools/Invalid/Number"),
4651 inBuf: `0`,
4652 inVal: addr(true),
4653 want: addr(true),
4654 wantErr: EU(nil).withType('0', boolType),
4655 }, {
4656 name: jsontest.Name("Bools/Invalid/String"),
4657 inBuf: `""`,
4658 inVal: addr(true),
4659 want: addr(true),
4660 wantErr: EU(nil).withType('"', boolType),
4661 }, {
4662 name: jsontest.Name("Bools/Invalid/Object"),
4663 inBuf: `{}`,
4664 inVal: addr(true),
4665 want: addr(true),
4666 wantErr: EU(nil).withType('{', boolType),
4667 }, {
4668 name: jsontest.Name("Bools/Invalid/Array"),
4669 inBuf: `[]`,
4670 inVal: addr(true),
4671 want: addr(true),
4672 wantErr: EU(nil).withType('[', boolType),
4673 }, {
4674 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
4675 opts: []Options{invalidFormatOption},
4676 inBuf: `false`,
4677 inVal: addr(true),
4678 want: addr(false),
4679 }, {
4680 name: jsontest.Name("Strings/Null"),
4681 inBuf: `null`,
4682 inVal: addr("something"),
4683 want: addr(""),
4684 }, {
4685 name: jsontest.Name("Strings"),
4686 inBuf: `[null,"","hello","世界"]`,
4687 inVal: new([]string),
4688 want: addr([]string{"", "", "hello", "世界"}),
4689 }, {
4690 name: jsontest.Name("Strings/Escaped"),
4691 inBuf: `[null,"","\u0068\u0065\u006c\u006c\u006f","\u4e16\u754c"]`,
4692 inVal: new([]string),
4693 want: addr([]string{"", "", "hello", "世界"}),
4694 }, {
4695 name: jsontest.Name("Strings/Named"),
4696 inBuf: `[null,"","hello","世界"]`,
4697 inVal: new([]namedString),
4698 want: addr([]namedString{"", "", "hello", "世界"}),
4699 }, {
4700 name: jsontest.Name("Strings/Invalid/False"),
4701 inBuf: `false`,
4702 inVal: addr("nochange"),
4703 want: addr("nochange"),
4704 wantErr: EU(nil).withType('f', stringType),
4705 }, {
4706 name: jsontest.Name("Strings/Invalid/True"),
4707 inBuf: `true`,
4708 inVal: addr("nochange"),
4709 want: addr("nochange"),
4710 wantErr: EU(nil).withType('t', stringType),
4711 }, {
4712 name: jsontest.Name("Strings/Invalid/Object"),
4713 inBuf: `{}`,
4714 inVal: addr("nochange"),
4715 want: addr("nochange"),
4716 wantErr: EU(nil).withType('{', stringType),
4717 }, {
4718 name: jsontest.Name("Strings/Invalid/Array"),
4719 inBuf: `[]`,
4720 inVal: addr("nochange"),
4721 want: addr("nochange"),
4722 wantErr: EU(nil).withType('[', stringType),
4723 }, {
4724 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
4725 opts: []Options{invalidFormatOption},
4726 inBuf: `"hello"`,
4727 inVal: addr("goodbye"),
4728 want: addr("hello"),
4729 }, {
4730 name: jsontest.Name("Strings/StringifiedString"),
4731 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4732 inBuf: `"\"foo\""`,
4733 inVal: new(string),
4734 want: addr("foo"),
4735 }, {
4736 name: jsontest.Name("Strings/StringifiedString/InvalidWhitespace"),
4737 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4738 inBuf: `"\"foo\" "`,
4739 inVal: new(string),
4740 want: new(string),
4741 wantErr: EU(newInvalidCharacterError(" ", "after string value", 0, "")).withType('"', stringType),
4742 }, {
4743 name: jsontest.Name("Strings/StringifiedString/InvalidString"),
4744 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4745 inBuf: `""`,
4746 inVal: new(string),
4747 want: new(string),
4748 wantErr: EU(&jsontext.SyntacticError{Err: io.ErrUnexpectedEOF}).withType('"', stringType),
4749 }, {
4750 name: jsontest.Name("Bytes/Null"),
4751 inBuf: `null`,
4752 inVal: addr([]byte("something")),
4753 want: addr([]byte(nil)),
4754 }, {
4755 name: jsontest.Name("Bytes"),
4756 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4757 inVal: new([][]byte),
4758 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4759 }, {
4760 name: jsontest.Name("Bytes/Large"),
4761 inBuf: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
4762 inVal: new([]byte),
4763 want: addr([]byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on.")),
4764 }, {
4765 name: jsontest.Name("Bytes/Reuse"),
4766 inBuf: `"AQID"`,
4767 inVal: addr([]byte("changed")),
4768 want: addr([]byte{1, 2, 3}),
4769 }, {
4770 name: jsontest.Name("Bytes/Escaped"),
4771 inBuf: `[null,"","\u0041\u0051\u003d\u003d","\u0041\u0051\u0049\u003d","\u0041\u0051\u0049\u0044"]`,
4772 inVal: new([][]byte),
4773 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4774 }, {
4775 name: jsontest.Name("Bytes/Named"),
4776 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4777 inVal: new([]namedBytes),
4778 want: addr([]namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4779 }, {
4780 name: jsontest.Name("Bytes/NotStringified"),
4781 opts: []Options{StringifyNumbers(true)},
4782 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4783 inVal: new([][]byte),
4784 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4785 }, {
4786
4787
4788 name: jsontest.Name("Bytes/Invariant"),
4789 inBuf: `[null,[],[1],[1,2],[1,2,3]]`,
4790 inVal: new([][]namedByte),
4791 want: addr([][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4792 }, {
4793
4794
4795 name: jsontest.Name("Bytes/ByteArray"),
4796 inBuf: `"aGVsbG8="`,
4797 inVal: new([5]byte),
4798 want: addr([5]byte{'h', 'e', 'l', 'l', 'o'}),
4799 }, {
4800 name: jsontest.Name("Bytes/ByteArray0/Valid"),
4801 inBuf: `""`,
4802 inVal: new([0]byte),
4803 want: addr([0]byte{}),
4804 }, {
4805 name: jsontest.Name("Bytes/ByteArray0/Invalid"),
4806 inBuf: `"A"`,
4807 inVal: new([0]byte),
4808 want: addr([0]byte{}),
4809 wantErr: EU(func() error {
4810 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("A"))
4811 return err
4812 }()).withType('"', T[[0]byte]()),
4813 }, {
4814 name: jsontest.Name("Bytes/ByteArray0/Overflow"),
4815 inBuf: `"AA=="`,
4816 inVal: new([0]byte),
4817 want: addr([0]byte{}),
4818 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 0")).withType('"', T[[0]byte]()),
4819 }, {
4820 name: jsontest.Name("Bytes/ByteArray1/Valid"),
4821 inBuf: `"AQ=="`,
4822 inVal: new([1]byte),
4823 want: addr([1]byte{1}),
4824 }, {
4825 name: jsontest.Name("Bytes/ByteArray1/Invalid"),
4826 inBuf: `"$$=="`,
4827 inVal: new([1]byte),
4828 want: addr([1]byte{}),
4829 wantErr: EU(func() error {
4830 _, err := base64.StdEncoding.Decode(make([]byte, 1), []byte("$$=="))
4831 return err
4832 }()).withType('"', T[[1]byte]()),
4833 }, {
4834 name: jsontest.Name("Bytes/ByteArray1/Underflow"),
4835 inBuf: `""`,
4836 inVal: new([1]byte),
4837 want: addr([1]byte{}),
4838 wantErr: EU(errors.New("decoded length of 0 mismatches array length of 1")).withType('"', T[[1]byte]()),
4839 }, {
4840 name: jsontest.Name("Bytes/ByteArray1/Overflow"),
4841 inBuf: `"AQI="`,
4842 inVal: new([1]byte),
4843 want: addr([1]byte{1}),
4844 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 1")).withType('"', T[[1]byte]()),
4845 }, {
4846 name: jsontest.Name("Bytes/ByteArray2/Valid"),
4847 inBuf: `"AQI="`,
4848 inVal: new([2]byte),
4849 want: addr([2]byte{1, 2}),
4850 }, {
4851 name: jsontest.Name("Bytes/ByteArray2/Invalid"),
4852 inBuf: `"$$$="`,
4853 inVal: new([2]byte),
4854 want: addr([2]byte{}),
4855 wantErr: EU(func() error {
4856 _, err := base64.StdEncoding.Decode(make([]byte, 2), []byte("$$$="))
4857 return err
4858 }()).withType('"', T[[2]byte]()),
4859 }, {
4860 name: jsontest.Name("Bytes/ByteArray2/Underflow"),
4861 inBuf: `"AQ=="`,
4862 inVal: new([2]byte),
4863 want: addr([2]byte{1, 0}),
4864 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 2")).withType('"', T[[2]byte]()),
4865 }, {
4866 name: jsontest.Name("Bytes/ByteArray2/Underflow/Allowed"),
4867 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4868 inBuf: `"AQ=="`,
4869 inVal: new([2]byte),
4870 want: addr([2]byte{1, 0}),
4871 }, {
4872 name: jsontest.Name("Bytes/ByteArray2/Overflow"),
4873 inBuf: `"AQID"`,
4874 inVal: new([2]byte),
4875 want: addr([2]byte{1, 2}),
4876 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 2")).withType('"', T[[2]byte]()),
4877 }, {
4878 name: jsontest.Name("Bytes/ByteArray2/Overflow/Allowed"),
4879 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4880 inBuf: `"AQID"`,
4881 inVal: new([2]byte),
4882 want: addr([2]byte{1, 2}),
4883 }, {
4884 name: jsontest.Name("Bytes/ByteArray3/Valid"),
4885 inBuf: `"AQID"`,
4886 inVal: new([3]byte),
4887 want: addr([3]byte{1, 2, 3}),
4888 }, {
4889 name: jsontest.Name("Bytes/ByteArray3/Invalid"),
4890 inBuf: `"$$$$"`,
4891 inVal: new([3]byte),
4892 want: addr([3]byte{}),
4893 wantErr: EU(func() error {
4894 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("$$$$"))
4895 return err
4896 }()).withType('"', T[[3]byte]()),
4897 }, {
4898 name: jsontest.Name("Bytes/ByteArray3/Underflow"),
4899 inBuf: `"AQI="`,
4900 inVal: addr([3]byte{0xff, 0xff, 0xff}),
4901 want: addr([3]byte{1, 2, 0}),
4902 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 3")).withType('"', T[[3]byte]()),
4903 }, {
4904 name: jsontest.Name("Bytes/ByteArray3/Overflow"),
4905 inBuf: `"AQIDAQ=="`,
4906 inVal: new([3]byte),
4907 want: addr([3]byte{1, 2, 3}),
4908 wantErr: EU(errors.New("decoded length of 4 mismatches array length of 3")).withType('"', T[[3]byte]()),
4909 }, {
4910 name: jsontest.Name("Bytes/ByteArray4/Valid"),
4911 inBuf: `"AQIDBA=="`,
4912 inVal: new([4]byte),
4913 want: addr([4]byte{1, 2, 3, 4}),
4914 }, {
4915 name: jsontest.Name("Bytes/ByteArray4/Invalid"),
4916 inBuf: `"$$$$$$=="`,
4917 inVal: new([4]byte),
4918 want: addr([4]byte{}),
4919 wantErr: EU(func() error {
4920 _, err := base64.StdEncoding.Decode(make([]byte, 4), []byte("$$$$$$=="))
4921 return err
4922 }()).withType('"', T[[4]byte]()),
4923 }, {
4924 name: jsontest.Name("Bytes/ByteArray4/Underflow"),
4925 inBuf: `"AQID"`,
4926 inVal: new([4]byte),
4927 want: addr([4]byte{1, 2, 3, 0}),
4928 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 4")).withType('"', T[[4]byte]()),
4929 }, {
4930 name: jsontest.Name("Bytes/ByteArray4/Overflow"),
4931 inBuf: `"AQIDBAU="`,
4932 inVal: new([4]byte),
4933 want: addr([4]byte{1, 2, 3, 4}),
4934 wantErr: EU(errors.New("decoded length of 5 mismatches array length of 4")).withType('"', T[[4]byte]()),
4935 }, {
4936
4937
4938 name: jsontest.Name("Bytes/NamedByteArray"),
4939 inBuf: `[104,101,108,108,111]`,
4940 inVal: new([5]namedByte),
4941 want: addr([5]namedByte{'h', 'e', 'l', 'l', 'o'}),
4942 }, {
4943 name: jsontest.Name("Bytes/Valid/Denormalized"),
4944 inBuf: `"AR=="`,
4945 inVal: new([]byte),
4946 want: addr([]byte{1}),
4947 }, {
4948 name: jsontest.Name("Bytes/Invalid/Unpadded1"),
4949 inBuf: `"AQ="`,
4950 inVal: addr([]byte("nochange")),
4951 want: addr([]byte("nochange")),
4952 wantErr: EU(func() error {
4953 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ="))
4954 return err
4955 }()).withType('"', bytesType),
4956 }, {
4957 name: jsontest.Name("Bytes/Invalid/Unpadded2"),
4958 inBuf: `"AQ"`,
4959 inVal: addr([]byte("nochange")),
4960 want: addr([]byte("nochange")),
4961 wantErr: EU(func() error {
4962 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ"))
4963 return err
4964 }()).withType('"', bytesType),
4965 }, {
4966 name: jsontest.Name("Bytes/Invalid/Character"),
4967 inBuf: `"@@@@"`,
4968 inVal: addr([]byte("nochange")),
4969 want: addr([]byte("nochange")),
4970 wantErr: EU(func() error {
4971 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("@@@@"))
4972 return err
4973 }()).withType('"', bytesType),
4974 }, {
4975 name: jsontest.Name("Bytes/Invalid/Bool"),
4976 inBuf: `true`,
4977 inVal: addr([]byte("nochange")),
4978 want: addr([]byte("nochange")),
4979 wantErr: EU(nil).withType('t', bytesType),
4980 }, {
4981 name: jsontest.Name("Bytes/Invalid/Number"),
4982 inBuf: `0`,
4983 inVal: addr([]byte("nochange")),
4984 want: addr([]byte("nochange")),
4985 wantErr: EU(nil).withType('0', bytesType),
4986 }, {
4987 name: jsontest.Name("Bytes/Invalid/Object"),
4988 inBuf: `{}`,
4989 inVal: addr([]byte("nochange")),
4990 want: addr([]byte("nochange")),
4991 wantErr: EU(nil).withType('{', bytesType),
4992 }, {
4993 name: jsontest.Name("Bytes/Invalid/Array"),
4994 inBuf: `[]`,
4995 inVal: addr([]byte("nochange")),
4996 want: addr([]byte("nochange")),
4997 wantErr: EU(nil).withType('[', bytesType),
4998 }, {
4999 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
5000 opts: []Options{invalidFormatOption},
5001 inBuf: `"aGVsbG8="`,
5002 inVal: new([]byte),
5003 want: addr([]byte("hello")),
5004 }, {
5005 name: jsontest.Name("Ints/Null"),
5006 inBuf: `null`,
5007 inVal: addr(int(1)),
5008 want: addr(int(0)),
5009 }, {
5010 name: jsontest.Name("Ints/Int"),
5011 inBuf: `1`,
5012 inVal: addr(int(0)),
5013 want: addr(int(1)),
5014 }, {
5015 name: jsontest.Name("Ints/Int8/MinOverflow"),
5016 inBuf: `-129`,
5017 inVal: addr(int8(-1)),
5018 want: addr(int8(-1)),
5019 wantErr: EU(strconv.ErrRange).withVal(`-129`).withType('0', T[int8]()),
5020 }, {
5021 name: jsontest.Name("Ints/Int8/Min"),
5022 inBuf: `-128`,
5023 inVal: addr(int8(0)),
5024 want: addr(int8(-128)),
5025 }, {
5026 name: jsontest.Name("Ints/Int8/Max"),
5027 inBuf: `127`,
5028 inVal: addr(int8(0)),
5029 want: addr(int8(127)),
5030 }, {
5031 name: jsontest.Name("Ints/Int8/MaxOverflow"),
5032 inBuf: `128`,
5033 inVal: addr(int8(-1)),
5034 want: addr(int8(-1)),
5035 wantErr: EU(strconv.ErrRange).withVal(`128`).withType('0', T[int8]()),
5036 }, {
5037 name: jsontest.Name("Ints/Int16/MinOverflow"),
5038 inBuf: `-32769`,
5039 inVal: addr(int16(-1)),
5040 want: addr(int16(-1)),
5041 wantErr: EU(strconv.ErrRange).withVal(`-32769`).withType('0', T[int16]()),
5042 }, {
5043 name: jsontest.Name("Ints/Int16/Min"),
5044 inBuf: `-32768`,
5045 inVal: addr(int16(0)),
5046 want: addr(int16(-32768)),
5047 }, {
5048 name: jsontest.Name("Ints/Int16/Max"),
5049 inBuf: `32767`,
5050 inVal: addr(int16(0)),
5051 want: addr(int16(32767)),
5052 }, {
5053 name: jsontest.Name("Ints/Int16/MaxOverflow"),
5054 inBuf: `32768`,
5055 inVal: addr(int16(-1)),
5056 want: addr(int16(-1)),
5057 wantErr: EU(strconv.ErrRange).withVal(`32768`).withType('0', T[int16]()),
5058 }, {
5059 name: jsontest.Name("Ints/Int32/MinOverflow"),
5060 inBuf: `-2147483649`,
5061 inVal: addr(int32(-1)),
5062 want: addr(int32(-1)),
5063 wantErr: EU(strconv.ErrRange).withVal(`-2147483649`).withType('0', T[int32]()),
5064 }, {
5065 name: jsontest.Name("Ints/Int32/Min"),
5066 inBuf: `-2147483648`,
5067 inVal: addr(int32(0)),
5068 want: addr(int32(-2147483648)),
5069 }, {
5070 name: jsontest.Name("Ints/Int32/Max"),
5071 inBuf: `2147483647`,
5072 inVal: addr(int32(0)),
5073 want: addr(int32(2147483647)),
5074 }, {
5075 name: jsontest.Name("Ints/Int32/MaxOverflow"),
5076 inBuf: `2147483648`,
5077 inVal: addr(int32(-1)),
5078 want: addr(int32(-1)),
5079 wantErr: EU(strconv.ErrRange).withVal(`2147483648`).withType('0', T[int32]()),
5080 }, {
5081 name: jsontest.Name("Ints/Int64/MinOverflow"),
5082 inBuf: `-9223372036854775809`,
5083 inVal: addr(int64(-1)),
5084 want: addr(int64(-1)),
5085 wantErr: EU(strconv.ErrRange).withVal(`-9223372036854775809`).withType('0', T[int64]()),
5086 }, {
5087 name: jsontest.Name("Ints/Int64/Min"),
5088 inBuf: `-9223372036854775808`,
5089 inVal: addr(int64(0)),
5090 want: addr(int64(-9223372036854775808)),
5091 }, {
5092 name: jsontest.Name("Ints/Int64/Max"),
5093 inBuf: `9223372036854775807`,
5094 inVal: addr(int64(0)),
5095 want: addr(int64(9223372036854775807)),
5096 }, {
5097 name: jsontest.Name("Ints/Int64/MaxOverflow"),
5098 inBuf: `9223372036854775808`,
5099 inVal: addr(int64(-1)),
5100 want: addr(int64(-1)),
5101 wantErr: EU(strconv.ErrRange).withVal(`9223372036854775808`).withType('0', T[int64]()),
5102 }, {
5103 name: jsontest.Name("Ints/Named"),
5104 inBuf: `-6464`,
5105 inVal: addr(namedInt64(0)),
5106 want: addr(namedInt64(-6464)),
5107 }, {
5108 name: jsontest.Name("Ints/Stringified"),
5109 opts: []Options{StringifyNumbers(true)},
5110 inBuf: `"-6464"`,
5111 inVal: new(int),
5112 want: addr(int(-6464)),
5113 }, {
5114 name: jsontest.Name("Ints/Stringified/Invalid"),
5115 opts: []Options{StringifyNumbers(true)},
5116 inBuf: `-6464`,
5117 inVal: new(int),
5118 want: new(int),
5119 wantErr: EU(nil).withType('0', T[int]()),
5120 }, {
5121 name: jsontest.Name("Ints/Stringified/LeadingZero"),
5122 opts: []Options{StringifyNumbers(true)},
5123 inBuf: `"00"`,
5124 inVal: addr(int(-1)),
5125 want: addr(int(-1)),
5126 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[int]()),
5127 }, {
5128 name: jsontest.Name("Ints/Escaped"),
5129 opts: []Options{StringifyNumbers(true)},
5130 inBuf: `"\u002d\u0036\u0034\u0036\u0034"`,
5131 inVal: new(int),
5132 want: addr(int(-6464)),
5133 }, {
5134 name: jsontest.Name("Ints/Valid/NegativeZero"),
5135 inBuf: `-0`,
5136 inVal: addr(int(1)),
5137 want: addr(int(0)),
5138 }, {
5139 name: jsontest.Name("Ints/Invalid/Fraction"),
5140 inBuf: `1.0`,
5141 inVal: addr(int(-1)),
5142 want: addr(int(-1)),
5143 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[int]()),
5144 }, {
5145 name: jsontest.Name("Ints/Invalid/Exponent"),
5146 inBuf: `1e0`,
5147 inVal: addr(int(-1)),
5148 want: addr(int(-1)),
5149 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[int]()),
5150 }, {
5151 name: jsontest.Name("Ints/Invalid/StringifiedFraction"),
5152 opts: []Options{StringifyNumbers(true)},
5153 inBuf: `"1.0"`,
5154 inVal: addr(int(-1)),
5155 want: addr(int(-1)),
5156 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[int]()),
5157 }, {
5158 name: jsontest.Name("Ints/Invalid/StringifiedExponent"),
5159 opts: []Options{StringifyNumbers(true)},
5160 inBuf: `"1e0"`,
5161 inVal: addr(int(-1)),
5162 want: addr(int(-1)),
5163 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[int]()),
5164 }, {
5165 name: jsontest.Name("Ints/Invalid/Overflow"),
5166 inBuf: `100000000000000000000000000000`,
5167 inVal: addr(int(-1)),
5168 want: addr(int(-1)),
5169 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[int]()),
5170 }, {
5171 name: jsontest.Name("Ints/Invalid/OverflowSyntax"),
5172 opts: []Options{StringifyNumbers(true)},
5173 inBuf: `"100000000000000000000000000000x"`,
5174 inVal: addr(int(-1)),
5175 want: addr(int(-1)),
5176 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[int]()),
5177 }, {
5178 name: jsontest.Name("Ints/Invalid/Whitespace"),
5179 opts: []Options{StringifyNumbers(true)},
5180 inBuf: `"0 "`,
5181 inVal: addr(int(-1)),
5182 want: addr(int(-1)),
5183 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[int]()),
5184 }, {
5185 name: jsontest.Name("Ints/Invalid/Bool"),
5186 inBuf: `true`,
5187 inVal: addr(int(-1)),
5188 want: addr(int(-1)),
5189 wantErr: EU(nil).withType('t', T[int]()),
5190 }, {
5191 name: jsontest.Name("Ints/Invalid/String"),
5192 inBuf: `"0"`,
5193 inVal: addr(int(-1)),
5194 want: addr(int(-1)),
5195 wantErr: EU(nil).withType('"', T[int]()),
5196 }, {
5197 name: jsontest.Name("Ints/Invalid/Object"),
5198 inBuf: `{}`,
5199 inVal: addr(int(-1)),
5200 want: addr(int(-1)),
5201 wantErr: EU(nil).withType('{', T[int]()),
5202 }, {
5203 name: jsontest.Name("Ints/Invalid/Array"),
5204 inBuf: `[]`,
5205 inVal: addr(int(-1)),
5206 want: addr(int(-1)),
5207 wantErr: EU(nil).withType('[', T[int]()),
5208 }, {
5209 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
5210 opts: []Options{invalidFormatOption},
5211 inBuf: `1`,
5212 inVal: addr(int(0)),
5213 want: addr(int(1)),
5214 }, {
5215 name: jsontest.Name("Uints/Null"),
5216 inBuf: `null`,
5217 inVal: addr(uint(1)),
5218 want: addr(uint(0)),
5219 }, {
5220 name: jsontest.Name("Uints/Uint"),
5221 inBuf: `1`,
5222 inVal: addr(uint(0)),
5223 want: addr(uint(1)),
5224 }, {
5225 name: jsontest.Name("Uints/Uint8/Min"),
5226 inBuf: `0`,
5227 inVal: addr(uint8(1)),
5228 want: addr(uint8(0)),
5229 }, {
5230 name: jsontest.Name("Uints/Uint8/Max"),
5231 inBuf: `255`,
5232 inVal: addr(uint8(0)),
5233 want: addr(uint8(255)),
5234 }, {
5235 name: jsontest.Name("Uints/Uint8/MaxOverflow"),
5236 inBuf: `256`,
5237 inVal: addr(uint8(1)),
5238 want: addr(uint8(1)),
5239 wantErr: EU(strconv.ErrRange).withVal(`256`).withType('0', T[uint8]()),
5240 }, {
5241 name: jsontest.Name("Uints/Uint16/Min"),
5242 inBuf: `0`,
5243 inVal: addr(uint16(1)),
5244 want: addr(uint16(0)),
5245 }, {
5246 name: jsontest.Name("Uints/Uint16/Max"),
5247 inBuf: `65535`,
5248 inVal: addr(uint16(0)),
5249 want: addr(uint16(65535)),
5250 }, {
5251 name: jsontest.Name("Uints/Uint16/MaxOverflow"),
5252 inBuf: `65536`,
5253 inVal: addr(uint16(1)),
5254 want: addr(uint16(1)),
5255 wantErr: EU(strconv.ErrRange).withVal(`65536`).withType('0', T[uint16]()),
5256 }, {
5257 name: jsontest.Name("Uints/Uint32/Min"),
5258 inBuf: `0`,
5259 inVal: addr(uint32(1)),
5260 want: addr(uint32(0)),
5261 }, {
5262 name: jsontest.Name("Uints/Uint32/Max"),
5263 inBuf: `4294967295`,
5264 inVal: addr(uint32(0)),
5265 want: addr(uint32(4294967295)),
5266 }, {
5267 name: jsontest.Name("Uints/Uint32/MaxOverflow"),
5268 inBuf: `4294967296`,
5269 inVal: addr(uint32(1)),
5270 want: addr(uint32(1)),
5271 wantErr: EU(strconv.ErrRange).withVal(`4294967296`).withType('0', T[uint32]()),
5272 }, {
5273 name: jsontest.Name("Uints/Uint64/Min"),
5274 inBuf: `0`,
5275 inVal: addr(uint64(1)),
5276 want: addr(uint64(0)),
5277 }, {
5278 name: jsontest.Name("Uints/Uint64/Max"),
5279 inBuf: `18446744073709551615`,
5280 inVal: addr(uint64(0)),
5281 want: addr(uint64(18446744073709551615)),
5282 }, {
5283 name: jsontest.Name("Uints/Uint64/MaxOverflow"),
5284 inBuf: `18446744073709551616`,
5285 inVal: addr(uint64(1)),
5286 want: addr(uint64(1)),
5287 wantErr: EU(strconv.ErrRange).withVal(`18446744073709551616`).withType('0', T[uint64]()),
5288 }, {
5289 name: jsontest.Name("Uints/Uintptr"),
5290 inBuf: `1`,
5291 inVal: addr(uintptr(0)),
5292 want: addr(uintptr(1)),
5293 }, {
5294 name: jsontest.Name("Uints/Named"),
5295 inBuf: `6464`,
5296 inVal: addr(namedUint64(0)),
5297 want: addr(namedUint64(6464)),
5298 }, {
5299 name: jsontest.Name("Uints/Stringified"),
5300 opts: []Options{StringifyNumbers(true)},
5301 inBuf: `"6464"`,
5302 inVal: new(uint),
5303 want: addr(uint(6464)),
5304 }, {
5305 name: jsontest.Name("Uints/Stringified/Invalid"),
5306 opts: []Options{StringifyNumbers(true)},
5307 inBuf: `6464`,
5308 inVal: new(uint),
5309 want: new(uint),
5310 wantErr: EU(nil).withType('0', T[uint]()),
5311 }, {
5312 name: jsontest.Name("Uints/Stringified/LeadingZero"),
5313 opts: []Options{StringifyNumbers(true)},
5314 inBuf: `"00"`,
5315 inVal: addr(uint(1)),
5316 want: addr(uint(1)),
5317 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[uint]()),
5318 }, {
5319 name: jsontest.Name("Uints/Escaped"),
5320 opts: []Options{StringifyNumbers(true)},
5321 inBuf: `"\u0036\u0034\u0036\u0034"`,
5322 inVal: new(uint),
5323 want: addr(uint(6464)),
5324 }, {
5325 name: jsontest.Name("Uints/Invalid/NegativeOne"),
5326 inBuf: `-1`,
5327 inVal: addr(uint(1)),
5328 want: addr(uint(1)),
5329 wantErr: EU(strconv.ErrSyntax).withVal(`-1`).withType('0', T[uint]()),
5330 }, {
5331 name: jsontest.Name("Uints/Invalid/NegativeZero"),
5332 inBuf: `-0`,
5333 inVal: addr(uint(1)),
5334 want: addr(uint(1)),
5335 wantErr: EU(strconv.ErrSyntax).withVal(`-0`).withType('0', T[uint]()),
5336 }, {
5337 name: jsontest.Name("Uints/Invalid/Fraction"),
5338 inBuf: `1.0`,
5339 inVal: addr(uint(10)),
5340 want: addr(uint(10)),
5341 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[uint]()),
5342 }, {
5343 name: jsontest.Name("Uints/Invalid/Exponent"),
5344 inBuf: `1e0`,
5345 inVal: addr(uint(10)),
5346 want: addr(uint(10)),
5347 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[uint]()),
5348 }, {
5349 name: jsontest.Name("Uints/Invalid/StringifiedFraction"),
5350 opts: []Options{StringifyNumbers(true)},
5351 inBuf: `"1.0"`,
5352 inVal: addr(uint(10)),
5353 want: addr(uint(10)),
5354 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[uint]()),
5355 }, {
5356 name: jsontest.Name("Uints/Invalid/StringifiedExponent"),
5357 opts: []Options{StringifyNumbers(true)},
5358 inBuf: `"1e0"`,
5359 inVal: addr(uint(10)),
5360 want: addr(uint(10)),
5361 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[uint]()),
5362 }, {
5363 name: jsontest.Name("Uints/Invalid/Overflow"),
5364 inBuf: `100000000000000000000000000000`,
5365 inVal: addr(uint(1)),
5366 want: addr(uint(1)),
5367 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[uint]()),
5368 }, {
5369 name: jsontest.Name("Uints/Invalid/OverflowSyntax"),
5370 opts: []Options{StringifyNumbers(true)},
5371 inBuf: `"100000000000000000000000000000x"`,
5372 inVal: addr(uint(1)),
5373 want: addr(uint(1)),
5374 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[uint]()),
5375 }, {
5376 name: jsontest.Name("Uints/Invalid/Whitespace"),
5377 opts: []Options{StringifyNumbers(true)},
5378 inBuf: `"0 "`,
5379 inVal: addr(uint(1)),
5380 want: addr(uint(1)),
5381 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[uint]()),
5382 }, {
5383 name: jsontest.Name("Uints/Invalid/Bool"),
5384 inBuf: `true`,
5385 inVal: addr(uint(1)),
5386 want: addr(uint(1)),
5387 wantErr: EU(nil).withType('t', T[uint]()),
5388 }, {
5389 name: jsontest.Name("Uints/Invalid/String"),
5390 inBuf: `"0"`,
5391 inVal: addr(uint(1)),
5392 want: addr(uint(1)),
5393 wantErr: EU(nil).withType('"', T[uint]()),
5394 }, {
5395 name: jsontest.Name("Uints/Invalid/Object"),
5396 inBuf: `{}`,
5397 inVal: addr(uint(1)),
5398 want: addr(uint(1)),
5399 wantErr: EU(nil).withType('{', T[uint]()),
5400 }, {
5401 name: jsontest.Name("Uints/Invalid/Array"),
5402 inBuf: `[]`,
5403 inVal: addr(uint(1)),
5404 want: addr(uint(1)),
5405 wantErr: EU(nil).withType('[', T[uint]()),
5406 }, {
5407 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
5408 opts: []Options{invalidFormatOption},
5409 inBuf: `1`,
5410 inVal: addr(uint(0)),
5411 want: addr(uint(1)),
5412 }, {
5413 name: jsontest.Name("Floats/Null"),
5414 inBuf: `null`,
5415 inVal: addr(float64(64.64)),
5416 want: addr(float64(0)),
5417 }, {
5418 name: jsontest.Name("Floats/Float32/Pi"),
5419 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5420 inVal: addr(float32(32.32)),
5421 want: addr(float32(math.Pi)),
5422 }, {
5423 name: jsontest.Name("Floats/Float32/Underflow"),
5424 inBuf: `1e-1000`,
5425 inVal: addr(float32(32.32)),
5426 want: addr(float32(0)),
5427 }, {
5428 name: jsontest.Name("Floats/Float32/Overflow"),
5429 inBuf: `-1e1000`,
5430 inVal: addr(float32(32.32)),
5431 want: addr(float32(-math.MaxFloat32)),
5432 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float32]()),
5433 }, {
5434 name: jsontest.Name("Floats/Float64/Pi"),
5435 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5436 inVal: addr(float64(64.64)),
5437 want: addr(float64(math.Pi)),
5438 }, {
5439 name: jsontest.Name("Floats/Float64/Underflow"),
5440 inBuf: `1e-1000`,
5441 inVal: addr(float64(64.64)),
5442 want: addr(float64(0)),
5443 }, {
5444 name: jsontest.Name("Floats/Float64/Overflow"),
5445 inBuf: `-1e1000`,
5446 inVal: addr(float64(64.64)),
5447 want: addr(float64(-math.MaxFloat64)),
5448 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float64]()),
5449 }, {
5450 name: jsontest.Name("Floats/Any/Overflow"),
5451 inBuf: `1e1000`,
5452 inVal: new(any),
5453 want: addr(any(float64(math.MaxFloat64))),
5454 wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float64]()),
5455 }, {
5456 name: jsontest.Name("Floats/Named"),
5457 inBuf: `64.64`,
5458 inVal: addr(namedFloat64(0)),
5459 want: addr(namedFloat64(64.64)),
5460 }, {
5461 name: jsontest.Name("Floats/Stringified"),
5462 opts: []Options{StringifyNumbers(true)},
5463 inBuf: `"64.64"`,
5464 inVal: new(float64),
5465 want: addr(float64(64.64)),
5466 }, {
5467 name: jsontest.Name("Floats/Stringified/Invalid"),
5468 opts: []Options{StringifyNumbers(true)},
5469 inBuf: `64.64`,
5470 inVal: new(float64),
5471 want: new(float64),
5472 wantErr: EU(nil).withType('0', T[float64]()),
5473 }, {
5474 name: jsontest.Name("Floats/Escaped"),
5475 opts: []Options{StringifyNumbers(true)},
5476 inBuf: `"\u0036\u0034\u002e\u0036\u0034"`,
5477 inVal: new(float64),
5478 want: addr(float64(64.64)),
5479 }, {
5480 name: jsontest.Name("Floats/Invalid/NaN"),
5481 opts: []Options{StringifyNumbers(true)},
5482 inBuf: `"NaN"`,
5483 inVal: addr(float64(64.64)),
5484 want: addr(float64(64.64)),
5485 wantErr: EU(strconv.ErrSyntax).withVal(`"NaN"`).withType('"', float64Type),
5486 }, {
5487 name: jsontest.Name("Floats/Invalid/Infinity"),
5488 opts: []Options{StringifyNumbers(true)},
5489 inBuf: `"Infinity"`,
5490 inVal: addr(float64(64.64)),
5491 want: addr(float64(64.64)),
5492 wantErr: EU(strconv.ErrSyntax).withVal(`"Infinity"`).withType('"', float64Type),
5493 }, {
5494 name: jsontest.Name("Floats/Invalid/Whitespace"),
5495 opts: []Options{StringifyNumbers(true)},
5496 inBuf: `"1 "`,
5497 inVal: addr(float64(64.64)),
5498 want: addr(float64(64.64)),
5499 wantErr: EU(strconv.ErrSyntax).withVal(`"1 "`).withType('"', float64Type),
5500 }, {
5501 name: jsontest.Name("Floats/Invalid/GoSyntax"),
5502 opts: []Options{StringifyNumbers(true)},
5503 inBuf: `"1p-2"`,
5504 inVal: addr(float64(64.64)),
5505 want: addr(float64(64.64)),
5506 wantErr: EU(strconv.ErrSyntax).withVal(`"1p-2"`).withType('"', float64Type),
5507 }, {
5508 name: jsontest.Name("Floats/Invalid/Bool"),
5509 inBuf: `true`,
5510 inVal: addr(float64(64.64)),
5511 want: addr(float64(64.64)),
5512 wantErr: EU(nil).withType('t', float64Type),
5513 }, {
5514 name: jsontest.Name("Floats/Invalid/String"),
5515 inBuf: `"0"`,
5516 inVal: addr(float64(64.64)),
5517 want: addr(float64(64.64)),
5518 wantErr: EU(nil).withType('"', float64Type),
5519 }, {
5520 name: jsontest.Name("Floats/Invalid/Object"),
5521 inBuf: `{}`,
5522 inVal: addr(float64(64.64)),
5523 want: addr(float64(64.64)),
5524 wantErr: EU(nil).withType('{', float64Type),
5525 }, {
5526 name: jsontest.Name("Floats/Invalid/Array"),
5527 inBuf: `[]`,
5528 inVal: addr(float64(64.64)),
5529 want: addr(float64(64.64)),
5530 wantErr: EU(nil).withType('[', float64Type),
5531 }, {
5532 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
5533 opts: []Options{invalidFormatOption},
5534 inBuf: `1`,
5535 inVal: addr(float64(0)),
5536 want: addr(float64(1)),
5537 }, {
5538 name: jsontest.Name("Maps/Null"),
5539 inBuf: `null`,
5540 inVal: addr(map[string]string{"key": "value"}),
5541 want: new(map[string]string),
5542 }, {
5543 name: jsontest.Name("Maps/InvalidKey/Bool"),
5544 inBuf: `{"true":"false"}`,
5545 inVal: new(map[bool]bool),
5546 want: addr(make(map[bool]bool)),
5547 wantErr: EU(nil).withPos(`{`, "/true").withType('"', boolType),
5548 }, {
5549 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
5550 inBuf: `{"true":"false"}`,
5551 inVal: new(map[namedBool]bool),
5552 want: addr(make(map[namedBool]bool)),
5553 wantErr: EU(nil).withPos(`{`, "/true").withType('"', T[namedBool]()),
5554 }, {
5555 name: jsontest.Name("Maps/InvalidKey/Array"),
5556 inBuf: `{"key":"value"}`,
5557 inVal: new(map[[1]string]string),
5558 want: addr(make(map[[1]string]string)),
5559 wantErr: EU(nil).withPos(`{`, "/key").withType('"', T[[1]string]()),
5560 }, {
5561 name: jsontest.Name("Maps/InvalidKey/Channel"),
5562 inBuf: `{"key":"value"}`,
5563 inVal: new(map[chan string]string),
5564 want: addr(make(map[chan string]string)),
5565 wantErr: EU(nil).withPos(`{`, "").withType(0, T[chan string]()),
5566 }, {
5567 name: jsontest.Name("Maps/ValidKey/Int"),
5568 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5569 inVal: new(map[int]int),
5570 want: addr(map[int]int{0: 0, -1: 1, 2: 2, -3: 3}),
5571 }, {
5572 name: jsontest.Name("Maps/ValidKey/NamedInt"),
5573 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5574 inVal: new(map[namedInt64]int),
5575 want: addr(map[namedInt64]int{0: 0, -1: 1, 2: 2, -3: 3}),
5576 }, {
5577 name: jsontest.Name("Maps/ValidKey/Uint"),
5578 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5579 inVal: new(map[uint]uint),
5580 want: addr(map[uint]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5581 }, {
5582 name: jsontest.Name("Maps/ValidKey/NamedUint"),
5583 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5584 inVal: new(map[namedUint64]uint),
5585 want: addr(map[namedUint64]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5586 }, {
5587 name: jsontest.Name("Maps/ValidKey/Float"),
5588 inBuf: `{"1.234":1.234,"12.34":12.34,"123.4":123.4}`,
5589 inVal: new(map[float64]float64),
5590 want: addr(map[float64]float64{1.234: 1.234, 12.34: 12.34, 123.4: 123.4}),
5591 }, {
5592 name: jsontest.Name("Maps/DuplicateName/Int"),
5593 inBuf: `{"0":1,"-0":-1}`,
5594 inVal: new(map[int]int),
5595 want: addr(map[int]int{0: 1}),
5596 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5597 }, {
5598 name: jsontest.Name("Maps/DuplicateName/Int/MergeWithLegacySemantics"),
5599 opts: []Options{jsonflags.MergeWithLegacySemantics | 1},
5600 inBuf: `{"0":1,"-0":-1}`,
5601 inVal: new(map[int]int),
5602 want: addr(map[int]int{0: 1}),
5603 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5604 }, {
5605 name: jsontest.Name("Maps/DuplicateName/Int/AllowDuplicateNames"),
5606 opts: []Options{jsontext.AllowDuplicateNames(true)},
5607 inBuf: `{"0":1,"-0":-1}`,
5608 inVal: new(map[int]int),
5609 want: addr(map[int]int{0: -1}),
5610 }, {
5611 name: jsontest.Name("Maps/DuplicateName/Int/OverwriteExisting"),
5612 inBuf: `{"-0":-1}`,
5613 inVal: addr(map[int]int{0: 1}),
5614 want: addr(map[int]int{0: -1}),
5615 }, {
5616 name: jsontest.Name("Maps/DuplicateName/Float"),
5617 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5618 inVal: new(map[float64]string),
5619 want: addr(map[float64]string{1: "1.0"}),
5620 wantErr: newDuplicateNameError("", []byte(`"1"`), len64(`{"1.0":"1.0",`)),
5621 }, {
5622 name: jsontest.Name("Maps/DuplicateName/Float/AllowDuplicateNames"),
5623 opts: []Options{jsontext.AllowDuplicateNames(true)},
5624 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5625 inVal: new(map[float64]string),
5626 want: addr(map[float64]string{1: "1e0"}),
5627 }, {
5628 name: jsontest.Name("Maps/DuplicateName/Float/OverwriteExisting"),
5629 inBuf: `{"1.0":"1.0"}`,
5630 inVal: addr(map[float64]string{1: "1"}),
5631 want: addr(map[float64]string{1: "1.0"}),
5632 }, {
5633 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
5634 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5635 inVal: new(map[nocaseString]string),
5636 want: addr(map[nocaseString]string{"hello": "hello"}),
5637 wantErr: newDuplicateNameError("", []byte(`"HELLO"`), len64(`{"hello":"hello",`)),
5638 }, {
5639 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
5640 opts: []Options{jsontext.AllowDuplicateNames(true)},
5641 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5642 inVal: new(map[nocaseString]string),
5643 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5644 }, {
5645 name: jsontest.Name("Maps/DuplicateName/NoCaseString/OverwriteExisting"),
5646 opts: []Options{jsontext.AllowDuplicateNames(true)},
5647 inBuf: `{"HELLO":"HELLO"}`,
5648 inVal: addr(map[nocaseString]string{"hello": "hello"}),
5649 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5650 }, {
5651 name: jsontest.Name("Maps/ValidKey/Interface"),
5652 inBuf: `{"false":"false","true":"true","string":"string","0":"0","[]":"[]","{}":"{}"}`,
5653 inVal: new(map[any]string),
5654 want: addr(map[any]string{
5655 "false": "false",
5656 "true": "true",
5657 "string": "string",
5658 "0": "0",
5659 "[]": "[]",
5660 "{}": "{}",
5661 }),
5662 }, {
5663 name: jsontest.Name("Maps/InvalidValue/Channel"),
5664 inBuf: `{"key":"value"}`,
5665 inVal: new(map[string]chan string),
5666 want: addr(map[string]chan string{
5667 "key": nil,
5668 }),
5669 wantErr: EU(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
5670 }, {
5671 name: jsontest.Name("Maps/RecursiveMap"),
5672 inBuf: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
5673 inVal: new(recursiveMap),
5674 want: addr(recursiveMap{
5675 "fizz": {
5676 "foo": {},
5677 "bar": {},
5678 },
5679 "buzz": {},
5680 }),
5681 }, {
5682
5683
5684
5685 name: jsontest.Name("Maps/Merge"),
5686 opts: []Options{jsontext.AllowDuplicateNames(true)},
5687 inBuf: `{"k1":{"k2":"v2"},"k2":{"k1":"v1"},"k2":{"k2":"v2"}}`,
5688 inVal: addr(map[string]map[string]string{
5689 "k1": {"k1": "v1"},
5690 }),
5691 want: addr(map[string]map[string]string{
5692 "k1": {"k1": "v1", "k2": "v2"},
5693 "k2": {"k1": "v1", "k2": "v2"},
5694 }),
5695 }, {
5696 name: jsontest.Name("Maps/Invalid/Bool"),
5697 inBuf: `true`,
5698 inVal: addr(map[string]string{"key": "value"}),
5699 want: addr(map[string]string{"key": "value"}),
5700 wantErr: EU(nil).withType('t', T[map[string]string]()),
5701 }, {
5702 name: jsontest.Name("Maps/Invalid/String"),
5703 inBuf: `""`,
5704 inVal: addr(map[string]string{"key": "value"}),
5705 want: addr(map[string]string{"key": "value"}),
5706 wantErr: EU(nil).withType('"', T[map[string]string]()),
5707 }, {
5708 name: jsontest.Name("Maps/Invalid/Number"),
5709 inBuf: `0`,
5710 inVal: addr(map[string]string{"key": "value"}),
5711 want: addr(map[string]string{"key": "value"}),
5712 wantErr: EU(nil).withType('0', T[map[string]string]()),
5713 }, {
5714 name: jsontest.Name("Maps/Invalid/Array"),
5715 inBuf: `[]`,
5716 inVal: addr(map[string]string{"key": "value"}),
5717 want: addr(map[string]string{"key": "value"}),
5718 wantErr: EU(nil).withType('[', T[map[string]string]()),
5719 }, {
5720 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
5721 opts: []Options{invalidFormatOption},
5722 inBuf: `{"hello":"goodbye"}`,
5723 inVal: addr(map[string]string{}),
5724 want: addr(map[string]string{"hello": "goodbye"}),
5725 }, {
5726 name: jsontest.Name("Structs/Null"),
5727 inBuf: `null`,
5728 inVal: addr(structAll{String: "something"}),
5729 want: addr(structAll{}),
5730 }, {
5731 name: jsontest.Name("Structs/Empty"),
5732 inBuf: `{}`,
5733 inVal: addr(structAll{
5734 String: "hello",
5735 Map: map[string]string{},
5736 Slice: []string{},
5737 }),
5738 want: addr(structAll{
5739 String: "hello",
5740 Map: map[string]string{},
5741 Slice: []string{},
5742 }),
5743 }, {
5744 name: jsontest.Name("Structs/Normal"),
5745 inBuf: `{
5746 "Bool": true,
5747 "String": "hello",
5748 "Bytes": "AQID",
5749 "Int": -64,
5750 "Uint": 64,
5751 "Float": 3.14159,
5752 "Map": {"key": "value"},
5753 "StructScalars": {
5754 "Bool": true,
5755 "String": "hello",
5756 "Bytes": "AQID",
5757 "Int": -64,
5758 "Uint": 64,
5759 "Float": 3.14159
5760 },
5761 "StructMaps": {
5762 "MapBool": {"": true},
5763 "MapString": {"": "hello"},
5764 "MapBytes": {"": "AQID"},
5765 "MapInt": {"": -64},
5766 "MapUint": {"": 64},
5767 "MapFloat": {"": 3.14159}
5768 },
5769 "StructSlices": {
5770 "SliceBool": [true],
5771 "SliceString": ["hello"],
5772 "SliceBytes": ["AQID"],
5773 "SliceInt": [-64],
5774 "SliceUint": [64],
5775 "SliceFloat": [3.14159]
5776 },
5777 "Slice": ["fizz","buzz"],
5778 "Array": ["goodbye"],
5779 "Pointer": {},
5780 "Interface": null
5781 }`,
5782 inVal: new(structAll),
5783 want: addr(structAll{
5784 Bool: true,
5785 String: "hello",
5786 Bytes: []byte{1, 2, 3},
5787 Int: -64,
5788 Uint: +64,
5789 Float: 3.14159,
5790 Map: map[string]string{"key": "value"},
5791 StructScalars: structScalars{
5792 Bool: true,
5793 String: "hello",
5794 Bytes: []byte{1, 2, 3},
5795 Int: -64,
5796 Uint: +64,
5797 Float: 3.14159,
5798 },
5799 StructMaps: structMaps{
5800 MapBool: map[string]bool{"": true},
5801 MapString: map[string]string{"": "hello"},
5802 MapBytes: map[string][]byte{"": {1, 2, 3}},
5803 MapInt: map[string]int64{"": -64},
5804 MapUint: map[string]uint64{"": +64},
5805 MapFloat: map[string]float64{"": 3.14159},
5806 },
5807 StructSlices: structSlices{
5808 SliceBool: []bool{true},
5809 SliceString: []string{"hello"},
5810 SliceBytes: [][]byte{{1, 2, 3}},
5811 SliceInt: []int64{-64},
5812 SliceUint: []uint64{+64},
5813 SliceFloat: []float64{3.14159},
5814 },
5815 Slice: []string{"fizz", "buzz"},
5816 Array: [1]string{"goodbye"},
5817 Pointer: new(structAll),
5818 }),
5819 }, {
5820 name: jsontest.Name("Structs/Merge"),
5821 inBuf: `{
5822 "Bool": false,
5823 "String": "goodbye",
5824 "Int": -64,
5825 "Float": 3.14159,
5826 "Map": {"k2": "v2"},
5827 "StructScalars": {
5828 "Bool": true,
5829 "String": "hello",
5830 "Bytes": "AQID",
5831 "Int": -64
5832 },
5833 "StructMaps": {
5834 "MapBool": {"": true},
5835 "MapString": {"": "hello"},
5836 "MapBytes": {"": "AQID"},
5837 "MapInt": {"": -64},
5838 "MapUint": {"": 64},
5839 "MapFloat": {"": 3.14159}
5840 },
5841 "StructSlices": {
5842 "SliceString": ["hello"],
5843 "SliceBytes": ["AQID"],
5844 "SliceInt": [-64],
5845 "SliceUint": [64]
5846 },
5847 "Slice": ["fizz","buzz"],
5848 "Array": ["goodbye"],
5849 "Pointer": {},
5850 "Interface": {"k2":"v2"}
5851 }`,
5852 inVal: addr(structAll{
5853 Bool: true,
5854 String: "hello",
5855 Bytes: []byte{1, 2, 3},
5856 Uint: +64,
5857 Float: math.NaN(),
5858 Map: map[string]string{"k1": "v1"},
5859 StructScalars: structScalars{
5860 String: "hello",
5861 Bytes: make([]byte, 2, 4),
5862 Uint: +64,
5863 Float: 3.14159,
5864 },
5865 StructMaps: structMaps{
5866 MapBool: map[string]bool{"": false},
5867 MapBytes: map[string][]byte{"": {}},
5868 MapInt: map[string]int64{"": 123},
5869 MapFloat: map[string]float64{"": math.Inf(+1)},
5870 },
5871 StructSlices: structSlices{
5872 SliceBool: []bool{true},
5873 SliceBytes: [][]byte{nil, nil},
5874 SliceInt: []int64{-123},
5875 SliceUint: []uint64{+123},
5876 SliceFloat: []float64{3.14159},
5877 },
5878 Slice: []string{"buzz", "fizz", "gizz"},
5879 Array: [1]string{"hello"},
5880 Pointer: new(structAll),
5881 Interface: map[string]string{"k1": "v1"},
5882 }),
5883 want: addr(structAll{
5884 Bool: false,
5885 String: "goodbye",
5886 Bytes: []byte{1, 2, 3},
5887 Int: -64,
5888 Uint: +64,
5889 Float: 3.14159,
5890 Map: map[string]string{"k1": "v1", "k2": "v2"},
5891 StructScalars: structScalars{
5892 Bool: true,
5893 String: "hello",
5894 Bytes: []byte{1, 2, 3},
5895 Int: -64,
5896 Uint: +64,
5897 Float: 3.14159,
5898 },
5899 StructMaps: structMaps{
5900 MapBool: map[string]bool{"": true},
5901 MapString: map[string]string{"": "hello"},
5902 MapBytes: map[string][]byte{"": {1, 2, 3}},
5903 MapInt: map[string]int64{"": -64},
5904 MapUint: map[string]uint64{"": +64},
5905 MapFloat: map[string]float64{"": 3.14159},
5906 },
5907 StructSlices: structSlices{
5908 SliceBool: []bool{true},
5909 SliceString: []string{"hello"},
5910 SliceBytes: [][]byte{{1, 2, 3}},
5911 SliceInt: []int64{-64},
5912 SliceUint: []uint64{+64},
5913 SliceFloat: []float64{3.14159},
5914 },
5915 Slice: []string{"fizz", "buzz"},
5916 Array: [1]string{"goodbye"},
5917 Pointer: new(structAll),
5918 Interface: map[string]string{"k1": "v1", "k2": "v2"},
5919 }),
5920 }, {
5921 name: jsontest.Name("Structs/Stringified/Normal"),
5922 inBuf: `{
5923 "Bool": true,
5924 "String": "hello",
5925 "Bytes": "AQID",
5926 "Int": "-64",
5927 "Uint": "64",
5928 "Float": "3.14159",
5929 "Map": {"key": "value"},
5930 "StructScalars": {
5931 "Bool": true,
5932 "String": "hello",
5933 "Bytes": "AQID",
5934 "Int": "-64",
5935 "Uint": "64",
5936 "Float": "3.14159"
5937 },
5938 "StructMaps": {
5939 "MapBool": {"": true},
5940 "MapString": {"": "hello"},
5941 "MapBytes": {"": "AQID"},
5942 "MapInt": {"": "-64"},
5943 "MapUint": {"": "64"},
5944 "MapFloat": {"": "3.14159"}
5945 },
5946 "StructSlices": {
5947 "SliceBool": [true],
5948 "SliceString": ["hello"],
5949 "SliceBytes": ["AQID"],
5950 "SliceInt": ["-64"],
5951 "SliceUint": ["64"],
5952 "SliceFloat": ["3.14159"]
5953 },
5954 "Slice": ["fizz","buzz"],
5955 "Array": ["goodbye"],
5956 "Pointer": {},
5957 "Interface": null
5958 }`,
5959 inVal: new(structStringifiedAll),
5960 want: addr(structStringifiedAll{
5961 Bool: true,
5962 String: "hello",
5963 Bytes: []byte{1, 2, 3},
5964 Int: -64,
5965 Uint: +64,
5966 Float: 3.14159,
5967 Map: map[string]string{"key": "value"},
5968 StructScalars: structScalars{
5969 Bool: true,
5970 String: "hello",
5971 Bytes: []byte{1, 2, 3},
5972 Int: -64,
5973 Uint: +64,
5974 Float: 3.14159,
5975 },
5976 StructMaps: structMaps{
5977 MapBool: map[string]bool{"": true},
5978 MapString: map[string]string{"": "hello"},
5979 MapBytes: map[string][]byte{"": {1, 2, 3}},
5980 MapInt: map[string]int64{"": -64},
5981 MapUint: map[string]uint64{"": +64},
5982 MapFloat: map[string]float64{"": 3.14159},
5983 },
5984 StructSlices: structSlices{
5985 SliceBool: []bool{true},
5986 SliceString: []string{"hello"},
5987 SliceBytes: [][]byte{{1, 2, 3}},
5988 SliceInt: []int64{-64},
5989 SliceUint: []uint64{+64},
5990 SliceFloat: []float64{3.14159},
5991 },
5992 Slice: []string{"fizz", "buzz"},
5993 Array: [1]string{"goodbye"},
5994 Pointer: new(structStringifiedAll),
5995 }),
5996 }, {
5997 name: jsontest.Name("Structs/Stringified/String"),
5998 inBuf: `{
5999 "Bool": true,
6000 "String": "hello",
6001 "Bytes": "AQID",
6002 "Int": "-64",
6003 "Uint": "64",
6004 "Float": "3.14159",
6005 "Map": {"key": "value"},
6006 "StructScalars": {
6007 "Bool": true,
6008 "String": "hello",
6009 "Bytes": "AQID",
6010 "Int": "-64",
6011 "Uint": "64",
6012 "Float": "3.14159"
6013 },
6014 "StructMaps": {
6015 "MapBool": {"": true},
6016 "MapString": {"": "hello"},
6017 "MapBytes": {"": "AQID"},
6018 "MapInt": {"": "-64"},
6019 "MapUint": {"": "64"},
6020 "MapFloat": {"": "3.14159"}
6021 },
6022 "StructSlices": {
6023 "SliceBool": [true],
6024 "SliceString": ["hello"],
6025 "SliceBytes": ["AQID"],
6026 "SliceInt": ["-64"],
6027 "SliceUint": ["64"],
6028 "SliceFloat": ["3.14159"]
6029 },
6030 "Slice": ["fizz","buzz"],
6031 "Array": ["goodbye"],
6032 "Pointer": {},
6033 "Interface": null
6034 }`,
6035 inVal: new(structStringifiedAll),
6036 want: addr(structStringifiedAll{
6037 Bool: true,
6038 String: "hello",
6039 Bytes: []byte{1, 2, 3},
6040 Int: -64,
6041 Uint: +64,
6042 Float: 3.14159,
6043 Map: map[string]string{"key": "value"},
6044 StructScalars: structScalars{
6045 Bool: true,
6046 String: "hello",
6047 Bytes: []byte{1, 2, 3},
6048 Int: -64,
6049 Uint: +64,
6050 Float: 3.14159,
6051 },
6052 StructMaps: structMaps{
6053 MapBool: map[string]bool{"": true},
6054 MapString: map[string]string{"": "hello"},
6055 MapBytes: map[string][]byte{"": {1, 2, 3}},
6056 MapInt: map[string]int64{"": -64},
6057 MapUint: map[string]uint64{"": +64},
6058 MapFloat: map[string]float64{"": 3.14159},
6059 },
6060 StructSlices: structSlices{
6061 SliceBool: []bool{true},
6062 SliceString: []string{"hello"},
6063 SliceBytes: [][]byte{{1, 2, 3}},
6064 SliceInt: []int64{-64},
6065 SliceUint: []uint64{+64},
6066 SliceFloat: []float64{3.14159},
6067 },
6068 Slice: []string{"fizz", "buzz"},
6069 Array: [1]string{"goodbye"},
6070 Pointer: new(structStringifiedAll),
6071 }),
6072 }, {
6073 name: jsontest.Name("Structs/Stringified/InvalidEmpty"),
6074 inBuf: `{"Int":""}`,
6075 inVal: new(structStringifiedAll),
6076 want: new(structStringifiedAll),
6077 wantErr: EU(strconv.ErrSyntax).withVal(`""`).withPos(`{"Int":`, "/Int").withType('"', T[int64]()),
6078 }, {
6079 name: jsontest.Name("Structs/LegacyStringified"),
6080 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6081 inBuf: `{
6082 "Bool": "true",
6083 "String": "\"hello\"",
6084 "Bytes": "AQID",
6085 "Int": "-64",
6086 "Uint": "64",
6087 "Float": "3.14159",
6088 "Map": {"key": "value"},
6089 "StructScalars": {
6090 "Bool": true,
6091 "String": "hello",
6092 "Bytes": "AQID",
6093 "Int": -64,
6094 "Uint": 64,
6095 "Float": 3.14159
6096 },
6097 "StructMaps": {
6098 "MapBool": {"": true},
6099 "MapString": {"": "hello"},
6100 "MapBytes": {"": "AQID"},
6101 "MapInt": {"": -64},
6102 "MapUint": {"": 64},
6103 "MapFloat": {"": 3.14159}
6104 },
6105 "StructSlices": {
6106 "SliceBool": [true],
6107 "SliceString": ["hello"],
6108 "SliceBytes": ["AQID"],
6109 "SliceInt": [-64],
6110 "SliceUint": [64],
6111 "SliceFloat": [3.14159]
6112 },
6113 "Slice": ["fizz", "buzz"],
6114 "Array": ["goodbye"]
6115 }`,
6116 inVal: new(structStringifiedAll),
6117 want: addr(structStringifiedAll{
6118 Bool: true,
6119 String: "hello",
6120 Bytes: []byte{1, 2, 3},
6121 Int: -64,
6122 Uint: +64,
6123 Float: 3.14159,
6124 Map: map[string]string{"key": "value"},
6125 StructScalars: structScalars{
6126 Bool: true,
6127 String: "hello",
6128 Bytes: []byte{1, 2, 3},
6129 Int: -64,
6130 Uint: +64,
6131 Float: 3.14159,
6132 },
6133 StructMaps: structMaps{
6134 MapBool: map[string]bool{"": true},
6135 MapString: map[string]string{"": "hello"},
6136 MapBytes: map[string][]byte{"": {1, 2, 3}},
6137 MapInt: map[string]int64{"": -64},
6138 MapUint: map[string]uint64{"": +64},
6139 MapFloat: map[string]float64{"": 3.14159},
6140 },
6141 StructSlices: structSlices{
6142 SliceBool: []bool{true},
6143 SliceString: []string{"hello"},
6144 SliceBytes: [][]byte{{1, 2, 3}},
6145 SliceInt: []int64{-64},
6146 SliceUint: []uint64{+64},
6147 SliceFloat: []float64{3.14159},
6148 },
6149 Slice: []string{"fizz", "buzz"},
6150 Array: [1]string{"goodbye"},
6151 }),
6152 }, {
6153 name: jsontest.Name("Structs/LegacyStringified/InvalidBool"),
6154 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6155 inBuf: `{"Bool": true}`,
6156 inVal: new(structStringifiedAll),
6157 wantErr: EU(nil).withPos(`{"Bool": `, "/Bool").withType('t', T[bool]()),
6158 }, {
6159 name: jsontest.Name("Structs/LegacyStringified/InvalidString"),
6160 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6161 inBuf: `{"String": "string"}`,
6162 inVal: new(structStringifiedAll),
6163 wantErr: EU(newInvalidCharacterError("s", "at start of string (expecting '\"')", 0, "")).
6164 withPos(`{"String": `, "/String").withType('"', T[string]()),
6165 }, {
6166 name: jsontest.Name("Structs/Format/Bytes"),
6167 inBuf: `{
6168 "Base16": "0123456789abcdef",
6169 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
6170 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
6171 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
6172 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
6173 "Array": [1, 2, 3, 4]
6174 }`,
6175 inVal: new(structFormatBytes),
6176 want: addr(structFormatBytes{
6177 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
6178 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6179 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6180 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߿"),
6181 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߿"),
6182 Array: []byte{1, 2, 3, 4},
6183 }),
6184 }, {
6185 name: jsontest.Name("Structs/Format/ArrayBytes"),
6186 inBuf: `{
6187 "Base16": "01020304",
6188 "Base32": "AEBAGBA=",
6189 "Base32Hex": "0410610=",
6190 "Base64": "AQIDBA==",
6191 "Base64URL": "AQIDBA==",
6192 "Array": [1, 2, 3, 4],
6193 "Default": "AQIDBA=="
6194 }`,
6195 inVal: new(structFormatArrayBytes),
6196 want: addr(structFormatArrayBytes{
6197 Base16: [4]byte{1, 2, 3, 4},
6198 Base32: [4]byte{1, 2, 3, 4},
6199 Base32Hex: [4]byte{1, 2, 3, 4},
6200 Base64: [4]byte{1, 2, 3, 4},
6201 Base64URL: [4]byte{1, 2, 3, 4},
6202 Array: [4]byte{1, 2, 3, 4},
6203 Default: [4]byte{1, 2, 3, 4},
6204 }),
6205 }, {
6206 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
6207 opts: []Options{jsonflags.FormatBytesWithLegacySemantics | 1},
6208 inBuf: `{
6209 "Base16": "01020304",
6210 "Base32": "AEBAGBA=",
6211 "Base32Hex": "0410610=",
6212 "Base64": "AQIDBA==",
6213 "Base64URL": "AQIDBA==",
6214 "Array": [1, 2, 3, 4],
6215 "Default": [1, 2, 3, 4]
6216 }`,
6217 inVal: new(structFormatArrayBytes),
6218 want: addr(structFormatArrayBytes{
6219 Base16: [4]byte{1, 2, 3, 4},
6220 Base32: [4]byte{1, 2, 3, 4},
6221 Base32Hex: [4]byte{1, 2, 3, 4},
6222 Base64: [4]byte{1, 2, 3, 4},
6223 Base64URL: [4]byte{1, 2, 3, 4},
6224 Array: [4]byte{1, 2, 3, 4},
6225 Default: [4]byte{1, 2, 3, 4},
6226 }),
6227 }, {
6228 name: jsontest.Name("Structs/Format/Bytes/Array"),
6229 opts: []Options{
6230 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *byte) error {
6231 if string(b) == "true" {
6232 *v = 1
6233 } else {
6234 *v = 0
6235 }
6236 return nil
6237 })),
6238 },
6239 inBuf: `{"Array":[false,true,false,true,false,true]}`,
6240 inVal: new(struct {
6241 Array []byte `json:",format:array"`
6242 }),
6243 want: addr(struct {
6244 Array []byte `json:",format:array"`
6245 }{
6246 Array: []byte{0, 1, 0, 1, 0, 1},
6247 }),
6248 }, {
6249 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/WrongKind"),
6250 inBuf: `{"Base16": [1,2,3,4]}`,
6251 inVal: new(structFormatBytes),
6252 wantErr: EU(nil).withPos(`{"Base16": `, "/Base16").withType('[', T[[]byte]()),
6253 }, {
6254 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/AllPadding"),
6255 inBuf: `{"Base16": "===="}`,
6256 inVal: new(structFormatBytes),
6257 wantErr: EU(func() error {
6258 _, err := hex.Decode(make([]byte, 2), []byte("====="))
6259 return err
6260 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6261 }, {
6262 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/EvenPadding"),
6263 inBuf: `{"Base16": "0123456789abcdef="}`,
6264 inVal: new(structFormatBytes),
6265 wantErr: EU(func() error {
6266 _, err := hex.Decode(make([]byte, 8), []byte("0123456789abcdef="))
6267 return err
6268 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6269 }, {
6270 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/OddPadding"),
6271 inBuf: `{"Base16": "0123456789abcdef0="}`,
6272 inVal: new(structFormatBytes),
6273 wantErr: EU(func() error {
6274 _, err := hex.Decode(make([]byte, 9), []byte("0123456789abcdef0="))
6275 return err
6276 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6277 }, {
6278 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/LineFeed"),
6279 inBuf: `{"Base16": "aa\naa"}`,
6280 inVal: new(structFormatBytes),
6281 wantErr: EU(func() error {
6282 _, err := hex.Decode(make([]byte, 9), []byte("aa\naa"))
6283 return err
6284 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6285 }, {
6286 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/CarriageReturn"),
6287 inBuf: `{"Base16": "aa\raa"}`,
6288 inVal: new(structFormatBytes),
6289 wantErr: EU(func() error {
6290 _, err := hex.Decode(make([]byte, 9), []byte("aa\raa"))
6291 return err
6292 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6293 }, {
6294 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/Space"),
6295 inBuf: `{"Base16": "aa aa"}`,
6296 inVal: new(structFormatBytes),
6297 wantErr: EU(func() error {
6298 _, err := hex.Decode(make([]byte, 9), []byte("aa aa"))
6299 return err
6300 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6301 }, {
6302 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Padding"),
6303 inBuf: `[
6304 {"Base32": "NA======"},
6305 {"Base32": "NBSQ===="},
6306 {"Base32": "NBSWY==="},
6307 {"Base32": "NBSWY3A="},
6308 {"Base32": "NBSWY3DP"}
6309 ]`,
6310 inVal: new([]structFormatBytes),
6311 want: addr([]structFormatBytes{
6312 {Base32: []byte("h")},
6313 {Base32: []byte("he")},
6314 {Base32: []byte("hel")},
6315 {Base32: []byte("hell")},
6316 {Base32: []byte("hello")},
6317 }),
6318 }, {
6319 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Invalid/NoPadding"),
6320 inBuf: `[
6321 {"Base32": "NA"},
6322 {"Base32": "NBSQ"},
6323 {"Base32": "NBSWY"},
6324 {"Base32": "NBSWY3A"},
6325 {"Base32": "NBSWY3DP"}
6326 ]`,
6327 inVal: new([]structFormatBytes),
6328 wantErr: EU(func() error {
6329 _, err := base32.StdEncoding.Decode(make([]byte, 1), []byte("NA"))
6330 return err
6331 }()).withPos(`[`+"\n\t\t\t\t"+`{"Base32": `, "/0/Base32").withType('"', T[[]byte]()),
6332 }, {
6333 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/WrongAlphabet"),
6334 inBuf: `{"Base32": "0123456789ABCDEFGHIJKLMNOPQRSTUV"}`,
6335 inVal: new(structFormatBytes),
6336 wantErr: EU(func() error {
6337 _, err := base32.StdEncoding.Decode(make([]byte, 20), []byte("0123456789ABCDEFGHIJKLMNOPQRSTUV"))
6338 return err
6339 }()).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6340 }, {
6341 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32Hex/WrongAlphabet"),
6342 inBuf: `{"Base32Hex": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"}`,
6343 inVal: new(structFormatBytes),
6344 wantErr: EU(func() error {
6345 _, err := base32.HexEncoding.Decode(make([]byte, 20), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"))
6346 return err
6347 }()).withPos(`{"Base32Hex": `, "/Base32Hex").withType('"', T[[]byte]()),
6348 }, {
6349 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/LineFeed"),
6350 inBuf: `{"Base32": "AAAA\nAAAA"}`,
6351 inVal: new(structFormatBytes),
6352 wantErr: EU(errors.New("illegal character '\\n' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6353 }, {
6354 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/CarriageReturn"),
6355 inBuf: `{"Base32": "AAAA\rAAAA"}`,
6356 inVal: new(structFormatBytes),
6357 wantErr: EU(errors.New("illegal character '\\r' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6358 }, {
6359 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/Space"),
6360 inBuf: `{"Base32": "AAAA AAAA"}`,
6361 inVal: new(structFormatBytes),
6362 wantErr: EU(base32.CorruptInputError(4)).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6363 }, {
6364 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/WrongAlphabet"),
6365 inBuf: `{"Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"}`,
6366 inVal: new(structFormatBytes),
6367 wantErr: EU(func() error {
6368 _, err := base64.StdEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"))
6369 return err
6370 }()).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6371 }, {
6372 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64URL/WrongAlphabet"),
6373 inBuf: `{"Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}`,
6374 inVal: new(structFormatBytes),
6375 wantErr: EU(func() error {
6376 _, err := base64.URLEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
6377 return err
6378 }()).withPos(`{"Base64URL": `, "/Base64URL").withType('"', T[[]byte]()),
6379 }, {
6380 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/LineFeed"),
6381 inBuf: `{"Base64": "aa=\n="}`,
6382 inVal: new(structFormatBytes),
6383 wantErr: EU(errors.New("illegal character '\\n' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6384 }, {
6385 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/CarriageReturn"),
6386 inBuf: `{"Base64": "aa=\r="}`,
6387 inVal: new(structFormatBytes),
6388 wantErr: EU(errors.New("illegal character '\\r' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6389 }, {
6390 name: jsontest.Name("Structs/Format/Bytes/Base64/NonAlphabet/Ignored"),
6391 opts: []Options{jsonflags.ParseBytesWithLooseRFC4648 | 1},
6392 inBuf: `{"Base64": "aa=\r\n="}`,
6393 inVal: new(structFormatBytes),
6394 want: &structFormatBytes{Base64: []byte{105}},
6395 }, {
6396 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/Space"),
6397 inBuf: `{"Base64": "aa= ="}`,
6398 inVal: new(structFormatBytes),
6399 wantErr: EU(base64.CorruptInputError(2)).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6400 }, {
6401 name: jsontest.Name("Structs/Format/Floats"),
6402 inBuf: `[
6403 {"NonFinite": 3.141592653589793, "PointerNonFinite": 3.141592653589793},
6404 {"NonFinite": "-Infinity", "PointerNonFinite": "-Infinity"},
6405 {"NonFinite": "Infinity", "PointerNonFinite": "Infinity"}
6406 ]`,
6407 inVal: new([]structFormatFloats),
6408 want: addr([]structFormatFloats{
6409 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
6410 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
6411 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
6412 }),
6413 }, {
6414 name: jsontest.Name("Structs/Format/Floats/NaN"),
6415 inBuf: `{"NonFinite": "NaN"}`,
6416 inVal: new(structFormatFloats),
6417
6418 }, {
6419 name: jsontest.Name("Structs/Format/Floats/Invalid/NaN"),
6420 inBuf: `{"NonFinite": "nan"}`,
6421 inVal: new(structFormatFloats),
6422 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6423 }, {
6424 name: jsontest.Name("Structs/Format/Floats/Invalid/PositiveInfinity"),
6425 inBuf: `{"NonFinite": "+Infinity"}`,
6426 inVal: new(structFormatFloats),
6427 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6428 }, {
6429 name: jsontest.Name("Structs/Format/Floats/Invalid/NegativeInfinitySpace"),
6430 inBuf: `{"NonFinite": "-Infinity "}`,
6431 inVal: new(structFormatFloats),
6432 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6433 }, {
6434 name: jsontest.Name("Structs/Format/Maps"),
6435 inBuf: `[
6436 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6437 {"EmitNull": {}, "PointerEmitNull": {}, "EmitEmpty": {}, "PointerEmitEmpty": {}, "EmitDefault": {}, "PointerEmitDefault": {}},
6438 {"EmitNull": {"k": "v"}, "PointerEmitNull": {"k": "v"}, "EmitEmpty": {"k": "v"}, "PointerEmitEmpty": {"k": "v"}, "EmitDefault": {"k": "v"}, "PointerEmitDefault": {"k": "v"}}
6439 ]`,
6440 inVal: new([]structFormatMaps),
6441 want: addr([]structFormatMaps{{
6442 EmitNull: map[string]string(nil), PointerEmitNull: (*map[string]string)(nil),
6443 EmitEmpty: map[string]string(nil), PointerEmitEmpty: (*map[string]string)(nil),
6444 EmitDefault: map[string]string(nil), PointerEmitDefault: (*map[string]string)(nil),
6445 }, {
6446 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
6447 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
6448 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
6449 }, {
6450 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
6451 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
6452 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
6453 }}),
6454 }, {
6455 name: jsontest.Name("Structs/Format/Slices"),
6456 inBuf: `[
6457 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6458 {"EmitNull": [], "PointerEmitNull": [], "EmitEmpty": [], "PointerEmitEmpty": [], "EmitDefault": [], "PointerEmitDefault": []},
6459 {"EmitNull": ["v"], "PointerEmitNull": ["v"], "EmitEmpty": ["v"], "PointerEmitEmpty": ["v"], "EmitDefault": ["v"], "PointerEmitDefault": ["v"]}
6460 ]`,
6461 inVal: new([]structFormatSlices),
6462 want: addr([]structFormatSlices{{
6463 EmitNull: []string(nil), PointerEmitNull: (*[]string)(nil),
6464 EmitEmpty: []string(nil), PointerEmitEmpty: (*[]string)(nil),
6465 EmitDefault: []string(nil), PointerEmitDefault: (*[]string)(nil),
6466 }, {
6467 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
6468 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
6469 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
6470 }, {
6471 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
6472 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
6473 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
6474 }}),
6475 }, {
6476 name: jsontest.Name("Structs/Format/Invalid/Bool"),
6477 inBuf: `{"Bool":true}`,
6478 inVal: new(structFormatInvalid),
6479 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, T[bool]()),
6480 }, {
6481 name: jsontest.Name("Structs/Format/Invalid/String"),
6482 inBuf: `{"String": "string"}`,
6483 inVal: new(structFormatInvalid),
6484 wantErr: EU(errInvalidFormatFlag).withPos(`{"String": `, "/String").withType(0, T[string]()),
6485 }, {
6486 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
6487 inBuf: `{"Bytes": "bytes"}`,
6488 inVal: new(structFormatInvalid),
6489 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bytes": `, "/Bytes").withType(0, T[[]byte]()),
6490 }, {
6491 name: jsontest.Name("Structs/Format/Invalid/Int"),
6492 inBuf: `{"Int": 1}`,
6493 inVal: new(structFormatInvalid),
6494 wantErr: EU(errInvalidFormatFlag).withPos(`{"Int": `, "/Int").withType(0, T[int64]()),
6495 }, {
6496 name: jsontest.Name("Structs/Format/Invalid/Uint"),
6497 inBuf: `{"Uint": 1}`,
6498 inVal: new(structFormatInvalid),
6499 wantErr: EU(errInvalidFormatFlag).withPos(`{"Uint": `, "/Uint").withType(0, T[uint64]()),
6500 }, {
6501 name: jsontest.Name("Structs/Format/Invalid/Float"),
6502 inBuf: `{"Float" : 1}`,
6503 inVal: new(structFormatInvalid),
6504 wantErr: EU(errInvalidFormatFlag).withPos(`{"Float" : `, "/Float").withType(0, T[float64]()),
6505 }, {
6506 name: jsontest.Name("Structs/Format/Invalid/Map"),
6507 inBuf: `{"Map":{}}`,
6508 inVal: new(structFormatInvalid),
6509 wantErr: EU(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
6510 }, {
6511 name: jsontest.Name("Structs/Format/Invalid/Struct"),
6512 inBuf: `{"Struct": {}}`,
6513 inVal: new(structFormatInvalid),
6514 wantErr: EU(errInvalidFormatFlag).withPos(`{"Struct": `, "/Struct").withType(0, T[structAll]()),
6515 }, {
6516 name: jsontest.Name("Structs/Format/Invalid/Slice"),
6517 inBuf: `{"Slice": {}}`,
6518 inVal: new(structFormatInvalid),
6519 wantErr: EU(errInvalidFormatFlag).withPos(`{"Slice": `, "/Slice").withType(0, T[[]string]()),
6520 }, {
6521 name: jsontest.Name("Structs/Format/Invalid/Array"),
6522 inBuf: `{"Array": []}`,
6523 inVal: new(structFormatInvalid),
6524 wantErr: EU(errInvalidFormatFlag).withPos(`{"Array": `, "/Array").withType(0, T[[1]string]()),
6525 }, {
6526 name: jsontest.Name("Structs/Format/Invalid/Interface"),
6527 inBuf: `{"Interface": "anything"}`,
6528 inVal: new(structFormatInvalid),
6529 wantErr: EU(errInvalidFormatFlag).withPos(`{"Interface": `, "/Interface").withType(0, T[any]()),
6530 }, {
6531 name: jsontest.Name("Structs/Inline/Zero"),
6532 inBuf: `{"D":""}`,
6533 inVal: new(structInlined),
6534 want: new(structInlined),
6535 }, {
6536 name: jsontest.Name("Structs/Inline/Alloc"),
6537 inBuf: `{"E":"","F":"","G":"","A":"","B":"","D":""}`,
6538 inVal: new(structInlined),
6539 want: addr(structInlined{
6540 X: structInlinedL1{
6541 X: &structInlinedL2{},
6542 StructEmbed1: StructEmbed1{},
6543 },
6544 StructEmbed2: &StructEmbed2{},
6545 }),
6546 }, {
6547 name: jsontest.Name("Structs/Inline/NonZero"),
6548 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6549 inVal: new(structInlined),
6550 want: addr(structInlined{
6551 X: structInlinedL1{
6552 X: &structInlinedL2{A: "A1", B: "B1" },
6553 StructEmbed1: StructEmbed1{ D: "D2" },
6554 },
6555 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6556 }),
6557 }, {
6558 name: jsontest.Name("Structs/Inline/Merge"),
6559 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6560 inVal: addr(structInlined{
6561 X: structInlinedL1{
6562 X: &structInlinedL2{B: "##", C: "C1"},
6563 StructEmbed1: StructEmbed1{C: "C2", E: "E2"},
6564 },
6565 StructEmbed2: &StructEmbed2{E: "##", G: "G3"},
6566 }),
6567 want: addr(structInlined{
6568 X: structInlinedL1{
6569 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
6570 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
6571 },
6572 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6573 }),
6574 }, {
6575 name: jsontest.Name("Structs/InlinedFallback/TextValue/Noop"),
6576 inBuf: `{"A":1,"B":2}`,
6577 inVal: new(structInlineTextValue),
6578 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(nil), B: 2}),
6579 }, {
6580 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Nil"),
6581 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6582 inVal: new(structInlineTextValue),
6583 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6584 }, {
6585 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Empty"),
6586 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6587 inVal: addr(structInlineTextValue{X: jsontext.Value{}}),
6588 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6589 }, {
6590 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Whitespace"),
6591 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6592 inVal: addr(structInlineTextValue{X: jsontext.Value("\n\r\t ")}),
6593 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("")}),
6594 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6595 }, {
6596 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Null"),
6597 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6598 inVal: addr(structInlineTextValue{X: jsontext.Value("null")}),
6599 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("null")}),
6600 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6601 }, {
6602 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/ObjectN0"),
6603 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6604 inVal: addr(structInlineTextValue{X: jsontext.Value(` { } `)}),
6605 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` {"fizz":"buzz"}`), B: 2}),
6606 }, {
6607 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN2/ObjectN1"),
6608 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6609 inVal: addr(structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)}),
6610 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` { "fizz" : "buzz","fizz":"buzz","foo":[ 1 , 2 , 3 ]}`), B: 2}),
6611 }, {
6612 name: jsontest.Name("Structs/InlinedFallback/TextValue/Merge/EndObject"),
6613 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6614 inVal: addr(structInlineTextValue{X: jsontext.Value(` } `)}),
6615
6616
6617 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`,"fizz":"buzz"}`), B: 2}),
6618 }, {
6619 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeInvalidValue"),
6620 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6621 inVal: new(structInlineTextValue),
6622 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":`)}),
6623 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6624 }, {
6625 name: jsontest.Name("Structs/InlinedFallback/TextValue/CaseSensitive"),
6626 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6627 inVal: new(structInlineTextValue),
6628 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","a":3}`), B: 2}),
6629 }, {
6630 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
6631 opts: []Options{jsontext.AllowDuplicateNames(false)},
6632 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6633 inVal: new(structInlineTextValue),
6634 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6635 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6636 }, {
6637 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
6638 opts: []Options{jsontext.AllowDuplicateNames(true)},
6639 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6640 inVal: new(structInlineTextValue),
6641 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`), B: 2}),
6642 }, {
6643 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Noop"),
6644 inBuf: `{}`,
6645 inVal: new(structInlinePointerInlineTextValue),
6646 want: new(structInlinePointerInlineTextValue),
6647 }, {
6648 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Alloc"),
6649 inBuf: `{"A":1,"fizz":"buzz"}`,
6650 inVal: new(structInlinePointerInlineTextValue),
6651 want: addr(structInlinePointerInlineTextValue{
6652 X: &struct {
6653 A int
6654 X jsontext.Value `json:",inline"`
6655 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6656 }),
6657 }, {
6658 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Merge"),
6659 inBuf: `{"fizz":"buzz"}`,
6660 inVal: addr(structInlinePointerInlineTextValue{
6661 X: &struct {
6662 A int
6663 X jsontext.Value `json:",inline"`
6664 }{A: 1},
6665 }),
6666 want: addr(structInlinePointerInlineTextValue{
6667 X: &struct {
6668 A int
6669 X jsontext.Value `json:",inline"`
6670 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6671 }),
6672 }, {
6673 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Noop"),
6674 inBuf: `{"A":1,"B":2}`,
6675 inVal: new(structInlinePointerTextValue),
6676 want: addr(structInlinePointerTextValue{A: 1, X: nil, B: 2}),
6677 }, {
6678 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Alloc"),
6679 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6680 inVal: new(structInlinePointerTextValue),
6681 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz"}`)), B: 2}),
6682 }, {
6683 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Merge"),
6684 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6685 inVal: addr(structInlinePointerTextValue{X: addr(jsontext.Value(`{"fizz":"buzz"}`))}),
6686 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`)), B: 2}),
6687 }, {
6688 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
6689 inBuf: `{"fizz":"buzz"}`,
6690 inVal: new(structInlineInlinePointerTextValue),
6691 want: addr(structInlineInlinePointerTextValue{
6692 X: struct {
6693 X *jsontext.Value `json:",inline"`
6694 }{X: addr(jsontext.Value(`{"fizz":"buzz"}`))},
6695 }),
6696 }, {
6697 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Noop"),
6698 inBuf: `{"A":1,"B":2}`,
6699 inVal: new(structInlineMapStringAny),
6700 want: addr(structInlineMapStringAny{A: 1, X: nil, B: 2}),
6701 }, {
6702 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Nil"),
6703 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6704 inVal: new(structInlineMapStringAny),
6705 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6706 }, {
6707 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Empty"),
6708 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6709 inVal: addr(structInlineMapStringAny{X: jsonObject{}}),
6710 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6711 }, {
6712 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/ObjectN1"),
6713 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6714 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": jsonObject{
6715 "alpha": "bravo",
6716 "charlie": "delta",
6717 }}}),
6718 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{
6719 "alpha": "bravo",
6720 "charlie": "DELTA",
6721 "echo": "foxtrot",
6722 }}, B: 2}),
6723 }, {
6724 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN2/ObjectN1"),
6725 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6726 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": "wuzz"}}),
6727 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6728 }, {
6729 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue"),
6730 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6731 inVal: new(structInlineMapStringAny),
6732 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": nil}}),
6733 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6734 }, {
6735 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue/Existing"),
6736 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6737 inVal: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6738 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6739 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6740 }, {
6741 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/CaseSensitive"),
6742 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6743 inVal: new(structInlineMapStringAny),
6744 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "a": 3.0}, B: 2}),
6745 }, {
6746 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectDuplicateNames"),
6747 opts: []Options{jsontext.AllowDuplicateNames(false)},
6748 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6749 inVal: new(structInlineMapStringAny),
6750 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6751 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6752 }, {
6753 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowDuplicateNames"),
6754 opts: []Options{jsontext.AllowDuplicateNames(true)},
6755 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
6756 inVal: new(structInlineMapStringAny),
6757 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
6758 }, {
6759 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Noop"),
6760 inBuf: `{}`,
6761 inVal: new(structInlinePointerInlineMapStringAny),
6762 want: new(structInlinePointerInlineMapStringAny),
6763 }, {
6764 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Alloc"),
6765 inBuf: `{"A":1,"fizz":"buzz"}`,
6766 inVal: new(structInlinePointerInlineMapStringAny),
6767 want: addr(structInlinePointerInlineMapStringAny{
6768 X: &struct {
6769 A int
6770 X jsonObject `json:",inline"`
6771 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6772 }),
6773 }, {
6774 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Merge"),
6775 inBuf: `{"fizz":"buzz"}`,
6776 inVal: addr(structInlinePointerInlineMapStringAny{
6777 X: &struct {
6778 A int
6779 X jsonObject `json:",inline"`
6780 }{A: 1},
6781 }),
6782 want: addr(structInlinePointerInlineMapStringAny{
6783 X: &struct {
6784 A int
6785 X jsonObject `json:",inline"`
6786 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6787 }),
6788 }, {
6789 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6790 opts: []Options{
6791 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
6792 var err error
6793 *v, err = strconv.ParseFloat(string(bytes.Trim(b, `"`)), 64)
6794 return err
6795 })),
6796 },
6797 inBuf: `{"D":"1.1","E":"2.2","F":"3.3"}`,
6798 inVal: new(structInlineMapStringAny),
6799 want: addr(structInlineMapStringAny{X: jsonObject{"D": 1.1, "E": 2.2, "F": 3.3}}),
6800 }, {
6801 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Noop"),
6802 inBuf: `{"A":1,"B":2}`,
6803 inVal: new(structInlinePointerMapStringAny),
6804 want: addr(structInlinePointerMapStringAny{A: 1, X: nil, B: 2}),
6805 }, {
6806 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Alloc"),
6807 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6808 inVal: new(structInlinePointerMapStringAny),
6809 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "buzz"}), B: 2}),
6810 }, {
6811 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Merge"),
6812 inBuf: `{"A":1,"fizz":"wuzz","B":2}`,
6813 inVal: addr(structInlinePointerMapStringAny{X: addr(jsonObject{"fizz": "buzz"})}),
6814 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "wuzz"}), B: 2}),
6815 }, {
6816 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
6817 inBuf: `{"fizz":"buzz"}`,
6818 inVal: new(structInlineInlinePointerMapStringAny),
6819 want: addr(structInlineInlinePointerMapStringAny{
6820 X: struct {
6821 X *jsonObject `json:",inline"`
6822 }{X: addr(jsonObject{"fizz": "buzz"})},
6823 }),
6824 }, {
6825 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
6826 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6827 inVal: new(structInlineMapStringInt),
6828 want: addr(structInlineMapStringInt{
6829 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6830 }),
6831 }, {
6832 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Null"),
6833 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6834 inVal: new(structInlineMapStringInt),
6835 want: addr(structInlineMapStringInt{
6836 X: map[string]int{"zero": 0, "one": 0, "two": 2},
6837 }),
6838 }, {
6839 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Invalid"),
6840 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6841 inVal: new(structInlineMapStringInt),
6842 want: addr(structInlineMapStringInt{
6843 X: map[string]int{"zero": 0, "one": 0},
6844 }),
6845 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6846 }, {
6847 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
6848 opts: []Options{StringifyNumbers(true)},
6849 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6850 inVal: new(structInlineMapStringInt),
6851 want: addr(structInlineMapStringInt{
6852 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6853 }),
6854 }, {
6855 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6856 opts: []Options{
6857 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6858 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6859 if err != nil {
6860 return err
6861 }
6862 *v = int(i)
6863 return nil
6864 })),
6865 },
6866 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6867 inVal: new(structInlineMapStringInt),
6868 want: addr(structInlineMapStringInt{
6869 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6870 }),
6871 }, {
6872 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
6873 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6874 inVal: new(structInlineMapNamedStringInt),
6875 want: addr(structInlineMapNamedStringInt{
6876 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6877 }),
6878 }, {
6879 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Null"),
6880 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6881 inVal: new(structInlineMapNamedStringInt),
6882 want: addr(structInlineMapNamedStringInt{
6883 X: map[namedString]int{"zero": 0, "one": 0, "two": 2},
6884 }),
6885 }, {
6886 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Invalid"),
6887 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6888 inVal: new(structInlineMapNamedStringInt),
6889 want: addr(structInlineMapNamedStringInt{
6890 X: map[namedString]int{"zero": 0, "one": 0},
6891 }),
6892 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6893 }, {
6894 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/StringifiedNumbers"),
6895 opts: []Options{StringifyNumbers(true)},
6896 inBuf: `{"zero": "0", "one": 1, "two": "2"}`,
6897 inVal: new(structInlineMapNamedStringInt),
6898 want: addr(structInlineMapNamedStringInt{
6899 X: map[namedString]int{"zero": 0, "one": 0},
6900 }),
6901 wantErr: EU(nil).withPos(`{"zero": "0", "one": `, "/one").withType('0', T[int]()),
6902 }, {
6903 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/UnmarshalFunc"),
6904 opts: []Options{
6905 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6906 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6907 if err != nil {
6908 return err
6909 }
6910 *v = int(i)
6911 return nil
6912 })),
6913 },
6914 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6915 inVal: new(structInlineMapNamedStringInt),
6916 want: addr(structInlineMapNamedStringInt{
6917 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6918 }),
6919 }, {
6920 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Noop"),
6921 inBuf: `{"A":1,"B":2}`,
6922 inVal: new(structInlineMapNamedStringAny),
6923 want: addr(structInlineMapNamedStringAny{A: 1, X: nil, B: 2}),
6924 }, {
6925 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Nil"),
6926 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6927 inVal: new(structInlineMapNamedStringAny),
6928 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6929 }, {
6930 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Empty"),
6931 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6932 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{}}),
6933 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6934 }, {
6935 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/ObjectN1"),
6936 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6937 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": jsonObject{
6938 "alpha": "bravo",
6939 "charlie": "delta",
6940 }}}),
6941 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": jsonObject{
6942 "alpha": "bravo",
6943 "charlie": "DELTA",
6944 "echo": "foxtrot",
6945 }}, B: 2}),
6946 }, {
6947 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN2/ObjectN1"),
6948 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6949 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": "wuzz"}}),
6950 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6951 }, {
6952 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue"),
6953 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6954 inVal: new(structInlineMapNamedStringAny),
6955 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": nil}}),
6956 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6957 }, {
6958 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue/Existing"),
6959 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6960 inVal: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
6961 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
6962 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6963 }, {
6964 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/CaseSensitive"),
6965 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6966 inVal: new(structInlineMapNamedStringAny),
6967 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "a": 3.0}, B: 2}),
6968 }, {
6969 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectDuplicateNames"),
6970 opts: []Options{jsontext.AllowDuplicateNames(false)},
6971 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6972 inVal: new(structInlineMapNamedStringAny),
6973 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6974 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6975 }, {
6976 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowDuplicateNames"),
6977 opts: []Options{jsontext.AllowDuplicateNames(true)},
6978 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
6979 inVal: new(structInlineMapNamedStringAny),
6980 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": map[string]any{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
6981 }, {
6982 name: jsontest.Name("Structs/InlinedFallback/RejectUnknownMembers"),
6983 opts: []Options{RejectUnknownMembers(true)},
6984 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6985 inVal: new(structInlineTextValue),
6986 want: addr(structInlineTextValue{
6987 A: 1,
6988 X: jsontext.Value(`{"fizz":"buzz"}`),
6989 B: 2,
6990 }),
6991 }, {
6992 name: jsontest.Name("Structs/UnknownIgnored"),
6993 opts: []Options{RejectUnknownMembers(false)},
6994 inBuf: `{"unknown":"fizzbuzz"}`,
6995 inVal: new(structAll),
6996 want: new(structAll),
6997 }, {
6998 name: jsontest.Name("Structs/RejectUnknownMembers"),
6999 opts: []Options{RejectUnknownMembers(true)},
7000 inBuf: `{"unknown":"fizzbuzz"}`,
7001 inVal: new(structAll),
7002 want: new(structAll),
7003 wantErr: EU(ErrUnknownName).withPos(`{`, "/unknown").withType('"', T[structAll]()),
7004 }, {
7005 name: jsontest.Name("Structs/UnexportedIgnored"),
7006 inBuf: `{"ignored":"unused"}`,
7007 inVal: new(structUnexportedIgnored),
7008 want: new(structUnexportedIgnored),
7009 }, {
7010 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
7011 inBuf: `{"namedString":"unused"}`,
7012 inVal: new(structIgnoredUnexportedEmbedded),
7013 want: new(structIgnoredUnexportedEmbedded),
7014 }, {
7015 name: jsontest.Name("Structs/WeirdNames"),
7016 inBuf: `{"":"empty",",":"comma","\"":"quote"}`,
7017 inVal: new(structWeirdNames),
7018 want: addr(structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"}),
7019 }, {
7020 name: jsontest.Name("Structs/NoCase/Exact"),
7021 inBuf: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
7022 inVal: new(structNoCase),
7023 want: addr(structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"}),
7024 }, {
7025 name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault"),
7026 inBuf: `{"aa_a":"aa_a"}`,
7027 inVal: new(structNoCase),
7028 want: addr(structNoCase{AaA: "aa_a"}),
7029 }, {
7030 name: jsontest.Name("Structs/NoCase/MatchCaseSensitiveDelimiter"),
7031 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
7032 inBuf: `{"aa_a":"aa_a"}`,
7033 inVal: new(structNoCase),
7034 want: addr(structNoCase{}),
7035 }, {
7036 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
7037 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
7038 inBuf: `{"aa_a":"aa_a"}`,
7039 inVal: new(structNoCase),
7040 want: addr(structNoCase{AA_A: "aa_a"}),
7041 }, {
7042 name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames"),
7043 opts: []Options{jsontext.AllowDuplicateNames(true)},
7044 inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`,
7045 inVal: new(structNoCase),
7046 want: addr(structNoCase{AaA: "aAa"}),
7047 }, {
7048 name: jsontest.Name("Structs/NoCase/Merge/RejectDuplicateNames"),
7049 opts: []Options{jsontext.AllowDuplicateNames(false)},
7050 inBuf: `{"AaA":"AaA","aaa":"aaa"}`,
7051 inVal: new(structNoCase),
7052 want: addr(structNoCase{AaA: "AaA"}),
7053 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AaA":"AaA",`)),
7054 }, {
7055 name: jsontest.Name("Structs/CaseSensitive"),
7056 inBuf: `{"BOOL": true, "STRING": "hello", "BYTES": "AQID", "INT": -64, "UINT": 64, "FLOAT": 3.14159}`,
7057 inVal: new(structScalars),
7058 want: addr(structScalars{}),
7059 }, {
7060 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactDifferent"),
7061 inBuf: `{"AAA":"AAA","AaA":"AaA","AAa":"AAa","Aaa":"Aaa"}`,
7062 inVal: addr(structNoCaseInlineTextValue{}),
7063 want: addr(structNoCaseInlineTextValue{AAA: "AAA", AaA: "AaA", AAa: "AAa", Aaa: "Aaa"}),
7064 }, {
7065 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactConflict"),
7066 inBuf: `{"AAA":"AAA","AAA":"AAA"}`,
7067 inVal: addr(structNoCaseInlineTextValue{}),
7068 want: addr(structNoCaseInlineTextValue{AAA: "AAA"}),
7069 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"AAA",`)),
7070 }, {
7071 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteExact"),
7072 inBuf: `{"AAA":"after"}`,
7073 inVal: addr(structNoCaseInlineTextValue{AAA: "before"}),
7074 want: addr(structNoCaseInlineTextValue{AAA: "after"}),
7075 }, {
7076 name: jsontest.Name("Structs/DuplicateName/NoCase/NoCaseConflict"),
7077 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7078 inVal: addr(structNoCaseInlineTextValue{}),
7079 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7080 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7081 }, {
7082 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteNoCase"),
7083 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7084 inVal: addr(structNoCaseInlineTextValue{}),
7085 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7086 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7087 }, {
7088 name: jsontest.Name("Structs/DuplicateName/Inline/Unknown"),
7089 inBuf: `{"unknown":""}`,
7090 inVal: addr(structNoCaseInlineTextValue{}),
7091 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7092 }, {
7093 name: jsontest.Name("Structs/DuplicateName/Inline/UnknownMerge"),
7094 inBuf: `{"unknown":""}`,
7095 inVal: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7096 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":"","unknown":""}`)}),
7097 }, {
7098 name: jsontest.Name("Structs/DuplicateName/Inline/NoCaseOkay"),
7099 inBuf: `{"b":"","B":""}`,
7100 inVal: addr(structNoCaseInlineTextValue{}),
7101 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":"","B":""}`)}),
7102 }, {
7103 name: jsontest.Name("Structs/DuplicateName/Inline/ExactConflict"),
7104 inBuf: `{"b":"","b":""}`,
7105 inVal: addr(structNoCaseInlineTextValue{}),
7106 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":""}`)}),
7107 wantErr: newDuplicateNameError("", []byte(`"b"`), len64(`{"b":"",`)),
7108 }, {
7109 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7110 inBuf: ``,
7111 inVal: addr(structAll{}),
7112 want: addr(structAll{}),
7113 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF},
7114 }, {
7115 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7116 inBuf: " \n\r\t",
7117 inVal: addr(structAll{}),
7118 want: addr(structAll{}),
7119 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF, ByteOffset: len64(" \n\r\t")},
7120 }, {
7121 name: jsontest.Name("Structs/Invalid/NestedErrUnexpectedEOF"),
7122 inBuf: `{"Pointer":`,
7123 inVal: addr(structAll{}),
7124 want: addr(structAll{Pointer: new(structAll)}),
7125 wantErr: &jsontext.SyntacticError{ByteOffset: len64(`{"Pointer":`), JSONPointer: "/Pointer", Err: io.ErrUnexpectedEOF},
7126 }, {
7127 name: jsontest.Name("Structs/Invalid/Conflicting"),
7128 inBuf: `{}`,
7129 inVal: addr(structConflicting{}),
7130 want: addr(structConflicting{}),
7131 wantErr: EU(errors.New(`Go struct fields A and B conflict over JSON object name "conflict"`)).withType('{', T[structConflicting]()),
7132 }, {
7133 name: jsontest.Name("Structs/Invalid/NoneExported"),
7134 inBuf: ` {}`,
7135 inVal: addr(structNoneExported{}),
7136 want: addr(structNoneExported{}),
7137 wantErr: EU(errNoExportedFields).withPos(` `, "").withType('{', T[structNoneExported]()),
7138 }, {
7139 name: jsontest.Name("Structs/Invalid/MalformedTag"),
7140 inBuf: `{}`,
7141 inVal: addr(structMalformedTag{}),
7142 want: addr(structMalformedTag{}),
7143 wantErr: EU(errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter or single quote)")).withType('{', T[structMalformedTag]()),
7144 }, {
7145 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
7146 inBuf: `{}`,
7147 inVal: addr(structUnexportedTag{}),
7148 want: addr(structUnexportedTag{}),
7149 wantErr: EU(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType('{', T[structUnexportedTag]()),
7150 }, {
7151 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
7152 inBuf: `{"NamedString":"hello"}`,
7153 inVal: addr(structExportedEmbedded{}),
7154 want: addr(structExportedEmbedded{}),
7155 wantErr: EU(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structExportedEmbedded]()),
7156 }, {
7157 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
7158 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
7159 inBuf: `{"NamedString":"hello"}`,
7160 inVal: addr(structExportedEmbedded{}),
7161 want: addr(structExportedEmbedded{"hello"}),
7162 }, {
7163 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
7164 inBuf: `{"name":"hello"}`,
7165 inVal: addr(structExportedEmbeddedTag{}),
7166 want: addr(structExportedEmbeddedTag{"hello"}),
7167 }, {
7168 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
7169 inBuf: `{}`,
7170 inVal: addr(structUnexportedEmbedded{}),
7171 want: addr(structUnexportedEmbedded{}),
7172 wantErr: EU(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structUnexportedEmbedded]()),
7173 }, {
7174 name: jsontest.Name("Structs/UnexportedEmbeddedStruct"),
7175 inBuf: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7176 inVal: addr(structUnexportedEmbeddedStruct{}),
7177 want: addr(structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7178 }, {
7179 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7180 inBuf: `{"Bool":true,"FizzBuzz":5}`,
7181 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7182 wantErr: EU(errNilField).withPos(`{"Bool":`, "/Bool").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7183 }, {
7184 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7185 inBuf: `{"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7186 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7187 wantErr: EU(errNilField).withPos(`{"FizzBuzz":5,"Addr":`, "/Addr").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7188 }, {
7189 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7190 inBuf: `{"Bool":true,"FizzBuzz":10,"Addr":"192.168.0.1"}`,
7191 inVal: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Int: 5}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{127, 0, 0, 1})}}),
7192 want: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true, Int: 5}, 10, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7193 }, {
7194 name: jsontest.Name("Structs/Unknown"),
7195 inBuf: `{
7196 "object0": {},
7197 "object1": {"key1": "value"},
7198 "object2": {"key1": "value", "key2": "value"},
7199 "objects": {"":{"":{"":{}}}},
7200 "array0": [],
7201 "array1": ["value1"],
7202 "array2": ["value1", "value2"],
7203 "array": [[[]]],
7204 "scalars": [null, false, true, "string", 12.345]
7205 }`,
7206 inVal: addr(struct{}{}),
7207 want: addr(struct{}{}),
7208 }, {
7209 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
7210 opts: []Options{invalidFormatOption},
7211 inBuf: `{"Field":"Value"}`,
7212 inVal: addr(struct{ Field string }{}),
7213 want: addr(struct{ Field string }{"Value"}),
7214 }, {
7215 name: jsontest.Name("Slices/Null"),
7216 inBuf: `null`,
7217 inVal: addr([]string{"something"}),
7218 want: addr([]string(nil)),
7219 }, {
7220 name: jsontest.Name("Slices/Bool"),
7221 inBuf: `[true,false]`,
7222 inVal: new([]bool),
7223 want: addr([]bool{true, false}),
7224 }, {
7225 name: jsontest.Name("Slices/String"),
7226 inBuf: `["hello","goodbye"]`,
7227 inVal: new([]string),
7228 want: addr([]string{"hello", "goodbye"}),
7229 }, {
7230 name: jsontest.Name("Slices/Bytes"),
7231 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7232 inVal: new([][]byte),
7233 want: addr([][]byte{[]byte("hello"), []byte("goodbye")}),
7234 }, {
7235 name: jsontest.Name("Slices/Int"),
7236 inBuf: `[-2,-1,0,1,2]`,
7237 inVal: new([]int),
7238 want: addr([]int{-2, -1, 0, 1, 2}),
7239 }, {
7240 name: jsontest.Name("Slices/Uint"),
7241 inBuf: `[0,1,2,3,4]`,
7242 inVal: new([]uint),
7243 want: addr([]uint{0, 1, 2, 3, 4}),
7244 }, {
7245 name: jsontest.Name("Slices/Float"),
7246 inBuf: `[3.14159,12.34]`,
7247 inVal: new([]float64),
7248 want: addr([]float64{3.14159, 12.34}),
7249 }, {
7250
7251
7252
7253 name: jsontest.Name("Slices/Merge"),
7254 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7255 inVal: addr([]map[string]string{{"k1": "v1"}, {"k2": "v2"}}[:1]),
7256 want: addr([]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7257 }, {
7258 name: jsontest.Name("Slices/Invalid/Channel"),
7259 inBuf: `["hello"]`,
7260 inVal: new([]chan string),
7261 want: addr([]chan string{nil}),
7262 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7263 }, {
7264 name: jsontest.Name("Slices/RecursiveSlice"),
7265 inBuf: `[[],[],[[]],[[],[]]]`,
7266 inVal: new(recursiveSlice),
7267 want: addr(recursiveSlice{
7268 {},
7269 {},
7270 {{}},
7271 {{}, {}},
7272 }),
7273 }, {
7274 name: jsontest.Name("Slices/Invalid/Bool"),
7275 inBuf: `true`,
7276 inVal: addr([]string{"nochange"}),
7277 want: addr([]string{"nochange"}),
7278 wantErr: EU(nil).withType('t', T[[]string]()),
7279 }, {
7280 name: jsontest.Name("Slices/Invalid/String"),
7281 inBuf: `""`,
7282 inVal: addr([]string{"nochange"}),
7283 want: addr([]string{"nochange"}),
7284 wantErr: EU(nil).withType('"', T[[]string]()),
7285 }, {
7286 name: jsontest.Name("Slices/Invalid/Number"),
7287 inBuf: `0`,
7288 inVal: addr([]string{"nochange"}),
7289 want: addr([]string{"nochange"}),
7290 wantErr: EU(nil).withType('0', T[[]string]()),
7291 }, {
7292 name: jsontest.Name("Slices/Invalid/Object"),
7293 inBuf: `{}`,
7294 inVal: addr([]string{"nochange"}),
7295 want: addr([]string{"nochange"}),
7296 wantErr: EU(nil).withType('{', T[[]string]()),
7297 }, {
7298 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
7299 opts: []Options{invalidFormatOption},
7300 inBuf: `[false,true]`,
7301 inVal: addr([]bool{true, false}),
7302 want: addr([]bool{false, true}),
7303 }, {
7304 name: jsontest.Name("Arrays/Null"),
7305 inBuf: `null`,
7306 inVal: addr([1]string{"something"}),
7307 want: addr([1]string{}),
7308 }, {
7309 name: jsontest.Name("Arrays/Bool"),
7310 inBuf: `[true,false]`,
7311 inVal: new([2]bool),
7312 want: addr([2]bool{true, false}),
7313 }, {
7314 name: jsontest.Name("Arrays/String"),
7315 inBuf: `["hello","goodbye"]`,
7316 inVal: new([2]string),
7317 want: addr([2]string{"hello", "goodbye"}),
7318 }, {
7319 name: jsontest.Name("Arrays/Bytes"),
7320 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7321 inVal: new([2][]byte),
7322 want: addr([2][]byte{[]byte("hello"), []byte("goodbye")}),
7323 }, {
7324 name: jsontest.Name("Arrays/Int"),
7325 inBuf: `[-2,-1,0,1,2]`,
7326 inVal: new([5]int),
7327 want: addr([5]int{-2, -1, 0, 1, 2}),
7328 }, {
7329 name: jsontest.Name("Arrays/Uint"),
7330 inBuf: `[0,1,2,3,4]`,
7331 inVal: new([5]uint),
7332 want: addr([5]uint{0, 1, 2, 3, 4}),
7333 }, {
7334 name: jsontest.Name("Arrays/Float"),
7335 inBuf: `[3.14159,12.34]`,
7336 inVal: new([2]float64),
7337 want: addr([2]float64{3.14159, 12.34}),
7338 }, {
7339
7340
7341 name: jsontest.Name("Arrays/Merge"),
7342 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7343 inVal: addr([2]map[string]string{{"k1": "v1"}, {"k2": "v2"}}),
7344 want: addr([2]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7345 }, {
7346 name: jsontest.Name("Arrays/Invalid/Channel"),
7347 inBuf: `["hello"]`,
7348 inVal: new([1]chan string),
7349 want: new([1]chan string),
7350 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7351 }, {
7352 name: jsontest.Name("Arrays/Invalid/Underflow"),
7353 inBuf: `{"F":[ ]}`,
7354 inVal: new(struct{ F [1]string }),
7355 want: addr(struct{ F [1]string }{}),
7356 wantErr: EU(errArrayUnderflow).withPos(`{"F":[ `, "/F").withType(']', T[[1]string]()),
7357 }, {
7358 name: jsontest.Name("Arrays/Invalid/Underflow/UnmarshalArrayFromAnyLength"),
7359 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7360 inBuf: `[-1,-2]`,
7361 inVal: addr([4]int{1, 2, 3, 4}),
7362 want: addr([4]int{-1, -2, 0, 0}),
7363 }, {
7364 name: jsontest.Name("Arrays/Invalid/Overflow"),
7365 inBuf: `["1","2"]`,
7366 inVal: new([1]string),
7367 want: addr([1]string{"1"}),
7368 wantErr: EU(errArrayOverflow).withPos(`["1","2"`, "").withType(']', T[[1]string]()),
7369 }, {
7370 name: jsontest.Name("Arrays/Invalid/Overflow/UnmarshalArrayFromAnyLength"),
7371 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7372 inBuf: `[-1,-2,-3,-4,-5,-6]`,
7373 inVal: addr([4]int{1, 2, 3, 4}),
7374 want: addr([4]int{-1, -2, -3, -4}),
7375 }, {
7376 name: jsontest.Name("Arrays/Invalid/Bool"),
7377 inBuf: `true`,
7378 inVal: addr([1]string{"nochange"}),
7379 want: addr([1]string{"nochange"}),
7380 wantErr: EU(nil).withType('t', T[[1]string]()),
7381 }, {
7382 name: jsontest.Name("Arrays/Invalid/String"),
7383 inBuf: `""`,
7384 inVal: addr([1]string{"nochange"}),
7385 want: addr([1]string{"nochange"}),
7386 wantErr: EU(nil).withType('"', T[[1]string]()),
7387 }, {
7388 name: jsontest.Name("Arrays/Invalid/Number"),
7389 inBuf: `0`,
7390 inVal: addr([1]string{"nochange"}),
7391 want: addr([1]string{"nochange"}),
7392 wantErr: EU(nil).withType('0', T[[1]string]()),
7393 }, {
7394 name: jsontest.Name("Arrays/Invalid/Object"),
7395 inBuf: `{}`,
7396 inVal: addr([1]string{"nochange"}),
7397 want: addr([1]string{"nochange"}),
7398 wantErr: EU(nil).withType('{', T[[1]string]()),
7399 }, {
7400 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
7401 opts: []Options{invalidFormatOption},
7402 inBuf: `[false,true]`,
7403 inVal: addr([2]bool{true, false}),
7404 want: addr([2]bool{false, true}),
7405 }, {
7406 name: jsontest.Name("Pointers/NullL0"),
7407 inBuf: `null`,
7408 inVal: new(*string),
7409 want: addr((*string)(nil)),
7410 }, {
7411 name: jsontest.Name("Pointers/NullL1"),
7412 inBuf: `null`,
7413 inVal: addr(new(*string)),
7414 want: addr((**string)(nil)),
7415 }, {
7416 name: jsontest.Name("Pointers/Bool"),
7417 inBuf: `true`,
7418 inVal: addr(new(bool)),
7419 want: addr(addr(true)),
7420 }, {
7421 name: jsontest.Name("Pointers/String"),
7422 inBuf: `"hello"`,
7423 inVal: addr(new(string)),
7424 want: addr(addr("hello")),
7425 }, {
7426 name: jsontest.Name("Pointers/Bytes"),
7427 inBuf: `"aGVsbG8="`,
7428 inVal: addr(new([]byte)),
7429 want: addr(addr([]byte("hello"))),
7430 }, {
7431 name: jsontest.Name("Pointers/Int"),
7432 inBuf: `-123`,
7433 inVal: addr(new(int)),
7434 want: addr(addr(int(-123))),
7435 }, {
7436 name: jsontest.Name("Pointers/Uint"),
7437 inBuf: `123`,
7438 inVal: addr(new(int)),
7439 want: addr(addr(int(123))),
7440 }, {
7441 name: jsontest.Name("Pointers/Float"),
7442 inBuf: `123.456`,
7443 inVal: addr(new(float64)),
7444 want: addr(addr(float64(123.456))),
7445 }, {
7446 name: jsontest.Name("Pointers/Allocate"),
7447 inBuf: `"hello"`,
7448 inVal: addr((*string)(nil)),
7449 want: addr(addr("hello")),
7450 }, {
7451 name: jsontest.Name("Points/IgnoreInvalidFormat"),
7452 opts: []Options{invalidFormatOption},
7453 inBuf: `true`,
7454 inVal: addr(new(bool)),
7455 want: addr(addr(true)),
7456 }, {
7457 name: jsontest.Name("Interfaces/Empty/Null"),
7458 inBuf: `null`,
7459 inVal: new(any),
7460 want: new(any),
7461 }, {
7462 name: jsontest.Name("Interfaces/NonEmpty/Null"),
7463 inBuf: `null`,
7464 inVal: new(io.Reader),
7465 want: new(io.Reader),
7466 }, {
7467 name: jsontest.Name("Interfaces/NonEmpty/Invalid"),
7468 inBuf: `"hello"`,
7469 inVal: new(io.Reader),
7470 want: new(io.Reader),
7471 wantErr: EU(internal.ErrNilInterface).withType(0, T[io.Reader]()),
7472 }, {
7473 name: jsontest.Name("Interfaces/Empty/False"),
7474 inBuf: `false`,
7475 inVal: new(any),
7476 want: func() any {
7477 var vi any = false
7478 return &vi
7479 }(),
7480 }, {
7481 name: jsontest.Name("Interfaces/Empty/True"),
7482 inBuf: `true`,
7483 inVal: new(any),
7484 want: func() any {
7485 var vi any = true
7486 return &vi
7487 }(),
7488 }, {
7489 name: jsontest.Name("Interfaces/Empty/String"),
7490 inBuf: `"string"`,
7491 inVal: new(any),
7492 want: func() any {
7493 var vi any = "string"
7494 return &vi
7495 }(),
7496 }, {
7497 name: jsontest.Name("Interfaces/Empty/Number"),
7498 inBuf: `3.14159`,
7499 inVal: new(any),
7500 want: func() any {
7501 var vi any = 3.14159
7502 return &vi
7503 }(),
7504 }, {
7505 name: jsontest.Name("Interfaces/Empty/Object"),
7506 inBuf: `{"k":"v"}`,
7507 inVal: new(any),
7508 want: func() any {
7509 var vi any = map[string]any{"k": "v"}
7510 return &vi
7511 }(),
7512 }, {
7513 name: jsontest.Name("Interfaces/Empty/Array"),
7514 inBuf: `["v"]`,
7515 inVal: new(any),
7516 want: func() any {
7517 var vi any = []any{"v"}
7518 return &vi
7519 }(),
7520 }, {
7521 name: jsontest.Name("Interfaces/NamedAny/String"),
7522 inBuf: `"string"`,
7523 inVal: new(namedAny),
7524 want: func() namedAny {
7525 var vi namedAny = "string"
7526 return &vi
7527 }(),
7528 }, {
7529 name: jsontest.Name("Interfaces/Invalid"),
7530 inBuf: `]`,
7531 inVal: new(any),
7532 want: new(any),
7533 wantErr: newInvalidCharacterError("]", "at start of value", 0, ""),
7534 }, {
7535
7536
7537
7538
7539 name: jsontest.Name("Interfaces/Merge/Map"),
7540 inBuf: `{"k2":"v2"}`,
7541 inVal: func() any {
7542 var vi any = map[string]string{"k1": "v1"}
7543 return &vi
7544 }(),
7545 want: func() any {
7546 var vi any = map[string]string{"k1": "v1", "k2": "v2"}
7547 return &vi
7548 }(),
7549 }, {
7550 name: jsontest.Name("Interfaces/Merge/Struct"),
7551 inBuf: `{"Array":["goodbye"]}`,
7552 inVal: func() any {
7553 var vi any = structAll{String: "hello"}
7554 return &vi
7555 }(),
7556 want: func() any {
7557 var vi any = structAll{String: "hello", Array: [1]string{"goodbye"}}
7558 return &vi
7559 }(),
7560 }, {
7561 name: jsontest.Name("Interfaces/Merge/NamedInt"),
7562 inBuf: `64`,
7563 inVal: func() any {
7564 var vi any = namedInt64(-64)
7565 return &vi
7566 }(),
7567 want: func() any {
7568 var vi any = namedInt64(+64)
7569 return &vi
7570 }(),
7571 }, {
7572 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
7573 opts: []Options{invalidFormatOption},
7574 inBuf: `true`,
7575 inVal: new(any),
7576 want: func() any {
7577 var vi any = true
7578 return &vi
7579 }(),
7580 }, {
7581 name: jsontest.Name("Interfaces/Any"),
7582 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7583 inVal: new(struct{ X any }),
7584 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7585 }, {
7586 name: jsontest.Name("Interfaces/Any/Named"),
7587 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7588 inVal: new(struct{ X namedAny }),
7589 want: addr(struct{ X namedAny }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7590 }, {
7591 name: jsontest.Name("Interfaces/Any/Stringified"),
7592 opts: []Options{StringifyNumbers(true)},
7593 inBuf: `{"X":"0"}`,
7594 inVal: new(struct{ X any }),
7595 want: addr(struct{ X any }{"0"}),
7596 }, {
7597 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Any"),
7598 opts: []Options{
7599 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
7600 *v = "called"
7601 return nil
7602 })),
7603 },
7604 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7605 inVal: new(struct{ X any }),
7606 want: addr(struct{ X any }{"called"}),
7607 }, {
7608 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Bool"),
7609 opts: []Options{
7610 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *bool) error {
7611 *v = string(b) != "true"
7612 return nil
7613 })),
7614 },
7615 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7616 inVal: new(struct{ X any }),
7617 want: addr(struct{ X any }{[]any{nil, true, false, "", 0.0, map[string]any{}, []any{}}}),
7618 }, {
7619 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/String"),
7620 opts: []Options{
7621 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7622 *v = "called"
7623 return nil
7624 })),
7625 },
7626 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7627 inVal: new(struct{ X any }),
7628 want: addr(struct{ X any }{[]any{nil, false, true, "called", 0.0, map[string]any{}, []any{}}}),
7629 }, {
7630 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Float64"),
7631 opts: []Options{
7632 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *float64) error {
7633 *v = 3.14159
7634 return nil
7635 })),
7636 },
7637 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7638 inVal: new(struct{ X any }),
7639 want: addr(struct{ X any }{[]any{nil, false, true, "", 3.14159, map[string]any{}, []any{}}}),
7640 }, {
7641 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/MapStringAny"),
7642 opts: []Options{
7643 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *map[string]any) error {
7644 *v = map[string]any{"called": nil}
7645 return nil
7646 })),
7647 },
7648 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7649 inVal: new(struct{ X any }),
7650 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{"called": nil}, []any{}}}),
7651 }, {
7652 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/SliceAny"),
7653 opts: []Options{
7654 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *[]any) error {
7655 *v = []any{"called"}
7656 return nil
7657 })),
7658 },
7659 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7660 inVal: new(struct{ X any }),
7661 want: addr(struct{ X any }{[]any{"called"}}),
7662 }, {
7663 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
7664 inBuf: `{"X":{"fizz":"buzz"}}`,
7665 inVal: new(struct{ X any }),
7666 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7667 }, {
7668 name: jsontest.Name("Interfaces/Any/Maps/RejectDuplicateNames"),
7669 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7670 inVal: new(struct{ X any }),
7671 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7672 wantErr: newDuplicateNameError("/X", []byte(`"fizz"`), len64(`{"X":{"fizz":"buzz",`)),
7673 }, {
7674 name: jsontest.Name("Interfaces/Any/Maps/AllowDuplicateNames"),
7675 opts: []Options{jsontext.AllowDuplicateNames(true)},
7676 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7677 inVal: new(struct{ X any }),
7678 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7679 wantErr: EU(nil).withPos(`{"X":{"fizz":"buzz","fizz":`, "/X/fizz").withType('t', T[string]()),
7680 }, {
7681 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
7682 inBuf: `{"X":["fizz","buzz"]}`,
7683 inVal: new(struct{ X any }),
7684 want: addr(struct{ X any }{[]any{"fizz", "buzz"}}),
7685 }, {
7686 name: jsontest.Name("Methods/NilPointer/Null"),
7687 inBuf: `{"X":null}`,
7688 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7689 want: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7690 }, {
7691 name: jsontest.Name("Methods/NilPointer/Value"),
7692 inBuf: `{"X":"value"}`,
7693 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7694 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7695 }, {
7696 name: jsontest.Name("Methods/NilInterface/Null"),
7697 inBuf: `{"X":null}`,
7698 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7699 want: addr(struct{ X MarshalerTo }{X: nil}),
7700 }, {
7701 name: jsontest.Name("Methods/NilInterface/Value"),
7702 inBuf: `{"X":"value"}`,
7703 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7704 want: addr(struct{ X MarshalerTo }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7705 }, {
7706 name: jsontest.Name("Methods/AllMethods"),
7707 inBuf: `{"X":"hello"}`,
7708 inVal: new(struct{ X *allMethods }),
7709 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}),
7710 }, {
7711 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
7712 inBuf: `{"X":"hello"}`,
7713 inVal: new(struct{ X *allMethodsExceptJSONv2 }),
7714 want: addr(struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7715 }, {
7716 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
7717 inBuf: `{"X":"hello"}`,
7718 inVal: new(struct{ X *allMethodsExceptJSONv1 }),
7719 want: addr(struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7720 }, {
7721 name: jsontest.Name("Methods/AllMethodsExceptText"),
7722 inBuf: `{"X":"hello"}`,
7723 inVal: new(struct{ X *allMethodsExceptText }),
7724 want: addr(struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7725 }, {
7726 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
7727 inBuf: `{"X":"hello"}`,
7728 inVal: new(struct{ X *onlyMethodJSONv2 }),
7729 want: addr(struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7730 }, {
7731 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
7732 inBuf: `{"X":"hello"}`,
7733 inVal: new(struct{ X *onlyMethodJSONv1 }),
7734 want: addr(struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7735 }, {
7736 name: jsontest.Name("Methods/OnlyMethodText"),
7737 inBuf: `{"X":"hello"}`,
7738 inVal: new(struct{ X *onlyMethodText }),
7739 want: addr(struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "UnmarshalText", value: []byte(`hello`)}}}),
7740 }, {
7741 name: jsontest.Name("Methods/Text/Null"),
7742 inBuf: `{"X":null}`,
7743 inVal: addr(struct{ X unmarshalTextFunc }{unmarshalTextFunc(func(b []byte) error {
7744 return errMustNotCall
7745 })}),
7746 want: addr(struct{ X unmarshalTextFunc }{nil}),
7747 }, {
7748 name: jsontest.Name("Methods/IP"),
7749 inBuf: `"192.168.0.100"`,
7750 inVal: new(net.IP),
7751 want: addr(net.IPv4(192, 168, 0, 100)),
7752 }, {
7753
7754 name: jsontest.Name("Methods/Anonymous"),
7755 inBuf: `{"X":"hello"}`,
7756 inVal: new(struct{ X struct{ allMethods } }),
7757 want: addr(struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7758 }, {
7759
7760 name: jsontest.Name("Methods/Addressable"),
7761 inBuf: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
7762 inVal: addr(struct {
7763 V allMethods
7764 M map[string]allMethods
7765 I any
7766 }{
7767 I: allMethods{},
7768 }),
7769 want: addr(struct {
7770 V allMethods
7771 M map[string]allMethods
7772 I any
7773 }{
7774 V: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7775 M: map[string]allMethods{"K": {method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}},
7776 I: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7777 }),
7778 }, {
7779
7780 name: jsontest.Name("Methods/MapKey/JSONv2"),
7781 inBuf: `{"k1":"v1b","k2":"v2"}`,
7782 inVal: addr(map[structMethodJSONv2]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7783 want: addr(map[structMethodJSONv2]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7784 }, {
7785
7786 name: jsontest.Name("Methods/MapKey/JSONv1"),
7787 inBuf: `{"k1":"v1b","k2":"v2"}`,
7788 inVal: addr(map[structMethodJSONv1]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7789 want: addr(map[structMethodJSONv1]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7790 }, {
7791 name: jsontest.Name("Methods/MapKey/Text"),
7792 inBuf: `{"k1":"v1b","k2":"v2"}`,
7793 inVal: addr(map[structMethodText]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7794 want: addr(map[structMethodText]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7795 }, {
7796 name: jsontest.Name("Methods/JSONv2/ErrUnsupported"),
7797 inBuf: `{"fizz":123}`,
7798 inVal: addr(unsupportedMethodJSONv2{}),
7799 want: addr(unsupportedMethodJSONv2{"called": 1, "fizz": 123}),
7800 }, {
7801 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
7802 inBuf: `{}`,
7803 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7804 return errSomeError
7805 })),
7806 wantErr: EU(errSomeError).withType(0, T[unmarshalJSONv2Func]()),
7807 }, {
7808 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
7809 inBuf: `{}`,
7810 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7811 return nil
7812 })),
7813 wantErr: EU(errNonSingularValue).withType(0, T[unmarshalJSONv2Func]()),
7814 }, {
7815 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
7816 inBuf: `{}{}`,
7817 inVal: addr(unmarshalJSONv2Func(func(dec *jsontext.Decoder) error {
7818 dec.ReadValue()
7819 dec.ReadValue()
7820 return nil
7821 })),
7822 wantErr: EU(errNonSingularValue).withPos(`{}`, "").withType(0, T[unmarshalJSONv2Func]()),
7823 }, {
7824 name: jsontest.Name("Methods/Invalid/JSONv2/ErrUnsupported"),
7825 inBuf: `{}`,
7826 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7827 return errors.ErrUnsupported
7828 })),
7829 wantErr: EU(nil).withType(0, T[unmarshalJSONv2Func]()),
7830 }, {
7831 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
7832 inBuf: `{}`,
7833 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7834 return errSomeError
7835 })),
7836 wantErr: EU(errSomeError).withType('{', T[unmarshalJSONv1Func]()),
7837 }, {
7838 name: jsontest.Name("Methods/Invalid/JSONv1/ErrUnsupported"),
7839 inBuf: `{}`,
7840 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7841 return errors.ErrUnsupported
7842 })),
7843 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "UnmarshalJSON method")).withType('{', T[unmarshalJSONv1Func]()),
7844 }, {
7845 name: jsontest.Name("Methods/Invalid/Text/Error"),
7846 inBuf: `"value"`,
7847 inVal: addr(unmarshalTextFunc(func([]byte) error {
7848 return errSomeError
7849 })),
7850 wantErr: EU(errSomeError).withType('"', T[unmarshalTextFunc]()),
7851 }, {
7852 name: jsontest.Name("Methods/Invalid/Text/Syntax"),
7853 inBuf: `{}`,
7854 inVal: addr(unmarshalTextFunc(func([]byte) error {
7855 panic("should not be called")
7856 })),
7857 wantErr: EU(errNonStringValue).withType('{', T[unmarshalTextFunc]()),
7858 }, {
7859 name: jsontest.Name("Methods/Invalid/Text/ErrUnsupported"),
7860 inBuf: `"value"`,
7861 inVal: addr(unmarshalTextFunc(func([]byte) error {
7862 return errors.ErrUnsupported
7863 })),
7864 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "UnmarshalText method")).withType('"', T[unmarshalTextFunc]()),
7865 }, {
7866 name: jsontest.Name("Functions/String/V1"),
7867 opts: []Options{
7868 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7869 if string(b) != `""` {
7870 return fmt.Errorf("got %s, want %s", b, `""`)
7871 }
7872 *v = "called"
7873 return nil
7874 })),
7875 },
7876 inBuf: `""`,
7877 inVal: addr(""),
7878 want: addr("called"),
7879 }, {
7880 name: jsontest.Name("Functions/String/Empty"),
7881 opts: []Options{WithUnmarshalers(nil)},
7882 inBuf: `"hello"`,
7883 inVal: addr(""),
7884 want: addr("hello"),
7885 }, {
7886 name: jsontest.Name("Functions/NamedString/V1/NoMatch"),
7887 opts: []Options{
7888 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7889 panic("should not be called")
7890 })),
7891 },
7892 inBuf: `""`,
7893 inVal: addr(""),
7894 want: addr(""),
7895 }, {
7896 name: jsontest.Name("Functions/NamedString/V1/Match"),
7897 opts: []Options{
7898 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7899 if string(b) != `""` {
7900 return fmt.Errorf("got %s, want %s", b, `""`)
7901 }
7902 *v = "called"
7903 return nil
7904 })),
7905 },
7906 inBuf: `""`,
7907 inVal: addr(namedString("")),
7908 want: addr(namedString("called")),
7909 }, {
7910 name: jsontest.Name("Functions/String/V2"),
7911 opts: []Options{
7912 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
7913 switch b, err := dec.ReadValue(); {
7914 case err != nil:
7915 return err
7916 case string(b) != `""`:
7917 return fmt.Errorf("got %s, want %s", b, `""`)
7918 }
7919 *v = "called"
7920 return nil
7921 })),
7922 },
7923 inBuf: `""`,
7924 inVal: addr(""),
7925 want: addr("called"),
7926 }, {
7927 name: jsontest.Name("Functions/NamedString/V2/NoMatch"),
7928 opts: []Options{
7929 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7930 panic("should not be called")
7931 })),
7932 },
7933 inBuf: `""`,
7934 inVal: addr(""),
7935 want: addr(""),
7936 }, {
7937 name: jsontest.Name("Functions/NamedString/V2/Match"),
7938 opts: []Options{
7939 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7940 switch t, err := dec.ReadToken(); {
7941 case err != nil:
7942 return err
7943 case t.String() != ``:
7944 return fmt.Errorf("got %q, want %q", t, ``)
7945 }
7946 *v = "called"
7947 return nil
7948 })),
7949 },
7950 inBuf: `""`,
7951 inVal: addr(namedString("")),
7952 want: addr(namedString("called")),
7953 }, {
7954 name: jsontest.Name("Functions/String/Empty1/NoMatch"),
7955 opts: []Options{
7956 WithUnmarshalers(new(Unmarshalers)),
7957 },
7958 inBuf: `""`,
7959 inVal: addr(""),
7960 want: addr(""),
7961 }, {
7962 name: jsontest.Name("Functions/String/Empty2/NoMatch"),
7963 opts: []Options{
7964 WithUnmarshalers(JoinUnmarshalers()),
7965 },
7966 inBuf: `""`,
7967 inVal: addr(""),
7968 want: addr(""),
7969 }, {
7970 name: jsontest.Name("Functions/String/V1/DirectError"),
7971 opts: []Options{
7972 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
7973 return errSomeError
7974 })),
7975 },
7976 inBuf: `""`,
7977 inVal: addr(""),
7978 want: addr(""),
7979 wantErr: EU(errSomeError).withType('"', reflect.PointerTo(stringType)),
7980 }, {
7981 name: jsontest.Name("Functions/String/V1/SkipError"),
7982 opts: []Options{
7983 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
7984 return errors.ErrUnsupported
7985 })),
7986 },
7987 inBuf: `""`,
7988 inVal: addr(""),
7989 want: addr(""),
7990 wantErr: EU(wrapErrUnsupported(errors.ErrUnsupported, "unmarshal function of type func([]byte, T) error")).withType('"', reflect.PointerTo(stringType)),
7991 }, {
7992 name: jsontest.Name("Functions/String/V2/DirectError"),
7993 opts: []Options{
7994 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
7995 return errSomeError
7996 })),
7997 },
7998 inBuf: `""`,
7999 inVal: addr(""),
8000 want: addr(""),
8001 wantErr: EU(errSomeError).withType(0, reflect.PointerTo(stringType)),
8002 }, {
8003 name: jsontest.Name("Functions/String/V2/TooFew"),
8004 opts: []Options{
8005 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8006 return nil
8007 })),
8008 },
8009 inBuf: `""`,
8010 inVal: addr(""),
8011 want: addr(""),
8012 wantErr: EU(errNonSingularValue).withType(0, reflect.PointerTo(stringType)),
8013 }, {
8014 name: jsontest.Name("Functions/String/V2/TooMany"),
8015 opts: []Options{
8016 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8017 if _, err := dec.ReadValue(); err != nil {
8018 return err
8019 }
8020 if _, err := dec.ReadValue(); err != nil {
8021 return err
8022 }
8023 return nil
8024 })),
8025 },
8026 inBuf: `{"X":["",""]}`,
8027 inVal: addr(struct{ X []string }{}),
8028 want: addr(struct{ X []string }{[]string{""}}),
8029 wantErr: EU(errNonSingularValue).withPos(`{"X":["",`, "/X").withType(0, reflect.PointerTo(stringType)),
8030 }, {
8031 name: jsontest.Name("Functions/String/V2/Skipped"),
8032 opts: []Options{
8033 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8034 return errors.ErrUnsupported
8035 })),
8036 },
8037 inBuf: `""`,
8038 inVal: addr(""),
8039 want: addr(""),
8040 }, {
8041 name: jsontest.Name("Functions/String/V2/ProcessBeforeSkip"),
8042 opts: []Options{
8043 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8044 if _, err := dec.ReadValue(); err != nil {
8045 return err
8046 }
8047 return errors.ErrUnsupported
8048 })),
8049 },
8050 inBuf: `""`,
8051 inVal: addr(""),
8052 want: addr(""),
8053 wantErr: EU(errUnsupportedMutation).withType(0, reflect.PointerTo(stringType)),
8054 }, {
8055 name: jsontest.Name("Functions/String/V2/WrappedUnsupported"),
8056 opts: []Options{
8057 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8058 return fmt.Errorf("wrap: %w", errors.ErrUnsupported)
8059 })),
8060 },
8061 inBuf: `""`,
8062 inVal: addr(""),
8063 want: addr(""),
8064 }, {
8065 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
8066 opts: []Options{
8067 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8068 if string(b) != `"hello"` {
8069 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8070 }
8071 *v = "called"
8072 return nil
8073 })),
8074 },
8075 inBuf: `{"hello":"world"}`,
8076 inVal: addr(map[nocaseString]string{}),
8077 want: addr(map[nocaseString]string{"called": "world"}),
8078 }, {
8079 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
8080 opts: []Options{
8081 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8082 if string(b) != `"hello"` {
8083 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8084 }
8085 *v.(*nocaseString) = "called"
8086 return nil
8087 })),
8088 },
8089 inBuf: `{"hello":"world"}`,
8090 inVal: addr(map[nocaseString]string{}),
8091 want: addr(map[nocaseString]string{"called": "world"}),
8092 }, {
8093 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
8094 opts: []Options{
8095 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8096 switch t, err := dec.ReadToken(); {
8097 case err != nil:
8098 return err
8099 case t.String() != "hello":
8100 return fmt.Errorf("got %q, want %q", t, "hello")
8101 }
8102 *v = "called"
8103 return nil
8104 })),
8105 },
8106 inBuf: `{"hello":"world"}`,
8107 inVal: addr(map[nocaseString]string{}),
8108 want: addr(map[nocaseString]string{"called": "world"}),
8109 }, {
8110 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
8111 opts: []Options{
8112 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8113 switch b, err := dec.ReadValue(); {
8114 case err != nil:
8115 return err
8116 case string(b) != `"hello"`:
8117 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8118 }
8119 *v.(*nocaseString) = "called"
8120 return nil
8121 })),
8122 },
8123 inBuf: `{"hello":"world"}`,
8124 inVal: addr(map[nocaseString]string{}),
8125 want: addr(map[nocaseString]string{"called": "world"}),
8126 }, {
8127 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
8128 opts: []Options{
8129 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8130 if _, err := dec.ReadValue(); err != nil {
8131 return err
8132 }
8133 xd := export.Decoder(dec)
8134 *v = fmt.Sprintf("%d-%d", len(xd.Tokens.Stack), xd.Tokens.Last.Length())
8135 return nil
8136 })),
8137 },
8138 inBuf: `{"name":"value","name":"value"}`,
8139 inVal: addr(map[string]string{}),
8140 want: addr(map[string]string{"1-1": "1-2"}),
8141 wantErr: newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"value",`)),
8142 }, {
8143 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
8144 opts: []Options{
8145 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8146 if string(b) != `"world"` {
8147 return fmt.Errorf("got %s, want %s", b, `"world"`)
8148 }
8149 *v = "called"
8150 return nil
8151 })),
8152 },
8153 inBuf: `{"hello":"world"}`,
8154 inVal: addr(map[string]nocaseString{}),
8155 want: addr(map[string]nocaseString{"hello": "called"}),
8156 }, {
8157 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
8158 opts: []Options{
8159 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8160 if string(b) != `"world"` {
8161 return fmt.Errorf("got %s, want %s", b, `"world"`)
8162 }
8163 *v.(*nocaseString) = "called"
8164 return nil
8165 })),
8166 },
8167 inBuf: `{"hello":"world"}`,
8168 inVal: addr(map[string]nocaseString{}),
8169 want: addr(map[string]nocaseString{"hello": "called"}),
8170 }, {
8171 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
8172 opts: []Options{
8173 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8174 switch t, err := dec.ReadToken(); {
8175 case err != nil:
8176 return err
8177 case t.String() != "world":
8178 return fmt.Errorf("got %q, want %q", t, "world")
8179 }
8180 *v = "called"
8181 return nil
8182 })),
8183 },
8184 inBuf: `{"hello":"world"}`,
8185 inVal: addr(map[string]nocaseString{}),
8186 want: addr(map[string]nocaseString{"hello": "called"}),
8187 }, {
8188 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
8189 opts: []Options{
8190 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8191 switch b, err := dec.ReadValue(); {
8192 case err != nil:
8193 return err
8194 case string(b) != `"world"`:
8195 return fmt.Errorf("got %s, want %s", b, `"world"`)
8196 }
8197 *v.(*nocaseString) = "called"
8198 return nil
8199 })),
8200 },
8201 inBuf: `{"hello":"world"}`,
8202 inVal: addr(map[string]nocaseString{}),
8203 want: addr(map[string]nocaseString{"hello": "called"}),
8204 }, {
8205 name: jsontest.Name("Funtions/Struct/Fields"),
8206 opts: []Options{
8207 WithUnmarshalers(JoinUnmarshalers(
8208 UnmarshalFunc(func(b []byte, v *bool) error {
8209 if string(b) != `"called1"` {
8210 return fmt.Errorf("got %s, want %s", b, `"called1"`)
8211 }
8212 *v = true
8213 return nil
8214 }),
8215 UnmarshalFunc(func(b []byte, v *string) error {
8216 if string(b) != `"called2"` {
8217 return fmt.Errorf("got %s, want %s", b, `"called2"`)
8218 }
8219 *v = "called2"
8220 return nil
8221 }),
8222 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[]byte) error {
8223 switch t, err := dec.ReadToken(); {
8224 case err != nil:
8225 return err
8226 case t.String() != "called3":
8227 return fmt.Errorf("got %q, want %q", t, "called3")
8228 }
8229 *v = []byte("called3")
8230 return nil
8231 }),
8232 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *int64) error {
8233 switch b, err := dec.ReadValue(); {
8234 case err != nil:
8235 return err
8236 case string(b) != `"called4"`:
8237 return fmt.Errorf("got %s, want %s", b, `"called4"`)
8238 }
8239 *v = 123
8240 return nil
8241 }),
8242 )),
8243 },
8244 inBuf: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":456,"Float":789}`,
8245 inVal: addr(structScalars{}),
8246 want: addr(structScalars{Bool: true, String: "called2", Bytes: []byte("called3"), Int: 123, Uint: 456, Float: 789}),
8247 }, {
8248 name: jsontest.Name("Functions/Struct/Inlined"),
8249 opts: []Options{
8250 WithUnmarshalers(JoinUnmarshalers(
8251 UnmarshalFunc(func([]byte, *structInlinedL1) error {
8252 panic("should not be called")
8253 }),
8254 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *StructEmbed2) error {
8255 panic("should not be called")
8256 }),
8257 )),
8258 },
8259 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
8260 inVal: new(structInlined),
8261 want: addr(structInlined{
8262 X: structInlinedL1{
8263 X: &structInlinedL2{A: "A1", B: "B1" },
8264 StructEmbed1: StructEmbed1{ D: "D2" },
8265 },
8266 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
8267 }),
8268 }, {
8269 name: jsontest.Name("Functions/Slice/Elem"),
8270 opts: []Options{
8271 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8272 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8273 return nil
8274 })),
8275 },
8276 inBuf: `["hello","World"]`,
8277 inVal: addr([]string{}),
8278 want: addr([]string{"HELLO", "WORLD"}),
8279 }, {
8280 name: jsontest.Name("Functions/Array/Elem"),
8281 opts: []Options{
8282 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8283 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8284 return nil
8285 })),
8286 },
8287 inBuf: `["hello","World"]`,
8288 inVal: addr([2]string{}),
8289 want: addr([2]string{"HELLO", "WORLD"}),
8290 }, {
8291 name: jsontest.Name("Functions/Pointer/Nil"),
8292 opts: []Options{
8293 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8294 t, err := dec.ReadToken()
8295 *v = strings.ToUpper(t.String())
8296 return err
8297 })),
8298 },
8299 inBuf: `{"X":"hello"}`,
8300 inVal: addr(struct{ X *string }{nil}),
8301 want: addr(struct{ X *string }{addr("HELLO")}),
8302 }, {
8303 name: jsontest.Name("Functions/Pointer/NonNil"),
8304 opts: []Options{
8305 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8306 t, err := dec.ReadToken()
8307 *v = strings.ToUpper(t.String())
8308 return err
8309 })),
8310 },
8311 inBuf: `{"X":"hello"}`,
8312 inVal: addr(struct{ X *string }{addr("")}),
8313 want: addr(struct{ X *string }{addr("HELLO")}),
8314 }, {
8315 name: jsontest.Name("Functions/Interface/Nil"),
8316 opts: []Options{
8317 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v fmt.Stringer) error {
8318 panic("should not be called")
8319 })),
8320 },
8321 inBuf: `{"X":"hello"}`,
8322 inVal: addr(struct{ X fmt.Stringer }{nil}),
8323 want: addr(struct{ X fmt.Stringer }{nil}),
8324 wantErr: EU(internal.ErrNilInterface).withPos(`{"X":`, "/X").withType(0, T[fmt.Stringer]()),
8325 }, {
8326 name: jsontest.Name("Functions/Interface/NetIP"),
8327 opts: []Options{
8328 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8329 *v = net.IP{}
8330 return errors.ErrUnsupported
8331 })),
8332 },
8333 inBuf: `{"X":"1.1.1.1"}`,
8334 inVal: addr(struct{ X fmt.Stringer }{nil}),
8335 want: addr(struct{ X fmt.Stringer }{net.IPv4(1, 1, 1, 1)}),
8336 }, {
8337 name: jsontest.Name("Functions/Interface/NewPointerNetIP"),
8338 opts: []Options{
8339 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8340 *v = new(net.IP)
8341 return errors.ErrUnsupported
8342 })),
8343 },
8344 inBuf: `{"X":"1.1.1.1"}`,
8345 inVal: addr(struct{ X fmt.Stringer }{nil}),
8346 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}),
8347 }, {
8348 name: jsontest.Name("Functions/Interface/NilPointerNetIP"),
8349 opts: []Options{
8350 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8351 *v = (*net.IP)(nil)
8352 return errors.ErrUnsupported
8353 })),
8354 },
8355 inBuf: `{"X":"1.1.1.1"}`,
8356 inVal: addr(struct{ X fmt.Stringer }{nil}),
8357 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}),
8358 }, {
8359 name: jsontest.Name("Functions/Interface/NilPointerNetIP/Override"),
8360 opts: []Options{
8361 WithUnmarshalers(JoinUnmarshalers(
8362 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8363 *v = (*net.IP)(nil)
8364 return errors.ErrUnsupported
8365 }),
8366 UnmarshalFunc(func(b []byte, v *net.IP) error {
8367 b = bytes.ReplaceAll(b, []byte(`1`), []byte(`8`))
8368 return v.UnmarshalText(bytes.Trim(b, `"`))
8369 }),
8370 )),
8371 },
8372 inBuf: `{"X":"1.1.1.1"}`,
8373 inVal: addr(struct{ X fmt.Stringer }{nil}),
8374 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(8, 8, 8, 8))}),
8375 }, {
8376 name: jsontest.Name("Functions/Interface/Any"),
8377 inBuf: `[null,{},{},{},{},{},{},{},{},{},{},{},{},"LAST"]`,
8378 inVal: addr([...]any{
8379 nil,
8380 valueStringer{},
8381 (*valueStringer)(nil),
8382 addr(valueStringer{}),
8383 (**valueStringer)(nil),
8384 addr((*valueStringer)(nil)),
8385 addr(addr(valueStringer{})),
8386 pointerStringer{},
8387 (*pointerStringer)(nil),
8388 addr(pointerStringer{}),
8389 (**pointerStringer)(nil),
8390 addr((*pointerStringer)(nil)),
8391 addr(addr(pointerStringer{})),
8392 "LAST",
8393 }),
8394 opts: []Options{
8395 WithUnmarshalers(func() *Unmarshalers {
8396 type P struct {
8397 D int
8398 N int64
8399 }
8400 type PV struct {
8401 P P
8402 V any
8403 }
8404
8405 var lastChecks []func() error
8406 checkLast := func() error {
8407 for _, fn := range lastChecks {
8408 if err := fn(); err != nil {
8409 return err
8410 }
8411 }
8412 return errors.ErrUnsupported
8413 }
8414 makeValueChecker := func(name string, want []PV) func(d *jsontext.Decoder, v any) error {
8415 checkNext := func(d *jsontext.Decoder, v any) error {
8416 xd := export.Decoder(d)
8417 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8418 rv := reflect.ValueOf(v)
8419 pv := PV{p, v}
8420 switch {
8421 case len(want) == 0:
8422 return fmt.Errorf("%s: %v: got more values than expected", name, p)
8423 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
8424 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
8425 case !reflect.DeepEqual(pv, want[0]):
8426 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
8427 default:
8428 want = want[1:]
8429 return errors.ErrUnsupported
8430 }
8431 }
8432 lastChecks = append(lastChecks, func() error {
8433 if len(want) > 0 {
8434 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8435 }
8436 return nil
8437 })
8438 return checkNext
8439 }
8440 makePositionChecker := func(name string, want []P) func(d *jsontext.Decoder, v any) error {
8441 checkNext := func(d *jsontext.Decoder, v any) error {
8442 xd := export.Decoder(d)
8443 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8444 switch {
8445 case len(want) == 0:
8446 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
8447 case p != want[0]:
8448 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
8449 default:
8450 want = want[1:]
8451 return errors.ErrUnsupported
8452 }
8453 }
8454 lastChecks = append(lastChecks, func() error {
8455 if len(want) > 0 {
8456 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8457 }
8458 return nil
8459 })
8460 return checkNext
8461 }
8462
8463
8464
8465 wantAny := []PV{
8466 {P{1, 0}, addr(any(nil))},
8467 {P{1, 1}, addr(any(valueStringer{}))},
8468 {P{1, 1}, addr(valueStringer{})},
8469 {P{1, 2}, addr(any((*valueStringer)(nil)))},
8470 {P{1, 2}, addr((*valueStringer)(nil))},
8471 {P{1, 2}, addr(valueStringer{})},
8472 {P{1, 3}, addr(any(addr(valueStringer{})))},
8473 {P{1, 3}, addr(addr(valueStringer{}))},
8474 {P{1, 3}, addr(valueStringer{})},
8475 {P{1, 4}, addr(any((**valueStringer)(nil)))},
8476 {P{1, 4}, addr((**valueStringer)(nil))},
8477 {P{1, 4}, addr((*valueStringer)(nil))},
8478 {P{1, 4}, addr(valueStringer{})},
8479 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
8480 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
8481 {P{1, 5}, addr((*valueStringer)(nil))},
8482 {P{1, 5}, addr(valueStringer{})},
8483 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
8484 {P{1, 6}, addr(addr(addr(valueStringer{})))},
8485 {P{1, 6}, addr(addr(valueStringer{}))},
8486 {P{1, 6}, addr(valueStringer{})},
8487 {P{1, 7}, addr(any(pointerStringer{}))},
8488 {P{1, 7}, addr(pointerStringer{})},
8489 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
8490 {P{1, 8}, addr((*pointerStringer)(nil))},
8491 {P{1, 8}, addr(pointerStringer{})},
8492 {P{1, 9}, addr(any(addr(pointerStringer{})))},
8493 {P{1, 9}, addr(addr(pointerStringer{}))},
8494 {P{1, 9}, addr(pointerStringer{})},
8495 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
8496 {P{1, 10}, addr((**pointerStringer)(nil))},
8497 {P{1, 10}, addr((*pointerStringer)(nil))},
8498 {P{1, 10}, addr(pointerStringer{})},
8499 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
8500 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
8501 {P{1, 11}, addr((*pointerStringer)(nil))},
8502 {P{1, 11}, addr(pointerStringer{})},
8503 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
8504 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
8505 {P{1, 12}, addr(addr(pointerStringer{}))},
8506 {P{1, 12}, addr(pointerStringer{})},
8507 {P{1, 13}, addr(any("LAST"))},
8508 {P{1, 13}, addr("LAST")},
8509 }
8510 checkAny := makeValueChecker("any", wantAny)
8511 anyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v any) error {
8512 return checkAny(dec, v)
8513 })
8514
8515 var wantPointerAny []PV
8516 for _, v := range wantAny {
8517 if _, ok := v.V.(*any); ok {
8518 wantPointerAny = append(wantPointerAny, v)
8519 }
8520 }
8521 checkPointerAny := makeValueChecker("*any", wantPointerAny)
8522 pointerAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *any) error {
8523 return checkPointerAny(dec, v)
8524 })
8525
8526 checkNamedAny := makeValueChecker("namedAny", wantAny)
8527 namedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v namedAny) error {
8528 return checkNamedAny(dec, v)
8529 })
8530
8531 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
8532 pointerNamedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedAny) error {
8533 return checkPointerNamedAny(dec, v)
8534 })
8535
8536 type stringer = fmt.Stringer
8537 var wantStringer []PV
8538 for _, v := range wantAny {
8539 if _, ok := v.V.(stringer); ok {
8540 wantStringer = append(wantStringer, v)
8541 }
8542 }
8543 checkStringer := makeValueChecker("stringer", wantStringer)
8544 stringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v stringer) error {
8545 return checkStringer(dec, v)
8546 })
8547
8548 checkPointerStringer := makeValueChecker("*stringer", nil)
8549 pointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *stringer) error {
8550 return checkPointerStringer(dec, v)
8551 })
8552
8553 wantValueStringer := []P{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}}
8554 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
8555 pointerValueStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *valueStringer) error {
8556 return checkPointerValueStringer(dec, v)
8557 })
8558
8559 wantPointerStringer := []P{{1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}}
8560 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
8561 pointerPointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *pointerStringer) error {
8562 return checkPointerPointerStringer(dec, v)
8563 })
8564
8565 lastUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8566 return checkLast()
8567 })
8568
8569 return JoinUnmarshalers(
8570
8571
8572 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[14]any) error {
8573 if _, err := dec.ReadToken(); err != nil {
8574 return err
8575 }
8576 for i := range len(*v) {
8577 if err := UnmarshalDecode(dec, &(*v)[i]); err != nil {
8578 return err
8579 }
8580 }
8581 if _, err := dec.ReadToken(); err != nil {
8582 return err
8583 }
8584 return nil
8585 }),
8586
8587 anyUnmarshaler,
8588 pointerAnyUnmarshaler,
8589 namedAnyUnmarshaler,
8590 pointerNamedAnyUnmarshaler,
8591 stringerUnmarshaler,
8592 pointerStringerUnmarshaler,
8593 pointerValueStringerUnmarshaler,
8594 pointerPointerStringerUnmarshaler,
8595 lastUnmarshaler,
8596 )
8597 }()),
8598 },
8599 }, {
8600 name: jsontest.Name("Functions/Precedence/V1First"),
8601 opts: []Options{
8602 WithUnmarshalers(JoinUnmarshalers(
8603 UnmarshalFunc(func(b []byte, v *string) error {
8604 if string(b) != `"called"` {
8605 return fmt.Errorf("got %s, want %s", b, `"called"`)
8606 }
8607 *v = "called"
8608 return nil
8609 }),
8610 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8611 panic("should not be called")
8612 }),
8613 )),
8614 },
8615 inBuf: `"called"`,
8616 inVal: addr(""),
8617 want: addr("called"),
8618 }, {
8619 name: jsontest.Name("Functions/Precedence/V2First"),
8620 opts: []Options{
8621 WithUnmarshalers(JoinUnmarshalers(
8622 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8623 switch t, err := dec.ReadToken(); {
8624 case err != nil:
8625 return err
8626 case t.String() != "called":
8627 return fmt.Errorf("got %q, want %q", t, "called")
8628 }
8629 *v = "called"
8630 return nil
8631 }),
8632 UnmarshalFunc(func([]byte, *string) error {
8633 panic("should not be called")
8634 }),
8635 )),
8636 },
8637 inBuf: `"called"`,
8638 inVal: addr(""),
8639 want: addr("called"),
8640 }, {
8641 name: jsontest.Name("Functions/Precedence/V2Skipped"),
8642 opts: []Options{
8643 WithUnmarshalers(JoinUnmarshalers(
8644 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8645 return errors.ErrUnsupported
8646 }),
8647 UnmarshalFunc(func(b []byte, v *string) error {
8648 if string(b) != `"called"` {
8649 return fmt.Errorf("got %s, want %s", b, `"called"`)
8650 }
8651 *v = "called"
8652 return nil
8653 }),
8654 )),
8655 },
8656 inBuf: `"called"`,
8657 inVal: addr(""),
8658 want: addr("called"),
8659 }, {
8660 name: jsontest.Name("Functions/Precedence/NestedFirst"),
8661 opts: []Options{
8662 WithUnmarshalers(JoinUnmarshalers(
8663 JoinUnmarshalers(
8664 UnmarshalFunc(func(b []byte, v *string) error {
8665 if string(b) != `"called"` {
8666 return fmt.Errorf("got %s, want %s", b, `"called"`)
8667 }
8668 *v = "called"
8669 return nil
8670 }),
8671 ),
8672 UnmarshalFunc(func([]byte, *string) error {
8673 panic("should not be called")
8674 }),
8675 )),
8676 },
8677 inBuf: `"called"`,
8678 inVal: addr(""),
8679 want: addr("called"),
8680 }, {
8681 name: jsontest.Name("Functions/Precedence/NestedLast"),
8682 opts: []Options{
8683 WithUnmarshalers(JoinUnmarshalers(
8684 UnmarshalFunc(func(b []byte, v *string) error {
8685 if string(b) != `"called"` {
8686 return fmt.Errorf("got %s, want %s", b, `"called"`)
8687 }
8688 *v = "called"
8689 return nil
8690 }),
8691 JoinUnmarshalers(
8692 UnmarshalFunc(func([]byte, *string) error {
8693 panic("should not be called")
8694 }),
8695 ),
8696 )),
8697 },
8698 inBuf: `"called"`,
8699 inVal: addr(""),
8700 want: addr("called"),
8701 }, {
8702 name: jsontest.Name("Duration/Null"),
8703 inBuf: `{"D1":null,"D2":null}`,
8704 inVal: addr(struct {
8705 D1 time.Duration `json:",format:units"`
8706 D2 time.Duration `json:",format:nano"`
8707 }{1, 1}),
8708 want: addr(struct {
8709 D1 time.Duration `json:",format:units"`
8710 D2 time.Duration `json:",format:nano"`
8711 }{0, 0}),
8712 }, {
8713 name: jsontest.Name("Duration/Zero"),
8714 inBuf: `{"D1":"0s","D2":0}`,
8715 inVal: addr(struct {
8716 D1 time.Duration `json:",format:units"`
8717 D2 time.Duration `json:",format:nano"`
8718 }{1, 1}),
8719 want: addr(struct {
8720 D1 time.Duration `json:",format:units"`
8721 D2 time.Duration `json:",format:nano"`
8722 }{0, 0}),
8723 }, {
8724 name: jsontest.Name("Duration/Positive"),
8725 inBuf: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
8726 inVal: new(struct {
8727 D1 time.Duration `json:",format:units"`
8728 D2 time.Duration `json:",format:nano"`
8729 }),
8730 want: addr(struct {
8731 D1 time.Duration `json:",format:units"`
8732 D2 time.Duration `json:",format:nano"`
8733 }{
8734 123456789123456789,
8735 123456789123456789,
8736 }),
8737 }, {
8738 name: jsontest.Name("Duration/Negative"),
8739 inBuf: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
8740 inVal: new(struct {
8741 D1 time.Duration `json:",format:units"`
8742 D2 time.Duration `json:",format:nano"`
8743 }),
8744 want: addr(struct {
8745 D1 time.Duration `json:",format:units"`
8746 D2 time.Duration `json:",format:nano"`
8747 }{
8748 -123456789123456789,
8749 -123456789123456789,
8750 }),
8751 }, {
8752 name: jsontest.Name("Duration/Nanos/String"),
8753 inBuf: `{"D":"12345"}`,
8754 inVal: addr(struct {
8755 D time.Duration `json:",string,format:nano"`
8756 }{1}),
8757 want: addr(struct {
8758 D time.Duration `json:",string,format:nano"`
8759 }{12345}),
8760 }, {
8761 name: jsontest.Name("Duration/Nanos/String/Invalid"),
8762 inBuf: `{"D":"+12345"}`,
8763 inVal: addr(struct {
8764 D time.Duration `json:",string,format:nano"`
8765 }{1}),
8766 want: addr(struct {
8767 D time.Duration `json:",string,format:nano"`
8768 }{1}),
8769 wantErr: EU(fmt.Errorf(`invalid duration "+12345": %w`, strconv.ErrSyntax)).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8770 }, {
8771 name: jsontest.Name("Duration/Nanos/Mismatch"),
8772 inBuf: `{"D":"34293h33m9.123456789s"}`,
8773 inVal: addr(struct {
8774 D time.Duration `json:",format:nano"`
8775 }{1}),
8776 want: addr(struct {
8777 D time.Duration `json:",format:nano"`
8778 }{1}),
8779 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8780 }, {
8781 name: jsontest.Name("Duration/Nanos"),
8782 inBuf: `{"D":1.324}`,
8783 inVal: addr(struct {
8784 D time.Duration `json:",format:nano"`
8785 }{-1}),
8786 want: addr(struct {
8787 D time.Duration `json:",format:nano"`
8788 }{1}),
8789 }, {
8790 name: jsontest.Name("Duration/String/Mismatch"),
8791 inBuf: `{"D":-123456789123456789}`,
8792 inVal: addr(struct {
8793 D time.Duration `json:",format:units"`
8794 }{1}),
8795 want: addr(struct {
8796 D time.Duration `json:",format:units"`
8797 }{1}),
8798 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('0', timeDurationType),
8799 }, {
8800 name: jsontest.Name("Duration/String/Invalid"),
8801 inBuf: `{"D":"5minkutes"}`,
8802 inVal: addr(struct {
8803 D time.Duration `json:",format:units"`
8804 }{1}),
8805 want: addr(struct {
8806 D time.Duration `json:",format:units"`
8807 }{1}),
8808 wantErr: EU(func() error {
8809 _, err := time.ParseDuration("5minkutes")
8810 return err
8811 }()).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8812 }, {
8813 name: jsontest.Name("Duration/Syntax/Invalid"),
8814 inBuf: `{"D":x}`,
8815 inVal: addr(struct {
8816 D time.Duration `json:",format:units"`
8817 }{1}),
8818 want: addr(struct {
8819 D time.Duration `json:",format:units"`
8820 }{1}),
8821 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"D":`), "/D"),
8822 }, {
8823 name: jsontest.Name("Duration/Format"),
8824 inBuf: `{
8825 "D1": "12h34m56.078090012s",
8826 "D2": "12h34m56.078090012s",
8827 "D3": 45296.078090012,
8828 "D4": "45296.078090012",
8829 "D5": 45296078.090012,
8830 "D6": "45296078.090012",
8831 "D7": 45296078090.012,
8832 "D8": "45296078090.012",
8833 "D9": 45296078090012,
8834 "D10": "45296078090012",
8835 "D11": "PT12H34M56.078090012S"
8836 }`,
8837 inVal: new(structDurationFormat),
8838 want: addr(structDurationFormat{
8839 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8840 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8841 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8842 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8843 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8844 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8845 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8846 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8847 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8848 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8849 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8850 }),
8851 }, {
8852 name: jsontest.Name("Duration/Format/Invalid"),
8853 inBuf: `{"D":"0s"}`,
8854 inVal: addr(struct {
8855 D time.Duration `json:",format:invalid"`
8856 }{1}),
8857 want: addr(struct {
8858 D time.Duration `json:",format:invalid"`
8859 }{1}),
8860 wantErr: EU(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, timeDurationType),
8861 }, {
8862
8872
8878 name: jsontest.Name("Duration/MapKey/Legacy"),
8879 opts: []Options{jsonflags.FormatDurationAsNano | 1},
8880 inBuf: `{"1000000000":""}`,
8881 inVal: new(map[time.Duration]string),
8882 want: addr(map[time.Duration]string{time.Second: ""}),
8883 }, {
8884
8891 name: jsontest.Name("Time/Zero"),
8892 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"}`,
8893 inVal: new(struct {
8894 T1 time.Time
8895 T2 time.Time `json:",format:RFC822"`
8896 T3 time.Time `json:",format:'2006-01-02'"`
8897 T4 time.Time `json:",omitzero"`
8898 T5 time.Time `json:",omitempty"`
8899 }),
8900 want: addr(struct {
8901 T1 time.Time
8902 T2 time.Time `json:",format:RFC822"`
8903 T3 time.Time `json:",format:'2006-01-02'"`
8904 T4 time.Time `json:",omitzero"`
8905 T5 time.Time `json:",omitempty"`
8906 }{
8907 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8908 mustParseTime(time.RFC822, "01 Jan 01 00:00 UTC"),
8909 mustParseTime("2006-01-02", "0001-01-01"),
8910 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8911 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8912 }),
8913 }, {
8914 name: jsontest.Name("Time/Format"),
8915 inBuf: `{
8916 "T1": "1234-01-02T03:04:05.000000006Z",
8917 "T2": "Mon Jan 2 03:04:05 1234",
8918 "T3": "Mon Jan 2 03:04:05 UTC 1234",
8919 "T4": "Mon Jan 02 03:04:05 +0000 1234",
8920 "T5": "02 Jan 34 03:04 UTC",
8921 "T6": "02 Jan 34 03:04 +0000",
8922 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
8923 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
8924 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
8925 "T10": "1234-01-02T03:04:05Z",
8926 "T11": "1234-01-02T03:04:05.000000006Z",
8927 "T12": "3:04AM",
8928 "T13": "Jan 2 03:04:05",
8929 "T14": "Jan 2 03:04:05.000",
8930 "T15": "Jan 2 03:04:05.000000",
8931 "T16": "Jan 2 03:04:05.000000006",
8932 "T17": "1234-01-02 03:04:05",
8933 "T18": "1234-01-02",
8934 "T19": "03:04:05",
8935 "T20": "1234-01-02",
8936 "T21": "\"weird\"1234",
8937 "T22": -23225777754.999999994,
8938 "T23": "-23225777754.999999994",
8939 "T24": -23225777754999.999994,
8940 "T25": "-23225777754999.999994",
8941 "T26": -23225777754999999.994,
8942 "T27": "-23225777754999999.994",
8943 "T28": -23225777754999999994,
8944 "T29": "-23225777754999999994"
8945 }`,
8946 inVal: new(structTimeFormat),
8947 want: addr(structTimeFormat{
8948 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8949 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
8950 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
8951 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
8952 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
8953 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
8954 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
8955 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
8956 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
8957 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
8958 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8959 mustParseTime(time.Kitchen, "3:04AM"),
8960 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
8961 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
8962 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
8963 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
8964 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
8965 mustParseTime(time.DateOnly, "1234-01-02"),
8966 mustParseTime(time.TimeOnly, "03:04:05"),
8967 mustParseTime("2006-01-02", "1234-01-02"),
8968 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
8969 time.Unix(-23225777755, 6).UTC(),
8970 time.Unix(-23225777755, 6).UTC(),
8971 time.Unix(-23225777755, 6).UTC(),
8972 time.Unix(-23225777755, 6).UTC(),
8973 time.Unix(-23225777755, 6).UTC(),
8974 time.Unix(-23225777755, 6).UTC(),
8975 time.Unix(-23225777755, 6).UTC(),
8976 time.Unix(-23225777755, 6).UTC(),
8977 }),
8978 }, {
8979 name: jsontest.Name("Time/Format/UnixString/InvalidNumber"),
8980 inBuf: `{
8981 "T23": -23225777754.999999994,
8982 "T25": -23225777754999.999994,
8983 "T27": -23225777754999999.994,
8984 "T29": -23225777754999999994
8985 }`,
8986 inVal: new(structTimeFormat),
8987 want: new(structTimeFormat),
8988 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T23": `, "/T23").withType('0', timeTimeType),
8989 }, {
8990 name: jsontest.Name("Time/Format/UnixString/InvalidString"),
8991 inBuf: `{
8992 "T22": "-23225777754.999999994",
8993 "T24": "-23225777754999.999994",
8994 "T26": "-23225777754999999.994",
8995 "T28": "-23225777754999999994"
8996 }`,
8997 inVal: new(structTimeFormat),
8998 want: new(structTimeFormat),
8999 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T22": `, "/T22").withType('"', timeTimeType),
9000 }, {
9001 name: jsontest.Name("Time/Format/Null"),
9002 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}`,
9003 inVal: addr(structTimeFormat{
9004 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9005 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9006 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9007 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9008 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9009 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9010 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9011 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9012 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9013 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9014 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9015 mustParseTime(time.Kitchen, "3:04AM"),
9016 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9017 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9018 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9019 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9020 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9021 mustParseTime(time.DateOnly, "1234-01-02"),
9022 mustParseTime(time.TimeOnly, "03:04:05"),
9023 mustParseTime("2006-01-02", "1234-01-02"),
9024 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9025 time.Unix(-23225777755, 6).UTC(),
9026 time.Unix(-23225777755, 6).UTC(),
9027 time.Unix(-23225777755, 6).UTC(),
9028 time.Unix(-23225777755, 6).UTC(),
9029 time.Unix(-23225777755, 6).UTC(),
9030 time.Unix(-23225777755, 6).UTC(),
9031 time.Unix(-23225777755, 6).UTC(),
9032 time.Unix(-23225777755, 6).UTC(),
9033 }),
9034 want: new(structTimeFormat),
9035 }, {
9036 name: jsontest.Name("Time/RFC3339/Mismatch"),
9037 inBuf: `{"T":1234}`,
9038 inVal: new(struct {
9039 T time.Time
9040 }),
9041 wantErr: EU(nil).withPos(`{"T":`, "/T").withType('0', timeTimeType),
9042 }, {
9043 name: jsontest.Name("Time/RFC3339/ParseError"),
9044 inBuf: `{"T":"2021-09-29T12:44:52"}`,
9045 inVal: new(struct {
9046 T time.Time
9047 }),
9048 wantErr: EU(func() error {
9049 _, err := time.Parse(time.RFC3339, "2021-09-29T12:44:52")
9050 return err
9051 }()).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9052 }, {
9053 name: jsontest.Name("Time/Format/Invalid"),
9054 inBuf: `{"T":""}`,
9055 inVal: new(struct {
9056 T time.Time `json:",format:UndefinedConstant"`
9057 }),
9058 wantErr: EU(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
9059 }, {
9060 name: jsontest.Name("Time/Format/SingleDigitHour"),
9061 inBuf: `{"T":"2000-01-01T1:12:34Z"}`,
9062 inVal: new(struct{ T time.Time }),
9063 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T1:12:34Z", "15", "1", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9064 }, {
9065 name: jsontest.Name("Time/Format/SubsecondComma"),
9066 inBuf: `{"T":"2000-01-01T00:00:00,000Z"}`,
9067 inVal: new(struct{ T time.Time }),
9068 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00,000Z", ".", ",", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9069 }, {
9070 name: jsontest.Name("Time/Format/TimezoneHourOverflow"),
9071 inBuf: `{"T":"2000-01-01T00:00:00+24:00"}`,
9072 inVal: new(struct{ T time.Time }),
9073 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),
9074 }, {
9075 name: jsontest.Name("Time/Format/TimezoneMinuteOverflow"),
9076 inBuf: `{"T":"2000-01-01T00:00:00+00:60"}`,
9077 inVal: new(struct{ T time.Time }),
9078 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),
9079 }, {
9080 name: jsontest.Name("Time/Syntax/Invalid"),
9081 inBuf: `{"T":x}`,
9082 inVal: new(struct {
9083 T time.Time
9084 }),
9085 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"T":`), "/T"),
9086 }, {
9087 name: jsontest.Name("Time/IgnoreInvalidFormat"),
9088 opts: []Options{invalidFormatOption},
9089 inBuf: `"2000-01-01T00:00:00Z"`,
9090 inVal: addr(time.Time{}),
9091 want: addr(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)),
9092 }}
9093
9094 for _, tt := range tests {
9095 t.Run(tt.name.Name, func(t *testing.T) {
9096 got := tt.inVal
9097 gotErr := Unmarshal([]byte(tt.inBuf), got, tt.opts...)
9098 if !reflect.DeepEqual(got, tt.want) && tt.want != nil {
9099 t.Errorf("%s: Unmarshal output mismatch:\ngot %v\nwant %v", tt.name.Where, got, tt.want)
9100 }
9101 if !reflect.DeepEqual(gotErr, tt.wantErr) {
9102 t.Errorf("%s: Unmarshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
9103 }
9104 })
9105 }
9106 }
9107
9108 func TestMarshalInvalidNamespace(t *testing.T) {
9109 tests := []struct {
9110 name jsontest.CaseName
9111 val any
9112 }{
9113 {jsontest.Name("Map"), map[string]string{"X": "\xde\xad\xbe\xef"}},
9114 {jsontest.Name("Struct"), struct{ X string }{"\xde\xad\xbe\xef"}},
9115 }
9116 for _, tt := range tests {
9117 t.Run(tt.name.Name, func(t *testing.T) {
9118 enc := jsontext.NewEncoder(new(bytes.Buffer))
9119 if err := MarshalEncode(enc, tt.val); err == nil {
9120 t.Fatalf("%s: MarshalEncode error is nil, want non-nil", tt.name.Where)
9121 }
9122 for _, tok := range []jsontext.Token{
9123 jsontext.Null, jsontext.String(""), jsontext.Int(0), jsontext.BeginObject, jsontext.EndObject, jsontext.BeginArray, jsontext.EndArray,
9124 } {
9125 if err := enc.WriteToken(tok); err == nil {
9126 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9127 }
9128 }
9129 for _, val := range []string{`null`, `""`, `0`, `{}`, `[]`} {
9130 if err := enc.WriteValue([]byte(val)); err == nil {
9131 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9132 }
9133 }
9134 })
9135 }
9136 }
9137
9138 func TestUnmarshalInvalidNamespace(t *testing.T) {
9139 tests := []struct {
9140 name jsontest.CaseName
9141 val any
9142 }{
9143 {jsontest.Name("Map"), addr(map[string]int{})},
9144 {jsontest.Name("Struct"), addr(struct{ X int }{})},
9145 }
9146 for _, tt := range tests {
9147 t.Run(tt.name.Name, func(t *testing.T) {
9148 dec := jsontext.NewDecoder(strings.NewReader(`{"X":""}`))
9149 if err := UnmarshalDecode(dec, tt.val); err == nil {
9150 t.Fatalf("%s: UnmarshalDecode error is nil, want non-nil", tt.name.Where)
9151 }
9152 if _, err := dec.ReadToken(); err == nil {
9153 t.Fatalf("%s: ReadToken error is nil, want non-nil", tt.name.Where)
9154 }
9155 if _, err := dec.ReadValue(); err == nil {
9156 t.Fatalf("%s: ReadValue error is nil, want non-nil", tt.name.Where)
9157 }
9158 })
9159 }
9160 }
9161
9162 func TestUnmarshalReuse(t *testing.T) {
9163 t.Run("Bytes", func(t *testing.T) {
9164 in := make([]byte, 3)
9165 want := &in[0]
9166 if err := Unmarshal([]byte(`"AQID"`), &in); err != nil {
9167 t.Fatalf("Unmarshal error: %v", err)
9168 }
9169 got := &in[0]
9170 if got != want {
9171 t.Errorf("input buffer was not reused")
9172 }
9173 })
9174 t.Run("Slices", func(t *testing.T) {
9175 in := make([]int, 3)
9176 want := &in[0]
9177 if err := Unmarshal([]byte(`[0,1,2]`), &in); err != nil {
9178 t.Fatalf("Unmarshal error: %v", err)
9179 }
9180 got := &in[0]
9181 if got != want {
9182 t.Errorf("input slice was not reused")
9183 }
9184 })
9185 t.Run("Maps", func(t *testing.T) {
9186 in := make(map[string]string)
9187 want := reflect.ValueOf(in).Pointer()
9188 if err := Unmarshal([]byte(`{"key":"value"}`), &in); err != nil {
9189 t.Fatalf("Unmarshal error: %v", err)
9190 }
9191 got := reflect.ValueOf(in).Pointer()
9192 if got != want {
9193 t.Errorf("input map was not reused")
9194 }
9195 })
9196 t.Run("Pointers", func(t *testing.T) {
9197 in := addr(addr(addr("hello")))
9198 want := **in
9199 if err := Unmarshal([]byte(`"goodbye"`), &in); err != nil {
9200 t.Fatalf("Unmarshal error: %v", err)
9201 }
9202 got := **in
9203 if got != want {
9204 t.Errorf("input pointer was not reused")
9205 }
9206 })
9207 }
9208
9209 type unmarshalerEOF struct{}
9210
9211 func (unmarshalerEOF) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
9212 return io.EOF
9213 }
9214
9215
9216
9217 func TestUnmarshalEOF(t *testing.T) {
9218 opts := WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ *struct{}) error {
9219 return io.EOF
9220 }))
9221
9222 for _, in := range []string{"", "[", "[null", "[null]"} {
9223 for _, newOut := range []func() any{
9224 func() any { return new(unmarshalerEOF) },
9225 func() any { return new([]unmarshalerEOF) },
9226 func() any { return new(struct{}) },
9227 func() any { return new([]struct{}) },
9228 } {
9229 wantErr := io.ErrUnexpectedEOF
9230 if gotErr := Unmarshal([]byte(in), newOut(), opts); !errors.Is(gotErr, wantErr) {
9231 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9232 }
9233 if gotErr := UnmarshalRead(strings.NewReader(in), newOut(), opts); !errors.Is(gotErr, wantErr) {
9234 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9235 }
9236 switch gotErr := UnmarshalDecode(jsontext.NewDecoder(strings.NewReader(in)), newOut(), opts); {
9237 case in != "" && !errors.Is(gotErr, wantErr):
9238 t.Errorf("Unmarshal = %v, want %v", gotErr, wantErr)
9239 case in == "" && gotErr != io.EOF:
9240 t.Errorf("Unmarshal = %v, want %v", gotErr, io.EOF)
9241 }
9242 }
9243 }
9244 }
9245
9246 type ReaderFunc func([]byte) (int, error)
9247
9248 func (f ReaderFunc) Read(b []byte) (int, error) { return f(b) }
9249
9250 type WriterFunc func([]byte) (int, error)
9251
9252 func (f WriterFunc) Write(b []byte) (int, error) { return f(b) }
9253
9254 func TestCoderBufferGrowth(t *testing.T) {
9255
9256
9257 checkGrowth := func(ns []int) {
9258 t.Helper()
9259 var sumBytes, sumRates, numGrows float64
9260 prev := ns[0]
9261 for i := 1; i < len(ns)-1; i++ {
9262 n := ns[i]
9263 if n != prev {
9264 sumRates += float64(n) / float64(prev)
9265 numGrows++
9266 prev = n
9267 }
9268 if n > 1<<20 {
9269 t.Fatalf("single Read/Write too large: %d", n)
9270 }
9271 sumBytes += float64(n)
9272 }
9273 if mean := sumBytes / float64(len(ns)); mean < 1<<10 {
9274 t.Fatalf("average Read/Write too small: %0.1f", mean)
9275 }
9276 switch mean := sumRates / numGrows; {
9277 case mean < 1.25:
9278 t.Fatalf("average growth rate too slow: %0.3f", mean)
9279 case mean > 2.00:
9280 t.Fatalf("average growth rate too fast: %0.3f", mean)
9281 }
9282 }
9283
9284
9285
9286 bb := struct{ *bytes.Buffer }{new(bytes.Buffer)}
9287
9288 var writeSizes []int
9289 if err := MarshalWrite(WriterFunc(func(b []byte) (int, error) {
9290 n, err := bb.Write(b)
9291 writeSizes = append(writeSizes, n)
9292 return n, err
9293 }), make([]struct{}, 1e6)); err != nil {
9294 t.Fatalf("MarshalWrite error: %v", err)
9295 }
9296 checkGrowth(writeSizes)
9297
9298 var readSizes []int
9299 if err := UnmarshalRead(ReaderFunc(func(b []byte) (int, error) {
9300 n, err := bb.Read(b)
9301 readSizes = append(readSizes, n)
9302 return n, err
9303 }), new([]struct{})); err != nil {
9304 t.Fatalf("UnmarshalRead error: %v", err)
9305 }
9306 checkGrowth(readSizes)
9307 }
9308
9309 func TestUintSet(t *testing.T) {
9310 type operation any
9311 type has struct {
9312 in uint
9313 want bool
9314 }
9315 type insert struct {
9316 in uint
9317 want bool
9318 }
9319
9320
9321 ops := []operation{
9322 has{0, false},
9323 has{63, false},
9324 has{64, false},
9325 has{1234, false},
9326 insert{3, true},
9327 has{2, false},
9328 has{3, true},
9329 has{4, false},
9330 has{63, false},
9331 insert{3, false},
9332 insert{63, true},
9333 has{63, true},
9334 insert{64, true},
9335 insert{64, false},
9336 has{64, true},
9337 insert{3264, true},
9338 has{3264, true},
9339 insert{3, false},
9340 has{3, true},
9341 }
9342
9343 var us uintSet
9344 for i, op := range ops {
9345 switch op := op.(type) {
9346 case has:
9347 if got := us.has(op.in); got != op.want {
9348 t.Fatalf("%d: uintSet.has(%v) = %v, want %v", i, op.in, got, op.want)
9349 }
9350 case insert:
9351 if got := us.insert(op.in); got != op.want {
9352 t.Fatalf("%d: uintSet.insert(%v) = %v, want %v", i, op.in, got, op.want)
9353 }
9354 default:
9355 panic(fmt.Sprintf("unknown operation: %T", op))
9356 }
9357 }
9358 }
9359
9360 func TestUnmarshalDecodeOptions(t *testing.T) {
9361 var calledFuncs int
9362 var calledOptions Options
9363 in := strings.NewReader(strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9364 dec := jsontext.NewDecoder(in,
9365 jsontext.AllowInvalidUTF8(true),
9366 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ any) error {
9367 opts := dec.Options()
9368 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9369 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9370 }
9371 calledFuncs++
9372 calledOptions = opts
9373 return errors.ErrUnsupported
9374 })),
9375 )
9376
9377 if err := UnmarshalDecode(dec, new(string)); err != nil {
9378 t.Fatalf("UnmarshalDecode: %v", err)
9379 }
9380 if calledFuncs != 1 {
9381 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9382 }
9383 if err := UnmarshalDecode(dec, new(string), calledOptions); err != nil {
9384 t.Fatalf("UnmarshalDecode: %v", err)
9385 }
9386 if calledFuncs != 2 {
9387 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9388 }
9389 if err := UnmarshalDecode(dec, new(string),
9390 jsontext.AllowInvalidUTF8(false),
9391 WithUnmarshalers(nil),
9392 ); err != nil {
9393 t.Fatalf("UnmarshalDecode: %v", err)
9394 }
9395 if calledFuncs != 2 {
9396 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9397 }
9398 if err := UnmarshalDecode(dec, new(string)); err != nil {
9399 t.Fatalf("UnmarshalDecode: %v", err)
9400 }
9401 if calledFuncs != 3 {
9402 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9403 }
9404 if err := UnmarshalDecode(dec, new(string), JoinOptions(
9405 jsontext.AllowInvalidUTF8(false),
9406 WithUnmarshalers(UnmarshalFromFunc(func(_ *jsontext.Decoder, _ any) error {
9407 opts := dec.Options()
9408 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9409 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9410 }
9411 calledFuncs = math.MaxInt
9412 return errors.ErrUnsupported
9413 })),
9414 )); err != nil {
9415 t.Fatalf("UnmarshalDecode: %v", err)
9416 }
9417 if calledFuncs != math.MaxInt {
9418 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9419 }
9420
9421
9422
9423 opts := dec.Options()
9424 dec.Reset(in, jsontext.AllowInvalidUTF8(false), opts)
9425 if v, _ := GetOption(dec.Options(), jsontext.AllowInvalidUTF8); v == false {
9426 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9427 }
9428 }
9429
9430 func TestUnmarshalDecodeStream(t *testing.T) {
9431 tests := []struct {
9432 in string
9433 want []any
9434 err error
9435 }{
9436 {in: ``, err: io.EOF},
9437 {in: `{`, err: &jsontext.SyntacticError{ByteOffset: len64(`{`), Err: io.ErrUnexpectedEOF}},
9438 {in: `{"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"`), Err: io.ErrUnexpectedEOF}},
9439 {in: `{"k"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9440 {in: `{"k":`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k":`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9441 {in: `{"k",`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError(",", "after object name (expecting ':')")}},
9442 {in: `{"k"}`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError("}", "after object name (expecting ':')")}},
9443 {in: `[`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), Err: io.ErrUnexpectedEOF}},
9444 {in: `[0`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: io.ErrUnexpectedEOF}},
9445 {in: ` [0`, err: &jsontext.SyntacticError{ByteOffset: len64(` [0`), Err: io.ErrUnexpectedEOF}},
9446 {in: `[0.`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), JSONPointer: "/0", Err: io.ErrUnexpectedEOF}},
9447 {in: `[0. `, err: &jsontext.SyntacticError{ByteOffset: len64(`[0.`), JSONPointer: "/0", Err: jsonwire.NewInvalidCharacterError(" ", "in number (expecting digit)")}},
9448 {in: `[0,`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0,`), Err: io.ErrUnexpectedEOF}},
9449 {in: `[0:`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: jsonwire.NewInvalidCharacterError(":", "after array element (expecting ',' or ']')")}},
9450 {in: `n`, err: &jsontext.SyntacticError{ByteOffset: len64(`n`), Err: io.ErrUnexpectedEOF}},
9451 {in: `nul`, err: &jsontext.SyntacticError{ByteOffset: len64(`nul`), Err: io.ErrUnexpectedEOF}},
9452 {in: `fal `, err: &jsontext.SyntacticError{ByteOffset: len64(`fal`), Err: jsonwire.NewInvalidCharacterError(" ", "in literal false (expecting 's')")}},
9453 {in: `false`, want: []any{false}, err: io.EOF},
9454 {in: `false0.0[]null`, want: []any{false, 0.0, []any{}, nil}, err: io.EOF},
9455 }
9456 for _, tt := range tests {
9457 d := jsontext.NewDecoder(strings.NewReader(tt.in))
9458 var got []any
9459 for {
9460 var v any
9461 if err := UnmarshalDecode(d, &v); err != nil {
9462 if !reflect.DeepEqual(err, tt.err) {
9463 t.Errorf("`%s`: UnmarshalDecode error = %v, want %v", tt.in, err, tt.err)
9464 }
9465 break
9466 }
9467 got = append(got, v)
9468 }
9469 if !reflect.DeepEqual(got, tt.want) {
9470 t.Errorf("`%s`: UnmarshalDecode = %v, want %v", tt.in, got, tt.want)
9471 }
9472 }
9473 }
9474
9475
9476
9477 func BenchmarkUnmarshalDecodeOptions(b *testing.B) {
9478 var i int
9479 in := new(bytes.Buffer)
9480 dec := jsontext.NewDecoder(in)
9481 makeBench := func(opts ...Options) func(*testing.B) {
9482 return func(b *testing.B) {
9483 for range b.N {
9484 in.WriteString("0 ")
9485 }
9486 dec.Reset(in)
9487 b.ResetTimer()
9488 for range b.N {
9489 UnmarshalDecode(dec, &i, opts...)
9490 }
9491 }
9492 }
9493 b.Run("None", makeBench())
9494 b.Run("Same", makeBench(&export.Decoder(dec).Struct))
9495 b.Run("New", makeBench(DefaultOptionsV2()))
9496 }
9497
9498 func TestMarshalEncodeOptions(t *testing.T) {
9499 var calledFuncs int
9500 var calledOptions Options
9501 out := new(bytes.Buffer)
9502 enc := jsontext.NewEncoder(
9503 out,
9504 jsontext.AllowInvalidUTF8(true),
9505 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9506 opts := enc.Options()
9507 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9508 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9509 }
9510 calledFuncs++
9511 calledOptions = opts
9512 return errors.ErrUnsupported
9513 })),
9514 )
9515
9516 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9517 t.Fatalf("MarshalEncode: %v", err)
9518 }
9519 if calledFuncs != 1 {
9520 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9521 }
9522 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", calledOptions); err != nil {
9523 t.Fatalf("MarshalEncode: %v", err)
9524 }
9525 if calledFuncs != 2 {
9526 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9527 }
9528 if err := MarshalEncode(enc, "\xde\xad\xbe\xef",
9529 jsontext.AllowInvalidUTF8(false),
9530 WithMarshalers(nil),
9531 ); err != nil {
9532 t.Fatalf("MarshalEncode: %v", err)
9533 }
9534 if calledFuncs != 2 {
9535 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9536 }
9537 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9538 t.Fatalf("MarshalEncode: %v", err)
9539 }
9540 if calledFuncs != 3 {
9541 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9542 }
9543 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", JoinOptions(
9544 jsontext.AllowInvalidUTF8(false),
9545 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9546 opts := enc.Options()
9547 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9548 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9549 }
9550 calledFuncs = math.MaxInt
9551 return errors.ErrUnsupported
9552 })),
9553 )); err != nil {
9554 t.Fatalf("MarshalEncode: %v", err)
9555 }
9556 if calledFuncs != math.MaxInt {
9557 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9558 }
9559 if out.String() != strings.Repeat("\"\xde\xad\ufffd\ufffd\"\n", 5) {
9560 t.Fatalf("output mismatch:\n\tgot: %s\n\twant: %s", out.String(), strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9561 }
9562
9563
9564
9565 opts := enc.Options()
9566 enc.Reset(out, jsontext.AllowInvalidUTF8(false), opts)
9567 if v, _ := GetOption(enc.Options(), jsontext.AllowInvalidUTF8); v == false {
9568 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9569 }
9570 }
9571
9572
9573
9574 func BenchmarkMarshalEncodeOptions(b *testing.B) {
9575 var i int
9576 out := new(bytes.Buffer)
9577 enc := jsontext.NewEncoder(out)
9578 makeBench := func(opts ...Options) func(*testing.B) {
9579 return func(b *testing.B) {
9580 out.Reset()
9581 enc.Reset(out)
9582 b.ResetTimer()
9583 for range b.N {
9584 MarshalEncode(enc, &i, opts...)
9585 }
9586 }
9587 }
9588 b.Run("None", makeBench())
9589 b.Run("Same", makeBench(&export.Encoder(enc).Struct))
9590 b.Run("New", makeBench(DefaultOptionsV2()))
9591 }
9592
View as plain text