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 structUnknownTextValue struct {
423 A int `json:",omitzero"`
424 X jsontext.Value `json:",unknown"`
425 B int `json:",omitzero"`
426 }
427 structInlineTextValue struct {
428 A int `json:",omitzero"`
429 X jsontext.Value `json:",inline"`
430 B int `json:",omitzero"`
431 }
432 structInlinePointerTextValue struct {
433 A int `json:",omitzero"`
434 X *jsontext.Value `json:",inline"`
435 B int `json:",omitzero"`
436 }
437 structInlinePointerInlineTextValue struct {
438 X *struct {
439 A int
440 X jsontext.Value `json:",inline"`
441 } `json:",inline"`
442 }
443 structInlineInlinePointerTextValue struct {
444 X struct {
445 X *jsontext.Value `json:",inline"`
446 } `json:",inline"`
447 }
448 structInlineMapStringAny struct {
449 A int `json:",omitzero"`
450 X jsonObject `json:",inline"`
451 B int `json:",omitzero"`
452 }
453 structInlinePointerMapStringAny struct {
454 A int `json:",omitzero"`
455 X *jsonObject `json:",inline"`
456 B int `json:",omitzero"`
457 }
458 structInlinePointerInlineMapStringAny struct {
459 X *struct {
460 A int
461 X jsonObject `json:",inline"`
462 } `json:",inline"`
463 }
464 structInlineInlinePointerMapStringAny struct {
465 X struct {
466 X *jsonObject `json:",inline"`
467 } `json:",inline"`
468 }
469 structInlineMapStringInt struct {
470 X map[string]int `json:",inline"`
471 }
472 structInlineMapNamedStringInt struct {
473 X map[namedString]int `json:",inline"`
474 }
475 structInlineMapNamedStringAny struct {
476 A int `json:",omitzero"`
477 X map[namedString]any `json:",inline"`
478 B int `json:",omitzero"`
479 }
480 structNoCaseInlineTextValue struct {
481 AAA string `json:",omitempty,case:strict"`
482 AA_b string `json:",omitempty"`
483 AaA string `json:",omitempty,case:ignore"`
484 AAa string `json:",omitempty,case:ignore"`
485 Aaa string `json:",omitempty"`
486 X jsontext.Value `json:",inline"`
487 }
488 structNoCaseInlineMapStringAny struct {
489 AAA string `json:",omitempty"`
490 AaA string `json:",omitempty,case:ignore"`
491 AAa string `json:",omitempty,case:ignore"`
492 Aaa string `json:",omitempty"`
493 X jsonObject `json:",inline"`
494 }
495
496 allMethods struct {
497 method string
498 value []byte
499 }
500 allMethodsExceptJSONv2 struct {
501 allMethods
502 MarshalJSONTo struct{}
503 UnmarshalJSONFrom struct{}
504 }
505 allMethodsExceptJSONv1 struct {
506 allMethods
507 MarshalJSON struct{}
508 UnmarshalJSON struct{}
509 }
510 allMethodsExceptText struct {
511 allMethods
512 MarshalText struct{}
513 UnmarshalText struct{}
514 }
515 onlyMethodJSONv2 struct {
516 allMethods
517 MarshalJSON struct{}
518 UnmarshalJSON struct{}
519 MarshalText struct{}
520 UnmarshalText struct{}
521 }
522 onlyMethodJSONv1 struct {
523 allMethods
524 MarshalJSONTo struct{}
525 UnmarshalJSONFrom struct{}
526 MarshalText struct{}
527 UnmarshalText struct{}
528 }
529 onlyMethodText struct {
530 allMethods
531 MarshalJSONTo struct{}
532 UnmarshalJSONFrom struct{}
533 MarshalJSON struct{}
534 UnmarshalJSON struct{}
535 }
536
537 structMethodJSONv2 struct{ value string }
538 structMethodJSONv1 struct{ value string }
539 structMethodText struct{ value string }
540
541 marshalJSONv2Func func(*jsontext.Encoder) error
542 marshalJSONv1Func func() ([]byte, error)
543 appendTextFunc func([]byte) ([]byte, error)
544 marshalTextFunc func() ([]byte, error)
545 unmarshalJSONv2Func func(*jsontext.Decoder) error
546 unmarshalJSONv1Func func([]byte) error
547 unmarshalTextFunc func([]byte) error
548
549 nocaseString string
550
551 stringMarshalEmpty string
552 stringMarshalNonEmpty string
553 bytesMarshalEmpty []byte
554 bytesMarshalNonEmpty []byte
555 mapMarshalEmpty map[string]string
556 mapMarshalNonEmpty map[string]string
557 sliceMarshalEmpty []string
558 sliceMarshalNonEmpty []string
559
560 valueAlwaysZero string
561 valueNeverZero string
562 pointerAlwaysZero string
563 pointerNeverZero string
564
565 valueStringer struct{}
566 pointerStringer struct{}
567
568 cyclicA struct {
569 B1 cyclicB `json:",inline"`
570 B2 cyclicB `json:",inline"`
571 }
572 cyclicB struct {
573 F int
574 A *cyclicA `json:",inline"`
575 }
576 )
577
578 func (structUnexportedEmbeddedMethodTag) MarshalText() {}
579 func (structUnexportedEmbeddedMethodTag) AppendText() {}
580
581 func (p *allMethods) MarshalJSONTo(enc *jsontext.Encoder) error {
582 if got, want := "MarshalJSONTo", p.method; got != want {
583 return fmt.Errorf("called wrong method: got %v, want %v", got, want)
584 }
585 return enc.WriteValue(p.value)
586 }
587 func (p *allMethods) MarshalJSON() ([]byte, error) {
588 if got, want := "MarshalJSON", p.method; got != want {
589 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
590 }
591 return p.value, nil
592 }
593 func (p *allMethods) MarshalText() ([]byte, error) {
594 if got, want := "MarshalText", p.method; got != want {
595 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
596 }
597 return p.value, nil
598 }
599
600 func (p *allMethods) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
601 p.method = "UnmarshalJSONFrom"
602 val, err := dec.ReadValue()
603 p.value = val
604 return err
605 }
606 func (p *allMethods) UnmarshalJSON(val []byte) error {
607 p.method = "UnmarshalJSON"
608 p.value = val
609 return nil
610 }
611 func (p *allMethods) UnmarshalText(val []byte) error {
612 p.method = "UnmarshalText"
613 p.value = val
614 return nil
615 }
616
617 func (s structMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
618 return enc.WriteToken(jsontext.String(s.value))
619 }
620 func (s *structMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
621 tok, err := dec.ReadToken()
622 if err != nil {
623 return err
624 }
625 if k := tok.Kind(); k != '"' {
626 return EU(nil).withType(k, T[structMethodJSONv2]())
627 }
628 s.value = tok.String()
629 return nil
630 }
631
632 func (s structMethodJSONv1) MarshalJSON() ([]byte, error) {
633 return jsontext.AppendQuote(nil, s.value)
634 }
635 func (s *structMethodJSONv1) UnmarshalJSON(b []byte) error {
636 if k := jsontext.Value(b).Kind(); k != '"' {
637 return EU(nil).withType(k, T[structMethodJSONv1]())
638 }
639 b, _ = jsontext.AppendUnquote(nil, b)
640 s.value = string(b)
641 return nil
642 }
643
644 func (s structMethodText) MarshalText() ([]byte, error) {
645 return []byte(s.value), nil
646 }
647 func (s *structMethodText) UnmarshalText(b []byte) error {
648 s.value = string(b)
649 return nil
650 }
651
652 func (f marshalJSONv2Func) MarshalJSONTo(enc *jsontext.Encoder) error {
653 return f(enc)
654 }
655 func (f marshalJSONv1Func) MarshalJSON() ([]byte, error) {
656 return f()
657 }
658 func (f appendTextFunc) AppendText(b []byte) ([]byte, error) {
659 return f(b)
660 }
661 func (f marshalTextFunc) MarshalText() ([]byte, error) {
662 return f()
663 }
664 func (f unmarshalJSONv2Func) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
665 return f(dec)
666 }
667 func (f unmarshalJSONv1Func) UnmarshalJSON(b []byte) error {
668 return f(b)
669 }
670 func (f unmarshalTextFunc) UnmarshalText(b []byte) error {
671 return f(b)
672 }
673
674 func (k nocaseString) MarshalText() ([]byte, error) {
675 return []byte(strings.ToLower(string(k))), nil
676 }
677 func (k *nocaseString) UnmarshalText(b []byte) error {
678 *k = nocaseString(strings.ToLower(string(b)))
679 return nil
680 }
681
682 func (stringMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`""`), nil }
683 func (stringMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`"value"`), nil }
684 func (bytesMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
685 func (bytesMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
686 func (mapMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`{}`), nil }
687 func (mapMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`{"key":"value"}`), nil }
688 func (sliceMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
689 func (sliceMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
690
691 func (valueAlwaysZero) IsZero() bool { return true }
692 func (valueNeverZero) IsZero() bool { return false }
693 func (*pointerAlwaysZero) IsZero() bool { return true }
694 func (*pointerNeverZero) IsZero() bool { return false }
695
696 func (valueStringer) String() string { return "" }
697 func (*pointerStringer) String() string { return "" }
698
699 func addr[T any](v T) *T {
700 return &v
701 }
702
703 func mustParseTime(layout, value string) time.Time {
704 t, err := time.Parse(layout, value)
705 if err != nil {
706 panic(err)
707 }
708 return t
709 }
710
711 var invalidFormatOption = &jsonopts.Struct{
712 ArshalValues: jsonopts.ArshalValues{FormatDepth: 1000, Format: "invalid"},
713 }
714
715 func TestMarshal(t *testing.T) {
716 tests := []struct {
717 name jsontest.CaseName
718 opts []Options
719 in any
720 want string
721 wantErr error
722
723 canonicalize bool
724 useWriter bool
725 }{{
726 name: jsontest.Name("Nil"),
727 in: nil,
728 want: `null`,
729 }, {
730 name: jsontest.Name("Bools"),
731 in: []bool{false, true},
732 want: `[false,true]`,
733 }, {
734 name: jsontest.Name("Bools/Named"),
735 in: []namedBool{false, true},
736 want: `[false,true]`,
737 }, {
738 name: jsontest.Name("Bools/NotStringified"),
739 opts: []Options{StringifyNumbers(true)},
740 in: []bool{false, true},
741 want: `[false,true]`,
742 }, {
743 name: jsontest.Name("Bools/StringifiedBool"),
744 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
745 in: []bool{false, true},
746 want: `["false","true"]`,
747 }, {
748 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
749 opts: []Options{invalidFormatOption},
750 in: true,
751 want: `true`,
752 }, {
753 name: jsontest.Name("Strings"),
754 in: []string{"", "hello", "世界"},
755 want: `["","hello","世界"]`,
756 }, {
757 name: jsontest.Name("Strings/Named"),
758 in: []namedString{"", "hello", "世界"},
759 want: `["","hello","世界"]`,
760 }, {
761 name: jsontest.Name("Strings/StringifiedBool"),
762 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
763 in: []string{"", "hello", "世界"},
764 want: `["\"\"","\"hello\"","\"世界\""]`,
765 }, {
766 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
767 opts: []Options{invalidFormatOption},
768 in: "string",
769 want: `"string"`,
770 }, {
771 name: jsontest.Name("Bytes"),
772 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
773 want: `["","","AQ==","AQI=","AQID"]`,
774 }, {
775 name: jsontest.Name("Bytes/FormatNilSliceAsNull"),
776 opts: []Options{FormatNilSliceAsNull(true)},
777 in: [][]byte{nil, {}},
778 want: `[null,""]`,
779 }, {
780 name: jsontest.Name("Bytes/Large"),
781 in: []byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on."),
782 want: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
783 }, {
784 name: jsontest.Name("Bytes/Named"),
785 in: []namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}},
786 want: `["","","AQ==","AQI=","AQID"]`,
787 }, {
788 name: jsontest.Name("Bytes/NotStringified"),
789 opts: []Options{StringifyNumbers(true)},
790 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
791 want: `["","","AQ==","AQI=","AQID"]`,
792 }, {
793
794
795 name: jsontest.Name("Bytes/Invariant"),
796 in: [][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
797 want: `[[],[],[1],[1,2],[1,2,3]]`,
798 }, {
799
800
801 name: jsontest.Name("Bytes/ByteArray"),
802 in: [5]byte{'h', 'e', 'l', 'l', 'o'},
803 want: `"aGVsbG8="`,
804 }, {
805
806
807 name: jsontest.Name("Bytes/NamedByteArray"),
808 in: [5]namedByte{'h', 'e', 'l', 'l', 'o'},
809 want: `[104,101,108,108,111]`,
810 }, {
811 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
812 opts: []Options{invalidFormatOption},
813 in: []byte("hello"),
814 want: `"aGVsbG8="`,
815 }, {
816 name: jsontest.Name("Ints"),
817 in: []any{
818 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
819 },
820 want: `[0,-128,-32768,-2147483648,-9223372036854775808,-6464]`,
821 }, {
822 name: jsontest.Name("Ints/Stringified"),
823 opts: []Options{StringifyNumbers(true)},
824 in: []any{
825 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
826 },
827 want: `["0","-128","-32768","-2147483648","-9223372036854775808","-6464"]`,
828 }, {
829 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
830 opts: []Options{invalidFormatOption},
831 in: int(0),
832 want: `0`,
833 }, {
834 name: jsontest.Name("Uints"),
835 in: []any{
836 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464), uintptr(1234),
837 },
838 want: `[0,255,65535,4294967295,18446744073709551615,6464,1234]`,
839 }, {
840 name: jsontest.Name("Uints/Stringified"),
841 opts: []Options{StringifyNumbers(true)},
842 in: []any{
843 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464),
844 },
845 want: `["0","255","65535","4294967295","18446744073709551615","6464"]`,
846 }, {
847 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
848 opts: []Options{invalidFormatOption},
849 in: uint(0),
850 want: `0`,
851 }, {
852 name: jsontest.Name("Floats"),
853 in: []any{
854 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
855 },
856 want: `[3.4028235e+38,1.7976931348623157e+308,64.64]`,
857 }, {
858 name: jsontest.Name("Floats/Stringified"),
859 opts: []Options{StringifyNumbers(true)},
860 in: []any{
861 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
862 },
863 want: `["3.4028235e+38","1.7976931348623157e+308","64.64"]`,
864 }, {
865 name: jsontest.Name("Floats/Invalid/NaN"),
866 opts: []Options{StringifyNumbers(true)},
867 in: math.NaN(),
868 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, float64Type),
869 }, {
870 name: jsontest.Name("Floats/Invalid/PositiveInfinity"),
871 in: math.Inf(+1),
872 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(+1))).withType(0, float64Type),
873 }, {
874 name: jsontest.Name("Floats/Invalid/NegativeInfinity"),
875 in: math.Inf(-1),
876 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(-1))).withType(0, float64Type),
877 }, {
878 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
879 opts: []Options{invalidFormatOption},
880 in: float64(0),
881 want: `0`,
882 }, {
883 name: jsontest.Name("Maps/InvalidKey/Bool"),
884 in: map[bool]string{false: "value"},
885 want: `{`,
886 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, boolType),
887 }, {
888 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
889 in: map[namedBool]string{false: "value"},
890 want: `{`,
891 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[namedBool]()),
892 }, {
893 name: jsontest.Name("Maps/InvalidKey/Array"),
894 in: map[[1]string]string{{"key"}: "value"},
895 want: `{`,
896 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[[1]string]()),
897 }, {
898 name: jsontest.Name("Maps/InvalidKey/Channel"),
899 in: map[chan string]string{make(chan string): "value"},
900 want: `{`,
901 wantErr: EM(nil).withPos(`{`, "").withType(0, T[chan string]()),
902 }, {
903 name: jsontest.Name("Maps/ValidKey/Int"),
904 in: map[int64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
905 canonicalize: true,
906 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
907 }, {
908 name: jsontest.Name("Maps/ValidKey/PointerInt"),
909 in: map[*int64]string{addr(int64(math.MinInt64)): "MinInt64", addr(int64(0)): "Zero", addr(int64(math.MaxInt64)): "MaxInt64"},
910 canonicalize: true,
911 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
912 }, {
913 name: jsontest.Name("Maps/DuplicateName/PointerInt"),
914 in: map[*int64]string{addr(int64(0)): "0", addr(int64(0)): "0"},
915 canonicalize: true,
916 want: `{"0":"0"`,
917 wantErr: newDuplicateNameError("", []byte(`"0"`), len64(`{"0":"0",`)),
918 }, {
919 name: jsontest.Name("Maps/ValidKey/NamedInt"),
920 in: map[namedInt64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
921 canonicalize: true,
922 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
923 }, {
924 name: jsontest.Name("Maps/ValidKey/Uint"),
925 in: map[uint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
926 canonicalize: true,
927 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
928 }, {
929 name: jsontest.Name("Maps/ValidKey/NamedUint"),
930 in: map[namedUint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
931 canonicalize: true,
932 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
933 }, {
934 name: jsontest.Name("Maps/ValidKey/Float"),
935 in: map[float64]string{3.14159: "value"},
936 want: `{"3.14159":"value"}`,
937 }, {
938 name: jsontest.Name("Maps/InvalidKey/Float/NaN"),
939 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
940 want: `{`,
941 wantErr: EM(errors.New("unsupported value: NaN")).withPos(`{`, "").withType(0, float64Type),
942 }, {
943 name: jsontest.Name("Maps/ValidKey/Interface"),
944 in: map[any]any{
945 "key": "key",
946 namedInt64(-64): int32(-32),
947 namedUint64(+64): uint32(+32),
948 namedFloat64(64.64): float32(32.32),
949 },
950 canonicalize: true,
951 want: `{"-64":-32,"64":32,"64.64":32.32,"key":"key"}`,
952 }, {
953 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8+AllowDuplicateNames"),
954 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
955 in: map[string]string{"\x80": "", "\x81": ""},
956 want: `{"�":"","�":""}`,
957 }, {
958 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8"),
959 opts: []Options{jsontext.AllowInvalidUTF8(true)},
960 in: map[string]string{"\x80": "", "\x81": ""},
961 want: `{"�":""`,
962 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":"",`)),
963 }, {
964 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
965 opts: []Options{jsontext.AllowDuplicateNames(true)},
966 in: map[nocaseString]string{"hello": "", "HELLO": ""},
967 want: `{"hello":"","hello":""}`,
968 }, {
969 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
970 in: map[nocaseString]string{"hello": "", "HELLO": ""},
971 want: `{"hello":""`,
972 wantErr: EM(newDuplicateNameError("", []byte(`"hello"`), len64(`{"hello":"",`))).withPos(`{"hello":"",`, "").withType(0, T[nocaseString]()),
973 }, {
974 name: jsontest.Name("Maps/DuplicateName/NaNs/Deterministic+AllowDuplicateNames"),
975 opts: []Options{
976 WithMarshalers(
977 MarshalFunc(func(v float64) ([]byte, error) { return []byte(`"NaN"`), nil }),
978 ),
979 Deterministic(true),
980 jsontext.AllowDuplicateNames(true),
981 },
982 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
983 want: `{"NaN":"NaN","NaN":"NaN"}`,
984 }, {
985 name: jsontest.Name("Maps/InvalidValue/Channel"),
986 in: map[string]chan string{
987 "key": nil,
988 },
989 want: `{"key"`,
990 wantErr: EM(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
991 }, {
992 name: jsontest.Name("Maps/String/Deterministic"),
993 opts: []Options{Deterministic(true)},
994 in: map[string]int{"a": 0, "b": 1, "c": 2},
995 want: `{"a":0,"b":1,"c":2}`,
996 }, {
997 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
998 opts: []Options{
999 Deterministic(true),
1000 jsontext.AllowInvalidUTF8(true),
1001 jsontext.AllowDuplicateNames(false),
1002 },
1003 in: map[string]int{"\xff": 0, "\xfe": 1},
1004 want: `{"�":1`,
1005 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1,`)),
1006 }, {
1007 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
1008 opts: []Options{
1009 Deterministic(true),
1010 jsontext.AllowInvalidUTF8(true),
1011 jsontext.AllowDuplicateNames(true),
1012 },
1013 in: map[string]int{"\xff": 0, "\xfe": 1},
1014 want: `{"�":1,"�":0}`,
1015 }, {
1016 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs"),
1017 opts: []Options{
1018 Deterministic(true),
1019 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1020 if p := enc.StackPointer(); p != "/X" {
1021 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1022 }
1023 switch v {
1024 case "a":
1025 return enc.WriteToken(jsontext.String("b"))
1026 case "b":
1027 return enc.WriteToken(jsontext.String("a"))
1028 default:
1029 return fmt.Errorf("invalid value: %q", v)
1030 }
1031 })),
1032 },
1033 in: map[namedString]map[string]int{"X": {"a": -1, "b": 1}},
1034 want: `{"X":{"a":1,"b":-1}}`,
1035 }, {
1036 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+RejectDuplicateNames"),
1037 opts: []Options{
1038 Deterministic(true),
1039 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1040 if p := enc.StackPointer(); p != "/X" {
1041 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1042 }
1043 switch v {
1044 case "a", "b":
1045 return enc.WriteToken(jsontext.String("x"))
1046 default:
1047 return fmt.Errorf("invalid value: %q", v)
1048 }
1049 })),
1050 jsontext.AllowDuplicateNames(false),
1051 },
1052 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1053 want: `{"X":{"x":1`,
1054 wantErr: newDuplicateNameError("/X/x", nil, len64(`{"X":{"x":1,`)),
1055 }, {
1056 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+AllowDuplicateNames"),
1057 opts: []Options{
1058 Deterministic(true),
1059 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1060 if p := enc.StackPointer(); p != "/X" {
1061 return fmt.Errorf("invalid stack pointer: got %s, want /0", p)
1062 }
1063 switch v {
1064 case "a", "b":
1065 return enc.WriteToken(jsontext.String("x"))
1066 default:
1067 return fmt.Errorf("invalid value: %q", v)
1068 }
1069 })),
1070 jsontext.AllowDuplicateNames(true),
1071 },
1072 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1073
1074
1075 want: `{"X":{"x":1,"x":1}}`,
1076 }, {
1077 name: jsontest.Name("Maps/RecursiveMap"),
1078 in: recursiveMap{
1079 "fizz": {
1080 "foo": {},
1081 "bar": nil,
1082 },
1083 "buzz": nil,
1084 },
1085 canonicalize: true,
1086 want: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
1087 }, {
1088 name: jsontest.Name("Maps/CyclicMap"),
1089 in: func() recursiveMap {
1090 m := recursiveMap{"k": nil}
1091 m["k"] = m
1092 return m
1093 }(),
1094 want: strings.Repeat(`{"k":`, startDetectingCyclesAfter) + `{"k"`,
1095 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"k":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/k", startDetectingCyclesAfter+1))).withType(0, T[recursiveMap]()),
1096 }, {
1097 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
1098 opts: []Options{invalidFormatOption},
1099 in: map[string]string{},
1100 want: `{}`,
1101 }, {
1102 name: jsontest.Name("Structs/Empty"),
1103 in: structEmpty{},
1104 want: `{}`,
1105 }, {
1106 name: jsontest.Name("Structs/UnexportedIgnored"),
1107 in: structUnexportedIgnored{ignored: "ignored"},
1108 want: `{}`,
1109 }, {
1110 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
1111 in: structIgnoredUnexportedEmbedded{namedString: "ignored"},
1112 want: `{}`,
1113 }, {
1114 name: jsontest.Name("Structs/WeirdNames"),
1115 in: structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"},
1116 want: `{"":"empty",",":"comma","\"":"quote"}`,
1117 }, {
1118 name: jsontest.Name("Structs/EscapedNames"),
1119 opts: []Options{jsontext.EscapeForHTML(true), jsontext.EscapeForJS(true)},
1120 in: struct {
1121 S string "json:\"'abc<>&\u2028\u2029xyz'\""
1122 M any
1123 I structInlineTextValue
1124 }{
1125 S: "abc<>&\u2028\u2029xyz",
1126 M: map[string]string{"abc<>&\u2028\u2029xyz": "abc<>&\u2028\u2029xyz"},
1127 I: structInlineTextValue{X: jsontext.Value(`{"abc<>&` + "\u2028\u2029" + `xyz":"abc<>&` + "\u2028\u2029" + `xyz"}`)},
1128 },
1129 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"}}`,
1130 }, {
1131 name: jsontest.Name("Structs/NoCase"),
1132 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1133 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1134 }, {
1135 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames"),
1136 opts: []Options{MatchCaseInsensitiveNames(true)},
1137 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1138 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1139 }, {
1140 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
1141 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
1142 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1143 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1144 }, {
1145 name: jsontest.Name("Structs/Normal"),
1146 opts: []Options{jsontext.Multiline(true)},
1147 in: structAll{
1148 Bool: true,
1149 String: "hello",
1150 Bytes: []byte{1, 2, 3},
1151 Int: -64,
1152 Uint: +64,
1153 Float: 3.14159,
1154 Map: map[string]string{"key": "value"},
1155 StructScalars: structScalars{
1156 Bool: true,
1157 String: "hello",
1158 Bytes: []byte{1, 2, 3},
1159 Int: -64,
1160 Uint: +64,
1161 Float: 3.14159,
1162 },
1163 StructMaps: structMaps{
1164 MapBool: map[string]bool{"": true},
1165 MapString: map[string]string{"": "hello"},
1166 MapBytes: map[string][]byte{"": {1, 2, 3}},
1167 MapInt: map[string]int64{"": -64},
1168 MapUint: map[string]uint64{"": +64},
1169 MapFloat: map[string]float64{"": 3.14159},
1170 },
1171 StructSlices: structSlices{
1172 SliceBool: []bool{true},
1173 SliceString: []string{"hello"},
1174 SliceBytes: [][]byte{{1, 2, 3}},
1175 SliceInt: []int64{-64},
1176 SliceUint: []uint64{+64},
1177 SliceFloat: []float64{3.14159},
1178 },
1179 Slice: []string{"fizz", "buzz"},
1180 Array: [1]string{"goodbye"},
1181 Pointer: new(structAll),
1182 Interface: (*structAll)(nil),
1183 },
1184 want: `{
1185 "Bool": true,
1186 "String": "hello",
1187 "Bytes": "AQID",
1188 "Int": -64,
1189 "Uint": 64,
1190 "Float": 3.14159,
1191 "Map": {
1192 "key": "value"
1193 },
1194 "StructScalars": {
1195 "Bool": true,
1196 "String": "hello",
1197 "Bytes": "AQID",
1198 "Int": -64,
1199 "Uint": 64,
1200 "Float": 3.14159
1201 },
1202 "StructMaps": {
1203 "MapBool": {
1204 "": true
1205 },
1206 "MapString": {
1207 "": "hello"
1208 },
1209 "MapBytes": {
1210 "": "AQID"
1211 },
1212 "MapInt": {
1213 "": -64
1214 },
1215 "MapUint": {
1216 "": 64
1217 },
1218 "MapFloat": {
1219 "": 3.14159
1220 }
1221 },
1222 "StructSlices": {
1223 "SliceBool": [
1224 true
1225 ],
1226 "SliceString": [
1227 "hello"
1228 ],
1229 "SliceBytes": [
1230 "AQID"
1231 ],
1232 "SliceInt": [
1233 -64
1234 ],
1235 "SliceUint": [
1236 64
1237 ],
1238 "SliceFloat": [
1239 3.14159
1240 ]
1241 },
1242 "Slice": [
1243 "fizz",
1244 "buzz"
1245 ],
1246 "Array": [
1247 "goodbye"
1248 ],
1249 "Pointer": {
1250 "Bool": false,
1251 "String": "",
1252 "Bytes": "",
1253 "Int": 0,
1254 "Uint": 0,
1255 "Float": 0,
1256 "Map": {},
1257 "StructScalars": {
1258 "Bool": false,
1259 "String": "",
1260 "Bytes": "",
1261 "Int": 0,
1262 "Uint": 0,
1263 "Float": 0
1264 },
1265 "StructMaps": {
1266 "MapBool": {},
1267 "MapString": {},
1268 "MapBytes": {},
1269 "MapInt": {},
1270 "MapUint": {},
1271 "MapFloat": {}
1272 },
1273 "StructSlices": {
1274 "SliceBool": [],
1275 "SliceString": [],
1276 "SliceBytes": [],
1277 "SliceInt": [],
1278 "SliceUint": [],
1279 "SliceFloat": []
1280 },
1281 "Slice": [],
1282 "Array": [
1283 ""
1284 ],
1285 "Pointer": null,
1286 "Interface": null
1287 },
1288 "Interface": null
1289 }`,
1290 }, {
1291 name: jsontest.Name("Structs/SpaceAfterColonAndComma"),
1292 opts: []Options{jsontext.SpaceAfterColon(true), jsontext.SpaceAfterComma(true)},
1293 in: structOmitZeroAll{Int: 1, Uint: 1},
1294 want: `{"Int": 1, "Uint": 1}`,
1295 }, {
1296 name: jsontest.Name("Structs/SpaceAfterColon"),
1297 opts: []Options{jsontext.SpaceAfterColon(true)},
1298 in: structOmitZeroAll{Int: 1, Uint: 1},
1299 want: `{"Int": 1,"Uint": 1}`,
1300 }, {
1301 name: jsontest.Name("Structs/SpaceAfterComma"),
1302 opts: []Options{jsontext.SpaceAfterComma(true)},
1303 in: structOmitZeroAll{Int: 1, Uint: 1, Slice: []string{"a", "b"}},
1304 want: `{"Int":1, "Uint":1, "Slice":["a", "b"]}`,
1305 }, {
1306 name: jsontest.Name("Structs/Stringified"),
1307 opts: []Options{jsontext.Multiline(true)},
1308 in: structStringifiedAll{
1309 Bool: true,
1310 String: "hello",
1311 Bytes: []byte{1, 2, 3},
1312 Int: -64,
1313 Uint: +64,
1314 Float: 3.14159,
1315 Map: map[string]string{"key": "value"},
1316 StructScalars: structScalars{
1317 Bool: true,
1318 String: "hello",
1319 Bytes: []byte{1, 2, 3},
1320 Int: -64,
1321 Uint: +64,
1322 Float: 3.14159,
1323 },
1324 StructMaps: structMaps{
1325 MapBool: map[string]bool{"": true},
1326 MapString: map[string]string{"": "hello"},
1327 MapBytes: map[string][]byte{"": {1, 2, 3}},
1328 MapInt: map[string]int64{"": -64},
1329 MapUint: map[string]uint64{"": +64},
1330 MapFloat: map[string]float64{"": 3.14159},
1331 },
1332 StructSlices: structSlices{
1333 SliceBool: []bool{true},
1334 SliceString: []string{"hello"},
1335 SliceBytes: [][]byte{{1, 2, 3}},
1336 SliceInt: []int64{-64},
1337 SliceUint: []uint64{+64},
1338 SliceFloat: []float64{3.14159},
1339 },
1340 Slice: []string{"fizz", "buzz"},
1341 Array: [1]string{"goodbye"},
1342 Pointer: new(structStringifiedAll),
1343 Interface: (*structStringifiedAll)(nil),
1344 },
1345 want: `{
1346 "Bool": true,
1347 "String": "hello",
1348 "Bytes": "AQID",
1349 "Int": "-64",
1350 "Uint": "64",
1351 "Float": "3.14159",
1352 "Map": {
1353 "key": "value"
1354 },
1355 "StructScalars": {
1356 "Bool": true,
1357 "String": "hello",
1358 "Bytes": "AQID",
1359 "Int": "-64",
1360 "Uint": "64",
1361 "Float": "3.14159"
1362 },
1363 "StructMaps": {
1364 "MapBool": {
1365 "": true
1366 },
1367 "MapString": {
1368 "": "hello"
1369 },
1370 "MapBytes": {
1371 "": "AQID"
1372 },
1373 "MapInt": {
1374 "": "-64"
1375 },
1376 "MapUint": {
1377 "": "64"
1378 },
1379 "MapFloat": {
1380 "": "3.14159"
1381 }
1382 },
1383 "StructSlices": {
1384 "SliceBool": [
1385 true
1386 ],
1387 "SliceString": [
1388 "hello"
1389 ],
1390 "SliceBytes": [
1391 "AQID"
1392 ],
1393 "SliceInt": [
1394 "-64"
1395 ],
1396 "SliceUint": [
1397 "64"
1398 ],
1399 "SliceFloat": [
1400 "3.14159"
1401 ]
1402 },
1403 "Slice": [
1404 "fizz",
1405 "buzz"
1406 ],
1407 "Array": [
1408 "goodbye"
1409 ],
1410 "Pointer": {
1411 "Bool": false,
1412 "String": "",
1413 "Bytes": "",
1414 "Int": "0",
1415 "Uint": "0",
1416 "Float": "0",
1417 "Map": {},
1418 "StructScalars": {
1419 "Bool": false,
1420 "String": "",
1421 "Bytes": "",
1422 "Int": "0",
1423 "Uint": "0",
1424 "Float": "0"
1425 },
1426 "StructMaps": {
1427 "MapBool": {},
1428 "MapString": {},
1429 "MapBytes": {},
1430 "MapInt": {},
1431 "MapUint": {},
1432 "MapFloat": {}
1433 },
1434 "StructSlices": {
1435 "SliceBool": [],
1436 "SliceString": [],
1437 "SliceBytes": [],
1438 "SliceInt": [],
1439 "SliceUint": [],
1440 "SliceFloat": []
1441 },
1442 "Slice": [],
1443 "Array": [
1444 ""
1445 ],
1446 "Pointer": null,
1447 "Interface": null
1448 },
1449 "Interface": null
1450 }`,
1451 }, {
1452 name: jsontest.Name("Structs/LegacyStringified"),
1453 opts: []Options{jsontext.Multiline(true), jsonflags.StringifyWithLegacySemantics | 1},
1454 in: structStringifiedAll{
1455 Bool: true,
1456 String: "hello",
1457 Bytes: []byte{1, 2, 3},
1458 Int: -64,
1459 Uint: +64,
1460 Float: 3.14159,
1461 Map: map[string]string{"key": "value"},
1462 StructScalars: structScalars{
1463 Bool: true,
1464 String: "hello",
1465 Bytes: []byte{1, 2, 3},
1466 Int: -64,
1467 Uint: +64,
1468 Float: 3.14159,
1469 },
1470 StructMaps: structMaps{
1471 MapBool: map[string]bool{"": true},
1472 MapString: map[string]string{"": "hello"},
1473 MapBytes: map[string][]byte{"": {1, 2, 3}},
1474 MapInt: map[string]int64{"": -64},
1475 MapUint: map[string]uint64{"": +64},
1476 MapFloat: map[string]float64{"": 3.14159},
1477 },
1478 StructSlices: structSlices{
1479 SliceBool: []bool{true},
1480 SliceString: []string{"hello"},
1481 SliceBytes: [][]byte{{1, 2, 3}},
1482 SliceInt: []int64{-64},
1483 SliceUint: []uint64{+64},
1484 SliceFloat: []float64{3.14159},
1485 },
1486 Slice: []string{"fizz", "buzz"},
1487 Array: [1]string{"goodbye"},
1488 Pointer: new(structStringifiedAll),
1489 Interface: (*structStringifiedAll)(nil),
1490 },
1491 want: `{
1492 "Bool": "true",
1493 "String": "\"hello\"",
1494 "Bytes": "AQID",
1495 "Int": "-64",
1496 "Uint": "64",
1497 "Float": "3.14159",
1498 "Map": {
1499 "key": "value"
1500 },
1501 "StructScalars": {
1502 "Bool": true,
1503 "String": "hello",
1504 "Bytes": "AQID",
1505 "Int": -64,
1506 "Uint": 64,
1507 "Float": 3.14159
1508 },
1509 "StructMaps": {
1510 "MapBool": {
1511 "": true
1512 },
1513 "MapString": {
1514 "": "hello"
1515 },
1516 "MapBytes": {
1517 "": "AQID"
1518 },
1519 "MapInt": {
1520 "": -64
1521 },
1522 "MapUint": {
1523 "": 64
1524 },
1525 "MapFloat": {
1526 "": 3.14159
1527 }
1528 },
1529 "StructSlices": {
1530 "SliceBool": [
1531 true
1532 ],
1533 "SliceString": [
1534 "hello"
1535 ],
1536 "SliceBytes": [
1537 "AQID"
1538 ],
1539 "SliceInt": [
1540 -64
1541 ],
1542 "SliceUint": [
1543 64
1544 ],
1545 "SliceFloat": [
1546 3.14159
1547 ]
1548 },
1549 "Slice": [
1550 "fizz",
1551 "buzz"
1552 ],
1553 "Array": [
1554 "goodbye"
1555 ],
1556 "Pointer": {
1557 "Bool": "false",
1558 "String": "\"\"",
1559 "Bytes": "",
1560 "Int": "0",
1561 "Uint": "0",
1562 "Float": "0",
1563 "Map": {},
1564 "StructScalars": {
1565 "Bool": false,
1566 "String": "",
1567 "Bytes": "",
1568 "Int": 0,
1569 "Uint": 0,
1570 "Float": 0
1571 },
1572 "StructMaps": {
1573 "MapBool": {},
1574 "MapString": {},
1575 "MapBytes": {},
1576 "MapInt": {},
1577 "MapUint": {},
1578 "MapFloat": {}
1579 },
1580 "StructSlices": {
1581 "SliceBool": [],
1582 "SliceString": [],
1583 "SliceBytes": [],
1584 "SliceInt": [],
1585 "SliceUint": [],
1586 "SliceFloat": []
1587 },
1588 "Slice": [],
1589 "Array": [
1590 ""
1591 ],
1592 "Pointer": null,
1593 "Interface": null
1594 },
1595 "Interface": null
1596 }`,
1597 }, {
1598 name: jsontest.Name("Structs/OmitZero/Zero"),
1599 in: structOmitZeroAll{},
1600 want: `{}`,
1601 }, {
1602 name: jsontest.Name("Structs/OmitZeroOption/Zero"),
1603 opts: []Options{OmitZeroStructFields(true)},
1604 in: structAll{},
1605 want: `{}`,
1606 }, {
1607 name: jsontest.Name("Structs/OmitZero/NonZero"),
1608 opts: []Options{jsontext.Multiline(true)},
1609 in: structOmitZeroAll{
1610 Bool: true,
1611 String: " ",
1612 Bytes: []byte{},
1613 Int: 1,
1614 Uint: 1,
1615 Float: math.SmallestNonzeroFloat64,
1616 Map: map[string]string{},
1617 StructScalars: structScalars{unexported: true},
1618 StructSlices: structSlices{Ignored: true},
1619 StructMaps: structMaps{MapBool: map[string]bool{}},
1620 Slice: []string{},
1621 Array: [1]string{" "},
1622 Pointer: new(structOmitZeroAll),
1623 Interface: (*structOmitZeroAll)(nil),
1624 },
1625 want: `{
1626 "Bool": true,
1627 "String": " ",
1628 "Bytes": "",
1629 "Int": 1,
1630 "Uint": 1,
1631 "Float": 5e-324,
1632 "Map": {},
1633 "StructScalars": {
1634 "Bool": false,
1635 "String": "",
1636 "Bytes": "",
1637 "Int": 0,
1638 "Uint": 0,
1639 "Float": 0
1640 },
1641 "StructMaps": {
1642 "MapBool": {},
1643 "MapString": {},
1644 "MapBytes": {},
1645 "MapInt": {},
1646 "MapUint": {},
1647 "MapFloat": {}
1648 },
1649 "StructSlices": {
1650 "SliceBool": [],
1651 "SliceString": [],
1652 "SliceBytes": [],
1653 "SliceInt": [],
1654 "SliceUint": [],
1655 "SliceFloat": []
1656 },
1657 "Slice": [],
1658 "Array": [
1659 " "
1660 ],
1661 "Pointer": {},
1662 "Interface": null
1663 }`,
1664 }, {
1665 name: jsontest.Name("Structs/OmitZeroOption/NonZero"),
1666 opts: []Options{OmitZeroStructFields(true), jsontext.Multiline(true)},
1667 in: structAll{
1668 Bool: true,
1669 String: " ",
1670 Bytes: []byte{},
1671 Int: 1,
1672 Uint: 1,
1673 Float: math.SmallestNonzeroFloat64,
1674 Map: map[string]string{},
1675 StructScalars: structScalars{unexported: true},
1676 StructSlices: structSlices{Ignored: true},
1677 StructMaps: structMaps{MapBool: map[string]bool{}},
1678 Slice: []string{},
1679 Array: [1]string{" "},
1680 Pointer: new(structAll),
1681 Interface: (*structAll)(nil),
1682 },
1683 want: `{
1684 "Bool": true,
1685 "String": " ",
1686 "Bytes": "",
1687 "Int": 1,
1688 "Uint": 1,
1689 "Float": 5e-324,
1690 "Map": {},
1691 "StructScalars": {},
1692 "StructMaps": {
1693 "MapBool": {}
1694 },
1695 "StructSlices": {},
1696 "Slice": [],
1697 "Array": [
1698 " "
1699 ],
1700 "Pointer": {},
1701 "Interface": null
1702 }`,
1703 }, {
1704 name: jsontest.Name("Structs/OmitZeroMethod/Zero"),
1705 in: structOmitZeroMethodAll{},
1706 want: `{"ValueNeverZero":"","PointerNeverZero":""}`,
1707 }, {
1708 name: jsontest.Name("Structs/OmitZeroMethod/NonZero"),
1709 opts: []Options{jsontext.Multiline(true)},
1710 in: structOmitZeroMethodAll{
1711 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1712 ValueNeverZero: valueNeverZero("nonzero"),
1713 PointerAlwaysZero: pointerAlwaysZero("nonzero"),
1714 PointerNeverZero: pointerNeverZero("nonzero"),
1715 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1716 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1717 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1718 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1719 PointerPointerValueAlwaysZero: addr(addr(valueAlwaysZero("nonzero"))),
1720 PointerPointerValueNeverZero: addr(addr(valueNeverZero("nonzero"))),
1721 PointerPointerPointerAlwaysZero: addr(addr(pointerAlwaysZero("nonzero"))),
1722 PointerPointerPointerNeverZero: addr(addr(pointerNeverZero("nonzero"))),
1723 },
1724 want: `{
1725 "ValueNeverZero": "nonzero",
1726 "PointerNeverZero": "nonzero",
1727 "PointerValueNeverZero": "nonzero",
1728 "PointerPointerNeverZero": "nonzero",
1729 "PointerPointerValueAlwaysZero": "nonzero",
1730 "PointerPointerValueNeverZero": "nonzero",
1731 "PointerPointerPointerAlwaysZero": "nonzero",
1732 "PointerPointerPointerNeverZero": "nonzero"
1733 }`,
1734 }, {
1735 name: jsontest.Name("Structs/OmitZeroMethod/Interface/Zero"),
1736 opts: []Options{jsontext.Multiline(true)},
1737 in: structOmitZeroMethodInterfaceAll{},
1738 want: `{}`,
1739 }, {
1740 name: jsontest.Name("Structs/OmitZeroMethod/Interface/PartialZero"),
1741 opts: []Options{jsontext.Multiline(true)},
1742 in: structOmitZeroMethodInterfaceAll{
1743 ValueAlwaysZero: valueAlwaysZero(""),
1744 ValueNeverZero: valueNeverZero(""),
1745 PointerValueAlwaysZero: (*valueAlwaysZero)(nil),
1746 PointerValueNeverZero: (*valueNeverZero)(nil),
1747 PointerPointerAlwaysZero: (*pointerAlwaysZero)(nil),
1748 PointerPointerNeverZero: (*pointerNeverZero)(nil),
1749 },
1750 want: `{
1751 "ValueNeverZero": ""
1752 }`,
1753 }, {
1754 name: jsontest.Name("Structs/OmitZeroMethod/Interface/NonZero"),
1755 opts: []Options{jsontext.Multiline(true)},
1756 in: structOmitZeroMethodInterfaceAll{
1757 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1758 ValueNeverZero: valueNeverZero("nonzero"),
1759 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1760 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1761 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1762 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1763 },
1764 want: `{
1765 "ValueNeverZero": "nonzero",
1766 "PointerValueNeverZero": "nonzero",
1767 "PointerPointerNeverZero": "nonzero"
1768 }`,
1769 }, {
1770 name: jsontest.Name("Structs/OmitEmpty/Zero"),
1771 opts: []Options{jsontext.Multiline(true)},
1772 in: structOmitEmptyAll{},
1773 want: `{
1774 "Bool": false,
1775 "StringNonEmpty": "value",
1776 "BytesNonEmpty": [
1777 "value"
1778 ],
1779 "Float": 0,
1780 "MapNonEmpty": {
1781 "key": "value"
1782 },
1783 "SliceNonEmpty": [
1784 "value"
1785 ]
1786 }`,
1787 }, {
1788 name: jsontest.Name("Structs/OmitEmpty/EmptyNonZero"),
1789 opts: []Options{jsontext.Multiline(true)},
1790 in: structOmitEmptyAll{
1791 String: string(""),
1792 StringEmpty: stringMarshalEmpty(""),
1793 StringNonEmpty: stringMarshalNonEmpty(""),
1794 PointerString: addr(string("")),
1795 PointerStringEmpty: addr(stringMarshalEmpty("")),
1796 PointerStringNonEmpty: addr(stringMarshalNonEmpty("")),
1797 Bytes: []byte(""),
1798 BytesEmpty: bytesMarshalEmpty([]byte("")),
1799 BytesNonEmpty: bytesMarshalNonEmpty([]byte("")),
1800 PointerBytes: addr([]byte("")),
1801 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte(""))),
1802 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte(""))),
1803 Map: map[string]string{},
1804 MapEmpty: mapMarshalEmpty{},
1805 MapNonEmpty: mapMarshalNonEmpty{},
1806 PointerMap: addr(map[string]string{}),
1807 PointerMapEmpty: addr(mapMarshalEmpty{}),
1808 PointerMapNonEmpty: addr(mapMarshalNonEmpty{}),
1809 Slice: []string{},
1810 SliceEmpty: sliceMarshalEmpty{},
1811 SliceNonEmpty: sliceMarshalNonEmpty{},
1812 PointerSlice: addr([]string{}),
1813 PointerSliceEmpty: addr(sliceMarshalEmpty{}),
1814 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{}),
1815 Pointer: &structOmitZeroEmptyAll{},
1816 Interface: []string{},
1817 },
1818 want: `{
1819 "Bool": false,
1820 "StringNonEmpty": "value",
1821 "PointerStringNonEmpty": "value",
1822 "BytesNonEmpty": [
1823 "value"
1824 ],
1825 "PointerBytesNonEmpty": [
1826 "value"
1827 ],
1828 "Float": 0,
1829 "MapNonEmpty": {
1830 "key": "value"
1831 },
1832 "PointerMapNonEmpty": {
1833 "key": "value"
1834 },
1835 "SliceNonEmpty": [
1836 "value"
1837 ],
1838 "PointerSliceNonEmpty": [
1839 "value"
1840 ]
1841 }`,
1842 }, {
1843 name: jsontest.Name("Structs/OmitEmpty/NonEmpty"),
1844 opts: []Options{jsontext.Multiline(true)},
1845 in: structOmitEmptyAll{
1846 Bool: true,
1847 PointerBool: addr(true),
1848 String: string("value"),
1849 StringEmpty: stringMarshalEmpty("value"),
1850 StringNonEmpty: stringMarshalNonEmpty("value"),
1851 PointerString: addr(string("value")),
1852 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1853 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1854 Bytes: []byte("value"),
1855 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1856 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1857 PointerBytes: addr([]byte("value")),
1858 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1859 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1860 Float: math.Copysign(0, -1),
1861 PointerFloat: addr(math.Copysign(0, -1)),
1862 Map: map[string]string{"": ""},
1863 MapEmpty: mapMarshalEmpty{"key": "value"},
1864 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1865 PointerMap: addr(map[string]string{"": ""}),
1866 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1867 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1868 Slice: []string{""},
1869 SliceEmpty: sliceMarshalEmpty{"value"},
1870 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1871 PointerSlice: addr([]string{""}),
1872 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1873 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1874 Pointer: &structOmitZeroEmptyAll{Float: math.SmallestNonzeroFloat64},
1875 Interface: []string{""},
1876 },
1877 want: `{
1878 "Bool": true,
1879 "PointerBool": true,
1880 "String": "value",
1881 "StringNonEmpty": "value",
1882 "PointerString": "value",
1883 "PointerStringNonEmpty": "value",
1884 "Bytes": "dmFsdWU=",
1885 "BytesNonEmpty": [
1886 "value"
1887 ],
1888 "PointerBytes": "dmFsdWU=",
1889 "PointerBytesNonEmpty": [
1890 "value"
1891 ],
1892 "Float": -0,
1893 "PointerFloat": -0,
1894 "Map": {
1895 "": ""
1896 },
1897 "MapNonEmpty": {
1898 "key": "value"
1899 },
1900 "PointerMap": {
1901 "": ""
1902 },
1903 "PointerMapNonEmpty": {
1904 "key": "value"
1905 },
1906 "Slice": [
1907 ""
1908 ],
1909 "SliceNonEmpty": [
1910 "value"
1911 ],
1912 "PointerSlice": [
1913 ""
1914 ],
1915 "PointerSliceNonEmpty": [
1916 "value"
1917 ],
1918 "Pointer": {
1919 "Float": 5e-324
1920 },
1921 "Interface": [
1922 ""
1923 ]
1924 }`,
1925 }, {
1926 name: jsontest.Name("Structs/OmitEmpty/Legacy/Zero"),
1927 opts: []Options{jsonflags.OmitEmptyWithLegacySemantics | 1},
1928 in: structOmitEmptyAll{},
1929 want: `{}`,
1930 }, {
1931 name: jsontest.Name("Structs/OmitEmpty/Legacy/NonEmpty"),
1932 opts: []Options{jsontext.Multiline(true), jsonflags.OmitEmptyWithLegacySemantics | 1},
1933 in: structOmitEmptyAll{
1934 Bool: true,
1935 PointerBool: addr(true),
1936 String: string("value"),
1937 StringEmpty: stringMarshalEmpty("value"),
1938 StringNonEmpty: stringMarshalNonEmpty("value"),
1939 PointerString: addr(string("value")),
1940 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1941 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1942 Bytes: []byte("value"),
1943 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1944 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1945 PointerBytes: addr([]byte("value")),
1946 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1947 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1948 Float: math.Copysign(0, -1),
1949 PointerFloat: addr(math.Copysign(0, -1)),
1950 Map: map[string]string{"": ""},
1951 MapEmpty: mapMarshalEmpty{"key": "value"},
1952 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1953 PointerMap: addr(map[string]string{"": ""}),
1954 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1955 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1956 Slice: []string{""},
1957 SliceEmpty: sliceMarshalEmpty{"value"},
1958 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1959 PointerSlice: addr([]string{""}),
1960 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1961 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1962 Pointer: &structOmitZeroEmptyAll{Float: math.Copysign(0, -1)},
1963 Interface: []string{""},
1964 },
1965 want: `{
1966 "Bool": true,
1967 "PointerBool": true,
1968 "String": "value",
1969 "StringEmpty": "",
1970 "StringNonEmpty": "value",
1971 "PointerString": "value",
1972 "PointerStringEmpty": "",
1973 "PointerStringNonEmpty": "value",
1974 "Bytes": "dmFsdWU=",
1975 "BytesEmpty": [],
1976 "BytesNonEmpty": [
1977 "value"
1978 ],
1979 "PointerBytes": "dmFsdWU=",
1980 "PointerBytesEmpty": [],
1981 "PointerBytesNonEmpty": [
1982 "value"
1983 ],
1984 "PointerFloat": -0,
1985 "Map": {
1986 "": ""
1987 },
1988 "MapEmpty": {},
1989 "MapNonEmpty": {
1990 "key": "value"
1991 },
1992 "PointerMap": {
1993 "": ""
1994 },
1995 "PointerMapEmpty": {},
1996 "PointerMapNonEmpty": {
1997 "key": "value"
1998 },
1999 "Slice": [
2000 ""
2001 ],
2002 "SliceEmpty": [],
2003 "SliceNonEmpty": [
2004 "value"
2005 ],
2006 "PointerSlice": [
2007 ""
2008 ],
2009 "PointerSliceEmpty": [],
2010 "PointerSliceNonEmpty": [
2011 "value"
2012 ],
2013 "Pointer": {},
2014 "Interface": [
2015 ""
2016 ]
2017 }`,
2018 }, {
2019 name: jsontest.Name("Structs/OmitEmpty/NonEmptyString"),
2020 in: struct {
2021 X string `json:",omitempty"`
2022 }{`"`},
2023 want: `{"X":"\""}`,
2024 }, {
2025 name: jsontest.Name("Structs/OmitZeroEmpty/Zero"),
2026 in: structOmitZeroEmptyAll{},
2027 want: `{}`,
2028 }, {
2029 name: jsontest.Name("Structs/OmitZeroEmpty/Empty"),
2030 in: structOmitZeroEmptyAll{
2031 Bytes: []byte{},
2032 Map: map[string]string{},
2033 Slice: []string{},
2034 Pointer: &structOmitZeroEmptyAll{},
2035 Interface: []string{},
2036 },
2037 want: `{}`,
2038 }, {
2039 name: jsontest.Name("Structs/OmitEmpty/PathologicalDepth"),
2040 in: func() any {
2041 type X struct {
2042 X *X `json:",omitempty"`
2043 }
2044 var make func(int) *X
2045 make = func(n int) *X {
2046 if n == 0 {
2047 return nil
2048 }
2049 return &X{make(n - 1)}
2050 }
2051 return make(100)
2052 }(),
2053 want: `{}`,
2054 useWriter: true,
2055 }, {
2056 name: jsontest.Name("Structs/OmitEmpty/PathologicalBreadth"),
2057 in: func() any {
2058 var fields []reflect.StructField
2059 for i := range 100 {
2060 fields = append(fields, reflect.StructField{
2061 Name: fmt.Sprintf("X%d", i),
2062 Type: T[stringMarshalEmpty](),
2063 Tag: `json:",omitempty"`,
2064 })
2065 }
2066 return reflect.New(reflect.StructOf(fields)).Interface()
2067 }(),
2068 want: `{}`,
2069 useWriter: true,
2070 }, {
2071 name: jsontest.Name("Structs/OmitEmpty/PathologicalTree"),
2072 in: func() any {
2073 type X struct {
2074 XL, XR *X `json:",omitempty"`
2075 }
2076 var make func(int) *X
2077 make = func(n int) *X {
2078 if n == 0 {
2079 return nil
2080 }
2081 return &X{make(n - 1), make(n - 1)}
2082 }
2083 return make(8)
2084 }(),
2085 want: `{}`,
2086 useWriter: true,
2087 }, {
2088 name: jsontest.Name("Structs/OmitZeroEmpty/NonEmpty"),
2089 in: structOmitZeroEmptyAll{
2090 Bytes: []byte("value"),
2091 Map: map[string]string{"": ""},
2092 Slice: []string{""},
2093 Pointer: &structOmitZeroEmptyAll{Bool: true},
2094 Interface: []string{""},
2095 },
2096 want: `{"Bytes":"dmFsdWU=","Map":{"":""},"Slice":[""],"Pointer":{"Bool":true},"Interface":[""]}`,
2097 }, {
2098 name: jsontest.Name("Structs/Format/Bytes"),
2099 opts: []Options{jsontext.Multiline(true)},
2100 in: structFormatBytes{
2101 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
2102 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2103 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2104 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߿"),
2105 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߿"),
2106 Array: []byte{1, 2, 3, 4},
2107 },
2108 want: `{
2109 "Base16": "0123456789abcdef",
2110 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
2111 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
2112 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
2113 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
2114 "Array": [
2115 1,
2116 2,
2117 3,
2118 4
2119 ]
2120 }`}, {
2121 name: jsontest.Name("Structs/Format/ArrayBytes"),
2122 opts: []Options{jsontext.Multiline(true)},
2123 in: structFormatArrayBytes{
2124 Base16: [4]byte{1, 2, 3, 4},
2125 Base32: [4]byte{1, 2, 3, 4},
2126 Base32Hex: [4]byte{1, 2, 3, 4},
2127 Base64: [4]byte{1, 2, 3, 4},
2128 Base64URL: [4]byte{1, 2, 3, 4},
2129 Array: [4]byte{1, 2, 3, 4},
2130 Default: [4]byte{1, 2, 3, 4},
2131 },
2132 want: `{
2133 "Base16": "01020304",
2134 "Base32": "AEBAGBA=",
2135 "Base32Hex": "0410610=",
2136 "Base64": "AQIDBA==",
2137 "Base64URL": "AQIDBA==",
2138 "Array": [
2139 1,
2140 2,
2141 3,
2142 4
2143 ],
2144 "Default": "AQIDBA=="
2145 }`}, {
2146 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
2147 opts: []Options{jsontext.Multiline(true), jsonflags.FormatByteArrayAsArray | jsonflags.FormatBytesWithLegacySemantics | 1},
2148 in: structFormatArrayBytes{
2149 Base16: [4]byte{1, 2, 3, 4},
2150 Base32: [4]byte{1, 2, 3, 4},
2151 Base32Hex: [4]byte{1, 2, 3, 4},
2152 Base64: [4]byte{1, 2, 3, 4},
2153 Base64URL: [4]byte{1, 2, 3, 4},
2154 Array: [4]byte{1, 2, 3, 4},
2155 Default: [4]byte{1, 2, 3, 4},
2156 },
2157 want: `{
2158 "Base16": "01020304",
2159 "Base32": "AEBAGBA=",
2160 "Base32Hex": "0410610=",
2161 "Base64": "AQIDBA==",
2162 "Base64URL": "AQIDBA==",
2163 "Array": [
2164 1,
2165 2,
2166 3,
2167 4
2168 ],
2169 "Default": [
2170 1,
2171 2,
2172 3,
2173 4
2174 ]
2175 }`}, {
2176 name: jsontest.Name("Structs/Format/Bytes/Array"),
2177 opts: []Options{
2178 WithMarshalers(MarshalFunc(func(in byte) ([]byte, error) {
2179 if in > 3 {
2180 return []byte("true"), nil
2181 } else {
2182 return []byte("false"), nil
2183 }
2184 })),
2185 },
2186 in: struct {
2187 Array []byte `json:",format:array"`
2188 }{
2189 Array: []byte{1, 6, 2, 5, 3, 4},
2190 },
2191 want: `{"Array":[false,true,false,true,false,true]}`,
2192 }, {
2193 name: jsontest.Name("Structs/Format/Floats"),
2194 opts: []Options{jsontext.Multiline(true)},
2195 in: []structFormatFloats{
2196 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
2197 {NonFinite: math.NaN(), PointerNonFinite: addr(math.NaN())},
2198 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
2199 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
2200 },
2201 want: `[
2202 {
2203 "NonFinite": 3.141592653589793,
2204 "PointerNonFinite": 3.141592653589793
2205 },
2206 {
2207 "NonFinite": "NaN",
2208 "PointerNonFinite": "NaN"
2209 },
2210 {
2211 "NonFinite": "-Infinity",
2212 "PointerNonFinite": "-Infinity"
2213 },
2214 {
2215 "NonFinite": "Infinity",
2216 "PointerNonFinite": "Infinity"
2217 }
2218 ]`,
2219 }, {
2220 name: jsontest.Name("Structs/Format/Maps"),
2221 opts: []Options{jsontext.Multiline(true)},
2222 in: []structFormatMaps{{
2223 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2224 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2225 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2226 }, {
2227 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2228 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2229 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2230 }, {
2231 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2232 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2233 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2234 }},
2235 want: `[
2236 {
2237 "EmitNull": null,
2238 "PointerEmitNull": null,
2239 "EmitEmpty": {},
2240 "PointerEmitEmpty": {},
2241 "EmitDefault": {},
2242 "PointerEmitDefault": {}
2243 },
2244 {
2245 "EmitNull": {},
2246 "PointerEmitNull": {},
2247 "EmitEmpty": {},
2248 "PointerEmitEmpty": {},
2249 "EmitDefault": {},
2250 "PointerEmitDefault": {}
2251 },
2252 {
2253 "EmitNull": {
2254 "k": "v"
2255 },
2256 "PointerEmitNull": {
2257 "k": "v"
2258 },
2259 "EmitEmpty": {
2260 "k": "v"
2261 },
2262 "PointerEmitEmpty": {
2263 "k": "v"
2264 },
2265 "EmitDefault": {
2266 "k": "v"
2267 },
2268 "PointerEmitDefault": {
2269 "k": "v"
2270 }
2271 }
2272 ]`,
2273 }, {
2274 name: jsontest.Name("Structs/Format/Maps/FormatNilMapAsNull"),
2275 opts: []Options{
2276 FormatNilMapAsNull(true),
2277 jsontext.Multiline(true),
2278 },
2279 in: []structFormatMaps{{
2280 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2281 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2282 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2283 }, {
2284 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2285 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2286 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2287 }, {
2288 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2289 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2290 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2291 }},
2292 want: `[
2293 {
2294 "EmitNull": null,
2295 "PointerEmitNull": null,
2296 "EmitEmpty": {},
2297 "PointerEmitEmpty": {},
2298 "EmitDefault": null,
2299 "PointerEmitDefault": null
2300 },
2301 {
2302 "EmitNull": {},
2303 "PointerEmitNull": {},
2304 "EmitEmpty": {},
2305 "PointerEmitEmpty": {},
2306 "EmitDefault": {},
2307 "PointerEmitDefault": {}
2308 },
2309 {
2310 "EmitNull": {
2311 "k": "v"
2312 },
2313 "PointerEmitNull": {
2314 "k": "v"
2315 },
2316 "EmitEmpty": {
2317 "k": "v"
2318 },
2319 "PointerEmitEmpty": {
2320 "k": "v"
2321 },
2322 "EmitDefault": {
2323 "k": "v"
2324 },
2325 "PointerEmitDefault": {
2326 "k": "v"
2327 }
2328 }
2329 ]`,
2330 }, {
2331 name: jsontest.Name("Structs/Format/Slices"),
2332 opts: []Options{jsontext.Multiline(true)},
2333 in: []structFormatSlices{{
2334 EmitNull: []string(nil), PointerEmitNull: addr([]string(nil)),
2335 EmitEmpty: []string(nil), PointerEmitEmpty: addr([]string(nil)),
2336 EmitDefault: []string(nil), PointerEmitDefault: addr([]string(nil)),
2337 }, {
2338 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
2339 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
2340 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
2341 }, {
2342 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
2343 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
2344 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
2345 }},
2346 want: `[
2347 {
2348 "EmitNull": null,
2349 "PointerEmitNull": null,
2350 "EmitEmpty": [],
2351 "PointerEmitEmpty": [],
2352 "EmitDefault": [],
2353 "PointerEmitDefault": []
2354 },
2355 {
2356 "EmitNull": [],
2357 "PointerEmitNull": [],
2358 "EmitEmpty": [],
2359 "PointerEmitEmpty": [],
2360 "EmitDefault": [],
2361 "PointerEmitDefault": []
2362 },
2363 {
2364 "EmitNull": [
2365 "v"
2366 ],
2367 "PointerEmitNull": [
2368 "v"
2369 ],
2370 "EmitEmpty": [
2371 "v"
2372 ],
2373 "PointerEmitEmpty": [
2374 "v"
2375 ],
2376 "EmitDefault": [
2377 "v"
2378 ],
2379 "PointerEmitDefault": [
2380 "v"
2381 ]
2382 }
2383 ]`,
2384 }, {
2385 name: jsontest.Name("Structs/Format/Invalid/Bool"),
2386 in: structFormatInvalid{Bool: true},
2387 want: `{"Bool"`,
2388 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, boolType),
2389 }, {
2390 name: jsontest.Name("Structs/Format/Invalid/String"),
2391 in: structFormatInvalid{String: "string"},
2392 want: `{"String"`,
2393 wantErr: EM(errInvalidFormatFlag).withPos(`{"String":`, "/String").withType(0, stringType),
2394 }, {
2395 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
2396 in: structFormatInvalid{Bytes: []byte("bytes")},
2397 want: `{"Bytes"`,
2398 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bytes":`, "/Bytes").withType(0, bytesType),
2399 }, {
2400 name: jsontest.Name("Structs/Format/Invalid/Int"),
2401 in: structFormatInvalid{Int: 1},
2402 want: `{"Int"`,
2403 wantErr: EM(errInvalidFormatFlag).withPos(`{"Int":`, "/Int").withType(0, T[int64]()),
2404 }, {
2405 name: jsontest.Name("Structs/Format/Invalid/Uint"),
2406 in: structFormatInvalid{Uint: 1},
2407 want: `{"Uint"`,
2408 wantErr: EM(errInvalidFormatFlag).withPos(`{"Uint":`, "/Uint").withType(0, T[uint64]()),
2409 }, {
2410 name: jsontest.Name("Structs/Format/Invalid/Float"),
2411 in: structFormatInvalid{Float: 1},
2412 want: `{"Float"`,
2413 wantErr: EM(errInvalidFormatFlag).withPos(`{"Float":`, "/Float").withType(0, T[float64]()),
2414 }, {
2415 name: jsontest.Name("Structs/Format/Invalid/Map"),
2416 in: structFormatInvalid{Map: map[string]string{}},
2417 want: `{"Map"`,
2418 wantErr: EM(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
2419 }, {
2420 name: jsontest.Name("Structs/Format/Invalid/Struct"),
2421 in: structFormatInvalid{Struct: structAll{Bool: true}},
2422 want: `{"Struct"`,
2423 wantErr: EM(errInvalidFormatFlag).withPos(`{"Struct":`, "/Struct").withType(0, T[structAll]()),
2424 }, {
2425 name: jsontest.Name("Structs/Format/Invalid/Slice"),
2426 in: structFormatInvalid{Slice: []string{}},
2427 want: `{"Slice"`,
2428 wantErr: EM(errInvalidFormatFlag).withPos(`{"Slice":`, "/Slice").withType(0, T[[]string]()),
2429 }, {
2430 name: jsontest.Name("Structs/Format/Invalid/Array"),
2431 in: structFormatInvalid{Array: [1]string{"string"}},
2432 want: `{"Array"`,
2433 wantErr: EM(errInvalidFormatFlag).withPos(`{"Array":`, "/Array").withType(0, T[[1]string]()),
2434 }, {
2435 name: jsontest.Name("Structs/Format/Invalid/Interface"),
2436 in: structFormatInvalid{Interface: "anything"},
2437 want: `{"Interface"`,
2438 wantErr: EM(errInvalidFormatFlag).withPos(`{"Interface":`, "/Interface").withType(0, T[any]()),
2439 }, {
2440 name: jsontest.Name("Structs/Inline/Zero"),
2441 in: structInlined{},
2442 want: `{"D":""}`,
2443 }, {
2444 name: jsontest.Name("Structs/Inline/Alloc"),
2445 in: structInlined{
2446 X: structInlinedL1{
2447 X: &structInlinedL2{},
2448 StructEmbed1: StructEmbed1{},
2449 },
2450 StructEmbed2: &StructEmbed2{},
2451 },
2452 want: `{"A":"","B":"","D":"","E":"","F":"","G":""}`,
2453 }, {
2454 name: jsontest.Name("Structs/Inline/NonZero"),
2455 in: structInlined{
2456 X: structInlinedL1{
2457 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
2458 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
2459 },
2460 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
2461 },
2462 want: `{"A":"A1","B":"B1","D":"D2","E":"E3","F":"F3","G":"G3"}`,
2463 }, {
2464 name: jsontest.Name("Structs/Inline/DualCycle"),
2465 in: cyclicA{
2466 B1: cyclicB{F: 1},
2467 B2: cyclicB{F: 2},
2468 },
2469 want: `{}`,
2470 }, {
2471 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nil"),
2472 in: structInlineTextValue{X: jsontext.Value(nil)},
2473 want: `{}`,
2474 }, {
2475 name: jsontest.Name("Structs/InlinedFallback/TextValue/Empty"),
2476 in: structInlineTextValue{X: jsontext.Value("")},
2477 want: `{}`,
2478 }, {
2479 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN1"),
2480 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)},
2481 want: `{"fizz":"buzz"}`,
2482 }, {
2483 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN2"),
2484 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `)},
2485 want: `{"fizz":"buzz","foo":"bar"}`,
2486 }, {
2487 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyWithOthers"),
2488 in: structInlineTextValue{
2489 A: 1,
2490 X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `),
2491 B: 2,
2492 },
2493
2494 want: `{"A":1,"B":2,"fizz":"buzz","foo":"bar"}`,
2495 }, {
2496 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
2497 opts: []Options{jsontext.AllowDuplicateNames(false)},
2498 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2499 want: `{"fizz":"buzz"`,
2500 wantErr: newDuplicateNameError("/fizz", nil, len64(`{"fizz":"buzz"`)),
2501 }, {
2502 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
2503 opts: []Options{jsontext.AllowDuplicateNames(true)},
2504 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2505 want: `{"fizz":"buzz","fizz":"buzz"}`,
2506 }, {
2507 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectInvalidUTF8"),
2508 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2509 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2510 want: `{`,
2511 wantErr: newInvalidUTF8Error(len64(`{"`+"\xde\xad"), ""),
2512 }, {
2513 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowInvalidUTF8"),
2514 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2515 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2516 want: `{"ޭ��":"value"}`,
2517 }, {
2518 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidWhitespace"),
2519 in: structInlineTextValue{X: jsontext.Value("\n\r\t ")},
2520 want: `{`,
2521 wantErr: EM(io.ErrUnexpectedEOF).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2522 }, {
2523 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObject"),
2524 in: structInlineTextValue{X: jsontext.Value(` true `)},
2525 want: `{`,
2526 wantErr: EM(errRawInlinedNotObject).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2527 }, {
2528 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObjectName"),
2529 in: structInlineTextValue{X: jsontext.Value(` { true : false } `)},
2530 want: `{`,
2531 wantErr: EM(newNonStringNameError(len64(" { "), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2532 }, {
2533 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidEndObject"),
2534 in: structInlineTextValue{X: jsontext.Value(` { "name" : false , } `)},
2535 want: `{"name":false`,
2536 wantErr: EM(newInvalidCharacterError(",", "at start of value", len64(` { "name" : false `), "")).withPos(`{"name":false,`, "").withType(0, T[jsontext.Value]()),
2537 }, {
2538 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidDualObject"),
2539 in: structInlineTextValue{X: jsontext.Value(`{}{}`)},
2540 want: `{`,
2541 wantErr: EM(newInvalidCharacterError("{", "after top-level value", len64(`{}`), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2542 }, {
2543 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Nil"),
2544 in: structInlinePointerInlineTextValue{},
2545 want: `{}`,
2546 }, {
2547 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nil"),
2548 in: structInlinePointerTextValue{},
2549 want: `{}`,
2550 }, {
2551 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/NonEmpty"),
2552 in: structInlinePointerTextValue{X: addr(jsontext.Value(` { "fizz" : "buzz" } `))},
2553 want: `{"fizz":"buzz"}`,
2554 }, {
2555 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
2556 in: structInlineInlinePointerTextValue{},
2557 want: `{}`,
2558 }, {
2559 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nil"),
2560 in: structInlineMapStringAny{X: nil},
2561 want: `{}`,
2562 }, {
2563 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Empty"),
2564 in: structInlineMapStringAny{X: make(jsonObject)},
2565 want: `{}`,
2566 }, {
2567 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN1"),
2568 in: structInlineMapStringAny{X: jsonObject{"fizz": nil}},
2569 want: `{"fizz":null}`,
2570 }, {
2571 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN2"),
2572 in: structInlineMapStringAny{X: jsonObject{"fizz": time.Time{}, "buzz": math.Pi}},
2573 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2574 canonicalize: true,
2575 }, {
2576 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyWithOthers"),
2577 in: structInlineMapStringAny{
2578 A: 1,
2579 X: jsonObject{"fizz": nil},
2580 B: 2,
2581 },
2582
2583 want: `{"A":1,"B":2,"fizz":null}`,
2584 }, {
2585 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectInvalidUTF8"),
2586 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2587 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2588 want: `{`,
2589 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, stringType),
2590 }, {
2591 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowInvalidUTF8"),
2592 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2593 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2594 want: `{"ޭ��":null}`,
2595 }, {
2596 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/InvalidValue"),
2597 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2598 in: structInlineMapStringAny{X: jsonObject{"name": make(chan string)}},
2599 want: `{"name"`,
2600 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2601 }, {
2602 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Nil"),
2603 in: structInlinePointerInlineMapStringAny{},
2604 want: `{}`,
2605 }, {
2606 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MarshalFunc"),
2607 opts: []Options{
2608 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2609 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2610 })),
2611 },
2612 in: structInlineMapStringAny{X: jsonObject{"fizz": 3.14159}},
2613 want: `{"fizz":"3.14159"}`,
2614 }, {
2615 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nil"),
2616 in: structInlinePointerMapStringAny{X: nil},
2617 want: `{}`,
2618 }, {
2619 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/NonEmpty"),
2620 in: structInlinePointerMapStringAny{X: addr(jsonObject{"name": "value"})},
2621 want: `{"name":"value"}`,
2622 }, {
2623 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
2624 in: structInlineInlinePointerMapStringAny{},
2625 want: `{}`,
2626 }, {
2627 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
2628 in: structInlineMapStringInt{
2629 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2630 },
2631 want: `{"one":1,"two":2,"zero":0}`,
2632 canonicalize: true,
2633 }, {
2634 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic"),
2635 opts: []Options{Deterministic(true)},
2636 in: structInlineMapStringInt{
2637 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2638 },
2639 want: `{"one":1,"two":2,"zero":0}`,
2640 }, {
2641 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
2642 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
2643 in: structInlineMapStringInt{
2644 X: map[string]int{"\xff": 0, "\xfe": 1},
2645 },
2646 want: `{"�":1`,
2647 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1`)),
2648 }, {
2649 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
2650 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
2651 in: structInlineMapStringInt{
2652 X: map[string]int{"\xff": 0, "\xfe": 1},
2653 },
2654 want: `{"�":1,"�":0}`,
2655 }, {
2656 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
2657 opts: []Options{StringifyNumbers(true)},
2658 in: structInlineMapStringInt{
2659 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2660 },
2661 want: `{"one":"1","two":"2","zero":"0"}`,
2662 canonicalize: true,
2663 }, {
2664 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/MarshalFunc"),
2665 opts: []Options{
2666 WithMarshalers(JoinMarshalers(
2667
2668 MarshalFunc(func(v string) ([]byte, error) {
2669 return []byte(fmt.Sprintf(`"%q"`, strings.ToUpper(v))), nil
2670 }),
2671 MarshalFunc(func(v int) ([]byte, error) {
2672 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2673 }),
2674 )),
2675 },
2676 in: structInlineMapStringInt{
2677 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2678 },
2679 want: `{"one":"1","two":"2","zero":"0"}`,
2680 canonicalize: true,
2681 }, {
2682 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
2683 in: structInlineMapNamedStringInt{
2684 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2685 },
2686 want: `{"one":1,"two":2,"zero":0}`,
2687 canonicalize: true,
2688 }, {
2689 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Deterministic"),
2690 opts: []Options{Deterministic(true)},
2691 in: structInlineMapNamedStringInt{
2692 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2693 },
2694 want: `{"one":1,"two":2,"zero":0}`,
2695 }, {
2696 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Nil"),
2697 in: structInlineMapNamedStringAny{X: nil},
2698 want: `{}`,
2699 }, {
2700 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Empty"),
2701 in: structInlineMapNamedStringAny{X: make(map[namedString]any)},
2702 want: `{}`,
2703 }, {
2704 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN1"),
2705 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": nil}},
2706 want: `{"fizz":null}`,
2707 }, {
2708 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN2"),
2709 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": time.Time{}, "buzz": math.Pi}},
2710 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2711 canonicalize: true,
2712 }, {
2713 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyWithOthers"),
2714 in: structInlineMapNamedStringAny{
2715 A: 1,
2716 X: map[namedString]any{"fizz": nil},
2717 B: 2,
2718 },
2719
2720 want: `{"A":1,"B":2,"fizz":null}`,
2721 }, {
2722 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectInvalidUTF8"),
2723 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2724 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2725 want: `{`,
2726 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, T[namedString]()),
2727 }, {
2728 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowInvalidUTF8"),
2729 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2730 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2731 want: `{"ޭ��":null}`,
2732 }, {
2733 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/InvalidValue"),
2734 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2735 in: structInlineMapNamedStringAny{X: map[namedString]any{"name": make(chan string)}},
2736 want: `{"name"`,
2737 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2738 }, {
2739 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MarshalFunc"),
2740 opts: []Options{
2741 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2742 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2743 })),
2744 },
2745 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": 3.14159}},
2746 want: `{"fizz":"3.14159"}`,
2747 }, {
2748 name: jsontest.Name("Structs/InlinedFallback/DiscardUnknownMembers"),
2749 opts: []Options{DiscardUnknownMembers(true)},
2750 in: structInlineTextValue{
2751 A: 1,
2752 X: jsontext.Value(` { "fizz" : "buzz" } `),
2753 B: 2,
2754 },
2755
2756 want: `{"A":1,"B":2,"fizz":"buzz"}`,
2757 }, {
2758 name: jsontest.Name("Structs/UnknownFallback/DiscardUnknownMembers"),
2759 opts: []Options{DiscardUnknownMembers(true)},
2760 in: structUnknownTextValue{
2761 A: 1,
2762 X: jsontext.Value(` { "fizz" : "buzz" } `),
2763 B: 2,
2764 },
2765 want: `{"A":1,"B":2}`,
2766 }, {
2767 name: jsontest.Name("Structs/UnknownFallback"),
2768 in: structUnknownTextValue{
2769 A: 1,
2770 X: jsontext.Value(` { "fizz" : "buzz" } `),
2771 B: 2,
2772 },
2773 want: `{"A":1,"B":2,"fizz":"buzz"}`,
2774 }, {
2775 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other"),
2776 in: structNoCaseInlineTextValue{
2777 X: jsontext.Value(`{"dupe":"","dupe":""}`),
2778 },
2779 want: `{"dupe":""`,
2780 wantErr: newDuplicateNameError("", []byte(`"dupe"`), len64(`{"dupe":""`)),
2781 }, {
2782 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other/AllowDuplicateNames"),
2783 opts: []Options{jsontext.AllowDuplicateNames(true)},
2784 in: structNoCaseInlineTextValue{
2785 X: jsontext.Value(`{"dupe": "", "dupe": ""}`),
2786 },
2787 want: `{"dupe":"","dupe":""}`,
2788 }, {
2789 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferent"),
2790 in: structNoCaseInlineTextValue{
2791 X: jsontext.Value(`{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""}`),
2792 },
2793 want: `{"Aaa":"","AaA":"","AAa":"","AAA":""}`,
2794 }, {
2795 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict"),
2796 in: structNoCaseInlineTextValue{
2797 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2798 },
2799 want: `{"Aaa":""`,
2800 wantErr: newDuplicateNameError("", []byte(`"Aaa"`), len64(`{"Aaa":""`)),
2801 }, {
2802 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict/AllowDuplicateNames"),
2803 opts: []Options{jsontext.AllowDuplicateNames(true)},
2804 in: structNoCaseInlineTextValue{
2805 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2806 },
2807 want: `{"Aaa":"","Aaa":""}`,
2808 }, {
2809 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict"),
2810 in: structNoCaseInlineTextValue{
2811 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2812 },
2813 want: `{"Aaa":"","AaA":""`,
2814 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"Aaa":"","AaA":""`)),
2815 }, {
2816 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict/AllowDuplicateNames"),
2817 opts: []Options{jsontext.AllowDuplicateNames(true)},
2818 in: structNoCaseInlineTextValue{
2819 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2820 },
2821 want: `{"Aaa":"","AaA":"","aaa":""}`,
2822 }, {
2823 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferentWithField"),
2824 in: structNoCaseInlineTextValue{
2825 AAA: "x",
2826 AaA: "x",
2827 X: jsontext.Value(`{"Aaa": ""}`),
2828 },
2829 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2830 }, {
2831 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflictWithField"),
2832 in: structNoCaseInlineTextValue{
2833 AAA: "x",
2834 AaA: "x",
2835 X: jsontext.Value(`{"AAA": ""}`),
2836 },
2837 want: `{"AAA":"x","AaA":"x"`,
2838 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2839 }, {
2840 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflictWithField"),
2841 in: structNoCaseInlineTextValue{
2842 AAA: "x",
2843 AaA: "x",
2844 X: jsontext.Value(`{"aaa": ""}`),
2845 },
2846 want: `{"AAA":"x","AaA":"x"`,
2847 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2848 }, {
2849 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveDelimiter"),
2850 in: structNoCaseInlineTextValue{
2851 AaA: "x",
2852 X: jsontext.Value(`{"aa_a": ""}`),
2853 },
2854 want: `{"AaA":"x"`,
2855 wantErr: newDuplicateNameError("", []byte(`"aa_a"`), len64(`{"AaA":"x"`)),
2856 }, {
2857 name: jsontest.Name("Structs/DuplicateName/MatchCaseSensitiveDelimiter"),
2858 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
2859 in: structNoCaseInlineTextValue{
2860 AaA: "x",
2861 X: jsontext.Value(`{"aa_a": ""}`),
2862 },
2863 want: `{"AaA":"x","aa_a":""}`,
2864 }, {
2865 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2866 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2867 in: structNoCaseInlineTextValue{
2868 AaA: "x",
2869 X: jsontext.Value(`{"aa_a": ""}`),
2870 },
2871 want: `{"AaA":"x","aa_a":""}`,
2872 }, {
2873 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2874 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2875 in: structNoCaseInlineTextValue{
2876 AA_b: "x",
2877 X: jsontext.Value(`{"aa_b": ""}`),
2878 },
2879 want: `{"AA_b":"x"`,
2880 wantErr: newDuplicateNameError("", []byte(`"aa_b"`), len64(`{"AA_b":"x"`)),
2881 }, {
2882 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferent"),
2883 in: structNoCaseInlineMapStringAny{
2884 X: jsonObject{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""},
2885 },
2886 want: `{"AAA":"","AAa":"","AaA":"","Aaa":""}`,
2887 canonicalize: true,
2888 }, {
2889 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferentWithField"),
2890 in: structNoCaseInlineMapStringAny{
2891 AAA: "x",
2892 AaA: "x",
2893 X: jsonObject{"Aaa": ""},
2894 },
2895 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2896 }, {
2897 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactConflictWithField"),
2898 in: structNoCaseInlineMapStringAny{
2899 AAA: "x",
2900 AaA: "x",
2901 X: jsonObject{"AAA": ""},
2902 },
2903 want: `{"AAA":"x","AaA":"x"`,
2904 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2905 }, {
2906 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/NoCaseConflictWithField"),
2907 in: structNoCaseInlineMapStringAny{
2908 AAA: "x",
2909 AaA: "x",
2910 X: jsonObject{"aaa": ""},
2911 },
2912 want: `{"AAA":"x","AaA":"x"`,
2913 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2914 }, {
2915 name: jsontest.Name("Structs/Invalid/Conflicting"),
2916 in: structConflicting{},
2917 want: ``,
2918 wantErr: EM(errors.New("Go struct fields A and B conflict over JSON object name \"conflict\"")).withType(0, T[structConflicting]()),
2919 }, {
2920 name: jsontest.Name("Structs/Invalid/NoneExported"),
2921 in: structNoneExported{},
2922 want: ``,
2923 wantErr: EM(errNoExportedFields).withType(0, T[structNoneExported]()),
2924 }, {
2925 name: jsontest.Name("Structs/Invalid/MalformedTag"),
2926 in: structMalformedTag{},
2927 want: ``,
2928 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]()),
2929 }, {
2930 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
2931 in: structUnexportedTag{},
2932 want: ``,
2933 wantErr: EM(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType(0, T[structUnexportedTag]()),
2934 }, {
2935 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
2936 in: structExportedEmbedded{"hello"},
2937 want: ``,
2938 wantErr: EM(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structExportedEmbedded]()),
2939 }, {
2940 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
2941 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2942 in: structExportedEmbedded{"hello"},
2943 want: `{"NamedString":"hello"}`,
2944 }, {
2945 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
2946 in: structExportedEmbeddedTag{"hello"},
2947 want: `{"name":"hello"}`,
2948 }, {
2949 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
2950 in: structUnexportedEmbedded{},
2951 want: ``,
2952 wantErr: EM(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structUnexportedEmbedded]()),
2953 }, {
2954 name: jsontest.Name("Structs/Valid/UnexportedEmbedded"),
2955 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2956 in: structUnexportedEmbedded{},
2957 want: `{}`,
2958 }, {
2959 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedTag"),
2960 in: structUnexportedEmbeddedTag{},
2961 wantErr: EM(errors.New("Go struct field namedString is not exported")).withType(0, T[structUnexportedEmbeddedTag]()),
2962 }, {
2963 name: jsontest.Name("Structs/Valid/UnexportedEmbeddedTag"),
2964 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2965 in: structUnexportedEmbeddedTag{},
2966 want: `{}`,
2967 }, {
2968 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedMethodTag"),
2969 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2970 in: structUnexportedEmbeddedMethodTag{},
2971 want: `{}`,
2972 }, {
2973 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/Zero"),
2974 in: structUnexportedEmbeddedStruct{},
2975 want: `{"FizzBuzz":0,"Addr":""}`,
2976 }, {
2977 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/NonZero"),
2978 in: structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2979 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2980 }, {
2981 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
2982 in: structUnexportedEmbeddedStructPointer{},
2983 want: `{"FizzBuzz":0}`,
2984 }, {
2985 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Zero"),
2986 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{}, 0, &structNestedAddr{}},
2987 want: `{"FizzBuzz":0,"Addr":""}`,
2988 }, {
2989 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/NonZero"),
2990 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2991 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2992 }, {
2993 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
2994 opts: []Options{invalidFormatOption},
2995 in: struct{}{},
2996 want: `{}`,
2997 }, {
2998 name: jsontest.Name("Slices/Interface"),
2999 in: []any{
3000 false, true,
3001 "hello", []byte("world"),
3002 int32(-32), namedInt64(-64),
3003 uint32(+32), namedUint64(+64),
3004 float32(32.32), namedFloat64(64.64),
3005 },
3006 want: `[false,true,"hello","d29ybGQ=",-32,-64,32,64,32.32,64.64]`,
3007 }, {
3008 name: jsontest.Name("Slices/Invalid/Channel"),
3009 in: [](chan string){nil},
3010 want: `[`,
3011 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3012 }, {
3013 name: jsontest.Name("Slices/RecursiveSlice"),
3014 in: recursiveSlice{
3015 nil,
3016 {},
3017 {nil},
3018 {nil, {}},
3019 },
3020 want: `[[],[],[[]],[[],[]]]`,
3021 }, {
3022 name: jsontest.Name("Slices/CyclicSlice"),
3023 in: func() recursiveSlice {
3024 s := recursiveSlice{{}}
3025 s[0] = s
3026 return s
3027 }(),
3028 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[`,
3029 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat("[", startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter+1))).withType(0, T[recursiveSlice]()),
3030 }, {
3031 name: jsontest.Name("Slices/NonCyclicSlice"),
3032 in: func() []any {
3033 v := []any{nil, nil}
3034 v[1] = v[:1]
3035 for i := 1000; i > 0; i-- {
3036 v = []any{v}
3037 }
3038 return v
3039 }(),
3040 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[null,[null]]` + strings.Repeat(`]`, startDetectingCyclesAfter),
3041 }, {
3042 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
3043 opts: []Options{invalidFormatOption},
3044 in: []string{"hello", "goodbye"},
3045 want: `["hello","goodbye"]`,
3046 }, {
3047 name: jsontest.Name("Arrays/Empty"),
3048 in: [0]struct{}{},
3049 want: `[]`,
3050 }, {
3051 name: jsontest.Name("Arrays/Bool"),
3052 in: [2]bool{false, true},
3053 want: `[false,true]`,
3054 }, {
3055 name: jsontest.Name("Arrays/String"),
3056 in: [2]string{"hello", "goodbye"},
3057 want: `["hello","goodbye"]`,
3058 }, {
3059 name: jsontest.Name("Arrays/Bytes"),
3060 in: [2][]byte{[]byte("hello"), []byte("goodbye")},
3061 want: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
3062 }, {
3063 name: jsontest.Name("Arrays/Int"),
3064 in: [2]int64{math.MinInt64, math.MaxInt64},
3065 want: `[-9223372036854775808,9223372036854775807]`,
3066 }, {
3067 name: jsontest.Name("Arrays/Uint"),
3068 in: [2]uint64{0, math.MaxUint64},
3069 want: `[0,18446744073709551615]`,
3070 }, {
3071 name: jsontest.Name("Arrays/Float"),
3072 in: [2]float64{-math.MaxFloat64, +math.MaxFloat64},
3073 want: `[-1.7976931348623157e+308,1.7976931348623157e+308]`,
3074 }, {
3075 name: jsontest.Name("Arrays/Invalid/Channel"),
3076 in: new([1]chan string),
3077 want: `[`,
3078 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3079 }, {
3080 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
3081 opts: []Options{invalidFormatOption},
3082 in: [2]string{"hello", "goodbye"},
3083 want: `["hello","goodbye"]`,
3084 }, {
3085 name: jsontest.Name("Pointers/NilL0"),
3086 in: (*int)(nil),
3087 want: `null`,
3088 }, {
3089 name: jsontest.Name("Pointers/NilL1"),
3090 in: new(*int),
3091 want: `null`,
3092 }, {
3093 name: jsontest.Name("Pointers/Bool"),
3094 in: addr(addr(bool(true))),
3095 want: `true`,
3096 }, {
3097 name: jsontest.Name("Pointers/String"),
3098 in: addr(addr(string("string"))),
3099 want: `"string"`,
3100 }, {
3101 name: jsontest.Name("Pointers/Bytes"),
3102 in: addr(addr([]byte("bytes"))),
3103 want: `"Ynl0ZXM="`,
3104 }, {
3105 name: jsontest.Name("Pointers/Int"),
3106 in: addr(addr(int(-100))),
3107 want: `-100`,
3108 }, {
3109 name: jsontest.Name("Pointers/Uint"),
3110 in: addr(addr(uint(100))),
3111 want: `100`,
3112 }, {
3113 name: jsontest.Name("Pointers/Float"),
3114 in: addr(addr(float64(3.14159))),
3115 want: `3.14159`,
3116 }, {
3117 name: jsontest.Name("Pointers/CyclicPointer"),
3118 in: func() *recursivePointer {
3119 p := new(recursivePointer)
3120 p.P = p
3121 return p
3122 }(),
3123 want: strings.Repeat(`{"P":`, startDetectingCyclesAfter) + `{"P"`,
3124 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"P":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/P", startDetectingCyclesAfter+1))).withType(0, T[*recursivePointer]()),
3125 }, {
3126 name: jsontest.Name("Pointers/IgnoreInvalidFormat"),
3127 opts: []Options{invalidFormatOption},
3128 in: addr(addr(bool(true))),
3129 want: `true`,
3130 }, {
3131 name: jsontest.Name("Interfaces/Nil/Empty"),
3132 in: [1]any{nil},
3133 want: `[null]`,
3134 }, {
3135 name: jsontest.Name("Interfaces/Nil/NonEmpty"),
3136 in: [1]io.Reader{nil},
3137 want: `[null]`,
3138 }, {
3139 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
3140 opts: []Options{invalidFormatOption},
3141 in: [1]io.Reader{nil},
3142 want: `[null]`,
3143 }, {
3144 name: jsontest.Name("Interfaces/Any"),
3145 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}, [8]byte{}}},
3146 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3147 }, {
3148 name: jsontest.Name("Interfaces/Any/Named"),
3149 in: struct{ X namedAny }{[]namedAny{nil, false, "", 0.0, map[string]namedAny{}, []namedAny{}, [8]byte{}}},
3150 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3151 }, {
3152 name: jsontest.Name("Interfaces/Any/Stringified"),
3153 opts: []Options{StringifyNumbers(true)},
3154 in: struct{ X any }{0.0},
3155 want: `{"X":"0"}`,
3156 }, {
3157 name: jsontest.Name("Interfaces/Any/MarshalFunc/Any"),
3158 opts: []Options{
3159 WithMarshalers(MarshalFunc(func(v any) ([]byte, error) {
3160 return []byte(`"called"`), nil
3161 })),
3162 },
3163 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3164 want: `"called"`,
3165 }, {
3166 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bool"),
3167 opts: []Options{
3168 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3169 return []byte(`"called"`), nil
3170 })),
3171 },
3172 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3173 want: `{"X":[null,"called","",0,{},[]]}`,
3174 }, {
3175 name: jsontest.Name("Interfaces/Any/MarshalFunc/String"),
3176 opts: []Options{
3177 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3178 return []byte(`"called"`), nil
3179 })),
3180 },
3181 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3182 want: `{"X":[null,false,"called",0,{},[]]}`,
3183 }, {
3184 name: jsontest.Name("Interfaces/Any/MarshalFunc/Float64"),
3185 opts: []Options{
3186 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
3187 return []byte(`"called"`), nil
3188 })),
3189 },
3190 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3191 want: `{"X":[null,false,"","called",{},[]]}`,
3192 }, {
3193 name: jsontest.Name("Interfaces/Any/MarshalFunc/MapStringAny"),
3194 opts: []Options{
3195 WithMarshalers(MarshalFunc(func(v map[string]any) ([]byte, error) {
3196 return []byte(`"called"`), nil
3197 })),
3198 },
3199 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3200 want: `{"X":[null,false,"",0,"called",[]]}`,
3201 }, {
3202 name: jsontest.Name("Interfaces/Any/MarshalFunc/SliceAny"),
3203 opts: []Options{
3204 WithMarshalers(MarshalFunc(func(v []any) ([]byte, error) {
3205 return []byte(`"called"`), nil
3206 })),
3207 },
3208 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3209 want: `{"X":"called"}`,
3210 }, {
3211 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bytes"),
3212 opts: []Options{
3213 WithMarshalers(MarshalFunc(func(v [8]byte) ([]byte, error) {
3214 return []byte(`"called"`), nil
3215 })),
3216 },
3217 in: struct{ X any }{[8]byte{}},
3218 want: `{"X":"called"}`,
3219 }, {
3220 name: jsontest.Name("Interfaces/Any/Float/NaN"),
3221 in: struct{ X any }{math.NaN()},
3222 want: `{"X"`,
3223 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, reflect.TypeFor[float64]()).withPos(`{"X":`, "/X"),
3224 }, {
3225 name: jsontest.Name("Interfaces/Any/Maps/Nil"),
3226 in: struct{ X any }{map[string]any(nil)},
3227 want: `{"X":{}}`,
3228 }, {
3229 name: jsontest.Name("Interfaces/Any/Maps/Nil/FormatNilMapAsNull"),
3230 opts: []Options{FormatNilMapAsNull(true)},
3231 in: struct{ X any }{map[string]any(nil)},
3232 want: `{"X":null}`,
3233 }, {
3234 name: jsontest.Name("Interfaces/Any/Maps/Empty"),
3235 in: struct{ X any }{map[string]any{}},
3236 want: `{"X":{}}`,
3237 }, {
3238 name: jsontest.Name("Interfaces/Any/Maps/Empty/Multiline"),
3239 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3240 in: struct{ X any }{map[string]any{}},
3241 want: "{\n\"X\": {}\n}",
3242 }, {
3243 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
3244 in: struct{ X any }{map[string]any{"fizz": "buzz"}},
3245 want: `{"X":{"fizz":"buzz"}}`,
3246 }, {
3247 name: jsontest.Name("Interfaces/Any/Maps/Deterministic"),
3248 opts: []Options{Deterministic(true)},
3249 in: struct{ X any }{map[string]any{"alpha": "", "bravo": ""}},
3250 want: `{"X":{"alpha":"","bravo":""}}`,
3251 }, {
3252 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
3253 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
3254 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3255 want: `{"X":{"�":""`,
3256 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3257 }, {
3258 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
3259 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3260 in: struct{ X any }{map[string]any{"\xff": "alpha", "\xfe": "bravo"}},
3261 want: `{"X":{"�":"bravo","�":"alpha"}}`,
3262 }, {
3263 name: jsontest.Name("Interfaces/Any/Maps/RejectInvalidUTF8"),
3264 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3265 want: `{"X":{`,
3266 wantErr: newInvalidUTF8Error(len64(`{"X":{`), "/X"),
3267 }, {
3268 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+RejectDuplicateNames"),
3269 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3270 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3271 want: `{"X":{"�":""`,
3272 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3273 }, {
3274 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+AllowDuplicateNames"),
3275 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3276 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3277 want: `{"X":{"�":"","�":""}}`,
3278 }, {
3279 name: jsontest.Name("Interfaces/Any/Maps/Cyclic"),
3280 in: func() any {
3281 m := map[string]any{}
3282 m[""] = m
3283 return struct{ X any }{m}
3284 }(),
3285 want: `{"X"` + strings.Repeat(`:{""`, startDetectingCyclesAfter),
3286 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`{"":`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/", startDetectingCyclesAfter))).withType(0, T[map[string]any]()),
3287 }, {
3288 name: jsontest.Name("Interfaces/Any/Slices/Nil"),
3289 in: struct{ X any }{[]any(nil)},
3290 want: `{"X":[]}`,
3291 }, {
3292 name: jsontest.Name("Interfaces/Any/Slices/Nil/FormatNilSliceAsNull"),
3293 opts: []Options{FormatNilSliceAsNull(true)},
3294 in: struct{ X any }{[]any(nil)},
3295 want: `{"X":null}`,
3296 }, {
3297 name: jsontest.Name("Interfaces/Any/Slices/Empty"),
3298 in: struct{ X any }{[]any{}},
3299 want: `{"X":[]}`,
3300 }, {
3301 name: jsontest.Name("Interfaces/Any/Slices/Empty/Multiline"),
3302 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3303 in: struct{ X any }{[]any{}},
3304 want: "{\n\"X\": []\n}",
3305 }, {
3306 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
3307 in: struct{ X any }{[]any{"fizz", "buzz"}},
3308 want: `{"X":["fizz","buzz"]}`,
3309 }, {
3310 name: jsontest.Name("Interfaces/Any/Slices/Cyclic"),
3311 in: func() any {
3312 s := make([]any, 1)
3313 s[0] = s
3314 return struct{ X any }{s}
3315 }(),
3316 want: `{"X":` + strings.Repeat(`[`, startDetectingCyclesAfter),
3317 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`[`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter))).withType(0, T[[]any]()),
3318 }, {
3319 name: jsontest.Name("Methods/NilPointer"),
3320 in: struct{ X *allMethods }{X: (*allMethods)(nil)},
3321 want: `{"X":null}`,
3322 }, {
3323
3324 name: jsontest.Name("Methods/NilInterface"),
3325 in: struct{ X MarshalerTo }{X: (*allMethods)(nil)},
3326 want: `{"X":null}`,
3327 }, {
3328 name: jsontest.Name("Methods/AllMethods"),
3329 in: struct{ X *allMethods }{X: &allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3330 want: `{"X":"hello"}`,
3331 }, {
3332 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
3333 in: struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3334 want: `{"X":"hello"}`,
3335 }, {
3336 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
3337 in: struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3338 want: `{"X":"hello"}`,
3339 }, {
3340 name: jsontest.Name("Methods/AllMethodsExceptText"),
3341 in: struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3342 want: `{"X":"hello"}`,
3343 }, {
3344 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
3345 in: struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3346 want: `{"X":"hello"}`,
3347 }, {
3348 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
3349 in: struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3350 want: `{"X":"hello"}`,
3351 }, {
3352 name: jsontest.Name("Methods/OnlyMethodText"),
3353 in: struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "MarshalText", value: []byte(`hello`)}}},
3354 want: `{"X":"hello"}`,
3355 }, {
3356 name: jsontest.Name("Methods/IP"),
3357 in: net.IPv4(192, 168, 0, 100),
3358 want: `"192.168.0.100"`,
3359 }, {
3360 name: jsontest.Name("Methods/NetIP"),
3361 in: struct {
3362 Addr netip.Addr
3363 AddrPort netip.AddrPort
3364 Prefix netip.Prefix
3365 }{
3366 Addr: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
3367 AddrPort: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 1234),
3368 Prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
3369 },
3370 want: `{"Addr":"1.2.3.4","AddrPort":"1.2.3.4:1234","Prefix":"1.2.3.4/24"}`,
3371 }, {
3372
3373 name: jsontest.Name("Methods/Anonymous"),
3374 in: struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3375 want: `{"X":"hello"}`,
3376 }, {
3377
3378 name: jsontest.Name("Methods/Addressable"),
3379 in: struct {
3380 V allMethods
3381 M map[string]allMethods
3382 I any
3383 }{
3384 V: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3385 M: map[string]allMethods{"K": {method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3386 I: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3387 },
3388 want: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
3389 }, {
3390
3391 name: jsontest.Name("Methods/MapKey/JSONv2"),
3392 in: map[structMethodJSONv2]string{{"k1"}: "v1", {"k2"}: "v2"},
3393 want: `{"k1":"v1","k2":"v2"}`,
3394 canonicalize: true,
3395 }, {
3396
3397 name: jsontest.Name("Methods/MapKey/JSONv1"),
3398 in: map[structMethodJSONv1]string{{"k1"}: "v1", {"k2"}: "v2"},
3399 want: `{"k1":"v1","k2":"v2"}`,
3400 canonicalize: true,
3401 }, {
3402 name: jsontest.Name("Methods/MapKey/Text"),
3403 in: map[structMethodText]string{{"k1"}: "v1", {"k2"}: "v2"},
3404 want: `{"k1":"v1","k2":"v2"}`,
3405 canonicalize: true,
3406 }, {
3407 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
3408 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3409 return errSomeError
3410 }),
3411 wantErr: EM(errSomeError).withType(0, T[marshalJSONv2Func]()),
3412 }, {
3413 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
3414 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3415 return nil
3416 }),
3417 wantErr: EM(errNonSingularValue).withType(0, T[marshalJSONv2Func]()),
3418 }, {
3419 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
3420 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3421 enc.WriteToken(jsontext.Null)
3422 enc.WriteToken(jsontext.Null)
3423 return nil
3424 }),
3425 want: `nullnull`,
3426 wantErr: EM(errNonSingularValue).withPos(`nullnull`, "").withType(0, T[marshalJSONv2Func]()),
3427 }, {
3428 name: jsontest.Name("Methods/Invalid/JSONv2/SkipFunc"),
3429 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3430 return SkipFunc
3431 }),
3432 wantErr: EM(errors.New("marshal method cannot be skipped")).withType(0, T[marshalJSONv2Func]()),
3433 }, {
3434 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
3435 in: marshalJSONv1Func(func() ([]byte, error) {
3436 return nil, errSomeError
3437 }),
3438 wantErr: EM(errSomeError).withType(0, T[marshalJSONv1Func]()),
3439 }, {
3440 name: jsontest.Name("Methods/Invalid/JSONv1/Syntax"),
3441 in: marshalJSONv1Func(func() ([]byte, error) {
3442 return []byte("invalid"), nil
3443 }),
3444 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[marshalJSONv1Func]()),
3445 }, {
3446 name: jsontest.Name("Methods/Invalid/JSONv1/SkipFunc"),
3447 in: marshalJSONv1Func(func() ([]byte, error) {
3448 return nil, SkipFunc
3449 }),
3450 wantErr: EM(errors.New("marshal method cannot be skipped")).withType(0, T[marshalJSONv1Func]()),
3451 }, {
3452 name: jsontest.Name("Methods/AppendText"),
3453 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), nil }),
3454 want: `"hello"`,
3455 }, {
3456 name: jsontest.Name("Methods/AppendText/Error"),
3457 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), errSomeError }),
3458 wantErr: EM(errSomeError).withType(0, T[appendTextFunc]()),
3459 }, {
3460 name: jsontest.Name("Methods/AppendText/NeedEscape"),
3461 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, `"`...), nil }),
3462 want: `"\""`,
3463 }, {
3464 name: jsontest.Name("Methods/AppendText/RejectInvalidUTF8"),
3465 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3466 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[appendTextFunc]()),
3467 }, {
3468 name: jsontest.Name("Methods/AppendText/AllowInvalidUTF8"),
3469 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3470 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3471 want: "\"\xde\xad\ufffd\ufffd\"",
3472 }, {
3473 name: jsontest.Name("Methods/Invalid/Text/Error"),
3474 in: marshalTextFunc(func() ([]byte, error) {
3475 return nil, errSomeError
3476 }),
3477 wantErr: EM(errSomeError).withType(0, T[marshalTextFunc]()),
3478 }, {
3479 name: jsontest.Name("Methods/Text/RejectInvalidUTF8"),
3480 in: marshalTextFunc(func() ([]byte, error) {
3481 return []byte("\xde\xad\xbe\xef"), nil
3482 }),
3483 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[marshalTextFunc]()),
3484 }, {
3485 name: jsontest.Name("Methods/Text/AllowInvalidUTF8"),
3486 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3487 in: marshalTextFunc(func() ([]byte, error) {
3488 return []byte("\xde\xad\xbe\xef"), nil
3489 }),
3490 want: "\"\xde\xad\ufffd\ufffd\"",
3491 }, {
3492 name: jsontest.Name("Methods/Invalid/Text/SkipFunc"),
3493 in: marshalTextFunc(func() ([]byte, error) {
3494 return nil, SkipFunc
3495 }),
3496 wantErr: EM(wrapSkipFunc(SkipFunc, "marshal method")).withType(0, T[marshalTextFunc]()),
3497 }, {
3498 name: jsontest.Name("Methods/Invalid/MapKey/JSONv2/Syntax"),
3499 in: map[any]string{
3500 addr(marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3501 return enc.WriteToken(jsontext.Null)
3502 })): "invalid",
3503 },
3504 want: `{`,
3505 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv2Func]()),
3506 }, {
3507 name: jsontest.Name("Methods/Invalid/MapKey/JSONv1/Syntax"),
3508 in: map[any]string{
3509 addr(marshalJSONv1Func(func() ([]byte, error) {
3510 return []byte(`null`), nil
3511 })): "invalid",
3512 },
3513 want: `{`,
3514 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv1Func]()),
3515 }, {
3516 name: jsontest.Name("Functions/Bool/V1"),
3517 opts: []Options{
3518 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3519 return []byte(`"called"`), nil
3520 })),
3521 },
3522 in: true,
3523 want: `"called"`,
3524 }, {
3525 name: jsontest.Name("Functions/Bool/Empty"),
3526 opts: []Options{WithMarshalers(nil)},
3527 in: true,
3528 want: `true`,
3529 }, {
3530 name: jsontest.Name("Functions/NamedBool/V1/NoMatch"),
3531 opts: []Options{
3532 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3533 return nil, errMustNotCall
3534 })),
3535 },
3536 in: true,
3537 want: `true`,
3538 }, {
3539 name: jsontest.Name("Functions/NamedBool/V1/Match"),
3540 opts: []Options{
3541 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3542 return []byte(`"called"`), nil
3543 })),
3544 },
3545 in: namedBool(true),
3546 want: `"called"`,
3547 }, {
3548 name: jsontest.Name("Functions/PointerBool/V1/Match"),
3549 opts: []Options{
3550 WithMarshalers(MarshalFunc(func(v *bool) ([]byte, error) {
3551 _ = *v
3552 return []byte(`"called"`), nil
3553 })),
3554 },
3555 in: true,
3556 want: `"called"`,
3557 }, {
3558 name: jsontest.Name("Functions/Bool/V2"),
3559 opts: []Options{
3560 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3561 return enc.WriteToken(jsontext.String("called"))
3562 })),
3563 },
3564 in: true,
3565 want: `"called"`,
3566 }, {
3567 name: jsontest.Name("Functions/NamedBool/V2/NoMatch"),
3568 opts: []Options{
3569 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3570 return errMustNotCall
3571 })),
3572 },
3573 in: true,
3574 want: `true`,
3575 }, {
3576 name: jsontest.Name("Functions/NamedBool/V2/Match"),
3577 opts: []Options{
3578 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3579 return enc.WriteToken(jsontext.String("called"))
3580 })),
3581 },
3582 in: namedBool(true),
3583 want: `"called"`,
3584 }, {
3585 name: jsontest.Name("Functions/PointerBool/V2/Match"),
3586 opts: []Options{
3587 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3588 _ = *v
3589 return enc.WriteToken(jsontext.String("called"))
3590 })),
3591 },
3592 in: true,
3593 want: `"called"`,
3594 }, {
3595 name: jsontest.Name("Functions/Bool/Empty1/NoMatch"),
3596 opts: []Options{
3597 WithMarshalers(new(Marshalers)),
3598 },
3599 in: true,
3600 want: `true`,
3601 }, {
3602 name: jsontest.Name("Functions/Bool/Empty2/NoMatch"),
3603 opts: []Options{
3604 WithMarshalers(JoinMarshalers()),
3605 },
3606 in: true,
3607 want: `true`,
3608 }, {
3609 name: jsontest.Name("Functions/Bool/V1/DirectError"),
3610 opts: []Options{
3611 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3612 return nil, errSomeError
3613 })),
3614 },
3615 in: true,
3616 wantErr: EM(errSomeError).withType(0, T[bool]()),
3617 }, {
3618 name: jsontest.Name("Functions/Bool/V1/SkipError"),
3619 opts: []Options{
3620 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3621 return nil, SkipFunc
3622 })),
3623 },
3624 in: true,
3625 wantErr: EM(wrapSkipFunc(SkipFunc, "marshal function of type func(T) ([]byte, error)")).withType(0, T[bool]()),
3626 }, {
3627 name: jsontest.Name("Functions/Bool/V1/InvalidValue"),
3628 opts: []Options{
3629 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3630 return []byte("invalid"), nil
3631 })),
3632 },
3633 in: true,
3634 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[bool]()),
3635 }, {
3636 name: jsontest.Name("Functions/Bool/V2/DirectError"),
3637 opts: []Options{
3638 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3639 return errSomeError
3640 })),
3641 },
3642 in: true,
3643 wantErr: EM(errSomeError).withType(0, T[bool]()),
3644 }, {
3645 name: jsontest.Name("Functions/Bool/V2/TooFew"),
3646 opts: []Options{
3647 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3648 return nil
3649 })),
3650 },
3651 in: true,
3652 wantErr: EM(errNonSingularValue).withType(0, T[bool]()),
3653 }, {
3654 name: jsontest.Name("Functions/Bool/V2/TooMany"),
3655 opts: []Options{
3656 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3657 enc.WriteValue([]byte(`"hello"`))
3658 enc.WriteValue([]byte(`"world"`))
3659 return nil
3660 })),
3661 },
3662 in: true,
3663 want: `"hello""world"`,
3664 wantErr: EM(errNonSingularValue).withPos(`"hello""world"`, "").withType(0, T[bool]()),
3665 }, {
3666 name: jsontest.Name("Functions/Bool/V2/Skipped"),
3667 opts: []Options{
3668 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3669 return SkipFunc
3670 })),
3671 },
3672 in: true,
3673 want: `true`,
3674 }, {
3675 name: jsontest.Name("Functions/Bool/V2/ProcessBeforeSkip"),
3676 opts: []Options{
3677 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3678 enc.WriteValue([]byte(`"hello"`))
3679 return SkipFunc
3680 })),
3681 },
3682 in: true,
3683 want: `"hello"`,
3684 wantErr: EM(errSkipMutation).withPos(`"hello"`, "").withType(0, T[bool]()),
3685 }, {
3686 name: jsontest.Name("Functions/Bool/V2/WrappedSkipError"),
3687 opts: []Options{
3688 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3689 return fmt.Errorf("wrap: %w", SkipFunc)
3690 })),
3691 },
3692 in: true,
3693 wantErr: EM(fmt.Errorf("wrap: %w", SkipFunc)).withType(0, T[bool]()),
3694 }, {
3695 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
3696 opts: []Options{
3697 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3698 return []byte(`"called"`), nil
3699 })),
3700 },
3701 in: map[nocaseString]string{"hello": "world"},
3702 want: `{"called":"world"}`,
3703 }, {
3704 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V1"),
3705 opts: []Options{
3706 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3707 _ = *v
3708 return []byte(`"called"`), nil
3709 })),
3710 },
3711 in: map[nocaseString]string{"hello": "world"},
3712 want: `{"called":"world"}`,
3713 }, {
3714 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
3715 opts: []Options{
3716 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3717 _ = *v.(*nocaseString)
3718 return []byte(`"called"`), nil
3719 })),
3720 },
3721 in: map[nocaseString]string{"hello": "world"},
3722 want: `{"called":"world"}`,
3723 }, {
3724 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1/InvalidValue"),
3725 opts: []Options{
3726 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3727 return []byte(`null`), nil
3728 })),
3729 },
3730 in: map[nocaseString]string{"hello": "world"},
3731 want: `{`,
3732 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3733 }, {
3734 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidKind"),
3735 opts: []Options{
3736 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3737 return []byte(`null`), nil
3738 })),
3739 },
3740 in: map[nocaseString]string{"hello": "world"},
3741 want: `{`,
3742 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3743 }, {
3744 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
3745 opts: []Options{
3746 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3747 return []byte(`"name"`), nil
3748 })),
3749 },
3750 in: map[string]string{"name1": "value", "name2": "value"},
3751 want: `{"name":"name"`,
3752 wantErr: EM(newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"name",`))).
3753 withPos(`{"name":"name",`, "").withType(0, T[string]()),
3754 }, {
3755 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
3756 opts: []Options{
3757 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3758 return enc.WriteValue([]byte(`"called"`))
3759 })),
3760 },
3761 in: map[nocaseString]string{"hello": "world"},
3762 want: `{"called":"world"}`,
3763 }, {
3764 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V2"),
3765 opts: []Options{
3766 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3767 _ = *v
3768 return enc.WriteValue([]byte(`"called"`))
3769 })),
3770 },
3771 in: map[nocaseString]string{"hello": "world"},
3772 want: `{"called":"world"}`,
3773 }, {
3774 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
3775 opts: []Options{
3776 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3777 _ = *v.(*nocaseString)
3778 return enc.WriteValue([]byte(`"called"`))
3779 })),
3780 },
3781 in: map[nocaseString]string{"hello": "world"},
3782 want: `{"called":"world"}`,
3783 }, {
3784 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidToken"),
3785 opts: []Options{
3786 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3787 return enc.WriteToken(jsontext.Null)
3788 })),
3789 },
3790 in: map[nocaseString]string{"hello": "world"},
3791 want: `{`,
3792 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3793 }, {
3794 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidValue"),
3795 opts: []Options{
3796 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3797 return enc.WriteValue([]byte(`null`))
3798 })),
3799 },
3800 in: map[nocaseString]string{"hello": "world"},
3801 want: `{`,
3802 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3803 }, {
3804 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
3805 opts: []Options{
3806 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3807 return []byte(`"called"`), nil
3808 })),
3809 },
3810 in: map[string]nocaseString{"hello": "world"},
3811 want: `{"hello":"called"}`,
3812 }, {
3813 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V1"),
3814 opts: []Options{
3815 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3816 _ = *v
3817 return []byte(`"called"`), nil
3818 })),
3819 },
3820 in: map[string]nocaseString{"hello": "world"},
3821 want: `{"hello":"called"}`,
3822 }, {
3823 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
3824 opts: []Options{
3825 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3826 _ = *v.(*nocaseString)
3827 return []byte(`"called"`), nil
3828 })),
3829 },
3830 in: map[string]nocaseString{"hello": "world"},
3831 want: `{"hello":"called"}`,
3832 }, {
3833 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
3834 opts: []Options{
3835 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3836 return enc.WriteValue([]byte(`"called"`))
3837 })),
3838 },
3839 in: map[string]nocaseString{"hello": "world"},
3840 want: `{"hello":"called"}`,
3841 }, {
3842 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V2"),
3843 opts: []Options{
3844 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3845 _ = *v
3846 return enc.WriteValue([]byte(`"called"`))
3847 })),
3848 },
3849 in: map[string]nocaseString{"hello": "world"},
3850 want: `{"hello":"called"}`,
3851 }, {
3852 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
3853 opts: []Options{
3854 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3855 _ = *v.(*nocaseString)
3856 return enc.WriteValue([]byte(`"called"`))
3857 })),
3858 },
3859 in: map[string]nocaseString{"hello": "world"},
3860 want: `{"hello":"called"}`,
3861 }, {
3862 name: jsontest.Name("Funtions/Struct/Fields"),
3863 opts: []Options{
3864 WithMarshalers(JoinMarshalers(
3865 MarshalFunc(func(v bool) ([]byte, error) {
3866 return []byte(`"called1"`), nil
3867 }),
3868 MarshalFunc(func(v *string) ([]byte, error) {
3869 return []byte(`"called2"`), nil
3870 }),
3871 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3872 return enc.WriteValue([]byte(`"called3"`))
3873 }),
3874 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3875 return enc.WriteValue([]byte(`"called4"`))
3876 }),
3877 )),
3878 },
3879 in: structScalars{},
3880 want: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":0,"Float":0}`,
3881 }, {
3882 name: jsontest.Name("Functions/Struct/OmitEmpty"),
3883 opts: []Options{
3884 WithMarshalers(JoinMarshalers(
3885 MarshalFunc(func(v bool) ([]byte, error) {
3886 return []byte(`null`), nil
3887 }),
3888 MarshalFunc(func(v string) ([]byte, error) {
3889 return []byte(`"called1"`), nil
3890 }),
3891 MarshalFunc(func(v *stringMarshalNonEmpty) ([]byte, error) {
3892 return []byte(`""`), nil
3893 }),
3894 MarshalToFunc(func(enc *jsontext.Encoder, v bytesMarshalNonEmpty) error {
3895 return enc.WriteValue([]byte(`{}`))
3896 }),
3897 MarshalToFunc(func(enc *jsontext.Encoder, v *float64) error {
3898 return enc.WriteValue([]byte(`[]`))
3899 }),
3900 MarshalFunc(func(v mapMarshalNonEmpty) ([]byte, error) {
3901 return []byte(`"called2"`), nil
3902 }),
3903 MarshalFunc(func(v []string) ([]byte, error) {
3904 return []byte(`"called3"`), nil
3905 }),
3906 MarshalToFunc(func(enc *jsontext.Encoder, v *sliceMarshalNonEmpty) error {
3907 return enc.WriteValue([]byte(`"called4"`))
3908 }),
3909 )),
3910 },
3911 in: structOmitEmptyAll{},
3912 want: `{"String":"called1","MapNonEmpty":"called2","Slice":"called3","SliceNonEmpty":"called4"}`,
3913 }, {
3914 name: jsontest.Name("Functions/Struct/OmitZero"),
3915 opts: []Options{
3916 WithMarshalers(JoinMarshalers(
3917 MarshalFunc(func(v bool) ([]byte, error) {
3918 panic("should not be called")
3919 }),
3920 MarshalFunc(func(v *string) ([]byte, error) {
3921 panic("should not be called")
3922 }),
3923 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3924 panic("should not be called")
3925 }),
3926 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3927 panic("should not be called")
3928 }),
3929 )),
3930 },
3931 in: structOmitZeroAll{},
3932 want: `{}`,
3933 }, {
3934 name: jsontest.Name("Functions/Struct/Inlined"),
3935 opts: []Options{
3936 WithMarshalers(JoinMarshalers(
3937 MarshalFunc(func(v structInlinedL1) ([]byte, error) {
3938 panic("should not be called")
3939 }),
3940 MarshalToFunc(func(enc *jsontext.Encoder, v *StructEmbed2) error {
3941 panic("should not be called")
3942 }),
3943 )),
3944 },
3945 in: structInlined{},
3946 want: `{"D":""}`,
3947 }, {
3948 name: jsontest.Name("Functions/Slice/Elem"),
3949 opts: []Options{
3950 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3951 return []byte(`"` + strconv.FormatBool(v) + `"`), nil
3952 })),
3953 },
3954 in: []bool{true, false},
3955 want: `["true","false"]`,
3956 }, {
3957 name: jsontest.Name("Functions/Array/Elem"),
3958 opts: []Options{
3959 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3960 return enc.WriteValue([]byte(`"` + strconv.FormatBool(*v) + `"`))
3961 })),
3962 },
3963 in: [2]bool{true, false},
3964 want: `["true","false"]`,
3965 }, {
3966 name: jsontest.Name("Functions/Pointer/Nil"),
3967 opts: []Options{
3968 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3969 panic("should not be called")
3970 })),
3971 },
3972 in: struct{ X *bool }{nil},
3973 want: `{"X":null}`,
3974 }, {
3975 name: jsontest.Name("Functions/Pointer/NonNil"),
3976 opts: []Options{
3977 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3978 return enc.WriteValue([]byte(`"called"`))
3979 })),
3980 },
3981 in: struct{ X *bool }{addr(false)},
3982 want: `{"X":"called"}`,
3983 }, {
3984 name: jsontest.Name("Functions/Interface/Nil"),
3985 opts: []Options{
3986 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
3987 panic("should not be called")
3988 })),
3989 },
3990 in: struct{ X fmt.Stringer }{nil},
3991 want: `{"X":null}`,
3992 }, {
3993 name: jsontest.Name("Functions/Interface/NonNil/MatchInterface"),
3994 opts: []Options{
3995 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
3996 return enc.WriteValue([]byte(`"called"`))
3997 })),
3998 },
3999 in: struct{ X fmt.Stringer }{valueStringer{}},
4000 want: `{"X":"called"}`,
4001 }, {
4002 name: jsontest.Name("Functions/Interface/NonNil/MatchConcrete"),
4003 opts: []Options{
4004 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4005 return enc.WriteValue([]byte(`"called"`))
4006 })),
4007 },
4008 in: struct{ X fmt.Stringer }{valueStringer{}},
4009 want: `{"X":"called"}`,
4010 }, {
4011 name: jsontest.Name("Functions/Interface/NonNil/MatchPointer"),
4012 opts: []Options{
4013 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4014 return enc.WriteValue([]byte(`"called"`))
4015 })),
4016 },
4017 in: struct{ X fmt.Stringer }{valueStringer{}},
4018 want: `{"X":"called"}`,
4019 }, {
4020 name: jsontest.Name("Functions/Interface/Any"),
4021 in: []any{
4022 nil,
4023 valueStringer{},
4024 (*valueStringer)(nil),
4025 addr(valueStringer{}),
4026 (**valueStringer)(nil),
4027 addr((*valueStringer)(nil)),
4028 addr(addr(valueStringer{})),
4029 pointerStringer{},
4030 (*pointerStringer)(nil),
4031 addr(pointerStringer{}),
4032 (**pointerStringer)(nil),
4033 addr((*pointerStringer)(nil)),
4034 addr(addr(pointerStringer{})),
4035 "LAST",
4036 },
4037 want: `[null,{},null,{},null,null,{},{},null,{},null,null,{},"LAST"]`,
4038 opts: []Options{
4039 WithMarshalers(func() *Marshalers {
4040 type P struct {
4041 D int
4042 N int64
4043 }
4044 type PV struct {
4045 P P
4046 V any
4047 }
4048
4049 var lastChecks []func() error
4050 checkLast := func() error {
4051 for _, fn := range lastChecks {
4052 if err := fn(); err != nil {
4053 return err
4054 }
4055 }
4056 return SkipFunc
4057 }
4058 makeValueChecker := func(name string, want []PV) func(e *jsontext.Encoder, v any) error {
4059 checkNext := func(e *jsontext.Encoder, v any) error {
4060 xe := export.Encoder(e)
4061 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4062 rv := reflect.ValueOf(v)
4063 pv := PV{p, v}
4064 switch {
4065 case len(want) == 0:
4066 return fmt.Errorf("%s: %v: got more values than expected", name, p)
4067 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
4068 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
4069 case !reflect.DeepEqual(pv, want[0]):
4070 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
4071 default:
4072 want = want[1:]
4073 return SkipFunc
4074 }
4075 }
4076 lastChecks = append(lastChecks, func() error {
4077 if len(want) > 0 {
4078 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4079 }
4080 return nil
4081 })
4082 return checkNext
4083 }
4084 makePositionChecker := func(name string, want []P) func(e *jsontext.Encoder, v any) error {
4085 checkNext := func(e *jsontext.Encoder, v any) error {
4086 xe := export.Encoder(e)
4087 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4088 switch {
4089 case len(want) == 0:
4090 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
4091 case p != want[0]:
4092 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
4093 default:
4094 want = want[1:]
4095 return SkipFunc
4096 }
4097 }
4098 lastChecks = append(lastChecks, func() error {
4099 if len(want) > 0 {
4100 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4101 }
4102 return nil
4103 })
4104 return checkNext
4105 }
4106
4107 wantAny := []PV{
4108 {P{0, 0}, addr([]any{
4109 nil,
4110 valueStringer{},
4111 (*valueStringer)(nil),
4112 addr(valueStringer{}),
4113 (**valueStringer)(nil),
4114 addr((*valueStringer)(nil)),
4115 addr(addr(valueStringer{})),
4116 pointerStringer{},
4117 (*pointerStringer)(nil),
4118 addr(pointerStringer{}),
4119 (**pointerStringer)(nil),
4120 addr((*pointerStringer)(nil)),
4121 addr(addr(pointerStringer{})),
4122 "LAST",
4123 })},
4124 {P{1, 0}, addr(any(nil))},
4125 {P{1, 1}, addr(any(valueStringer{}))},
4126 {P{1, 1}, addr(valueStringer{})},
4127 {P{1, 2}, addr(any((*valueStringer)(nil)))},
4128 {P{1, 2}, addr((*valueStringer)(nil))},
4129 {P{1, 3}, addr(any(addr(valueStringer{})))},
4130 {P{1, 3}, addr(addr(valueStringer{}))},
4131 {P{1, 3}, addr(valueStringer{})},
4132 {P{1, 4}, addr(any((**valueStringer)(nil)))},
4133 {P{1, 4}, addr((**valueStringer)(nil))},
4134 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
4135 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
4136 {P{1, 5}, addr((*valueStringer)(nil))},
4137 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
4138 {P{1, 6}, addr(addr(addr(valueStringer{})))},
4139 {P{1, 6}, addr(addr(valueStringer{}))},
4140 {P{1, 6}, addr(valueStringer{})},
4141 {P{1, 7}, addr(any(pointerStringer{}))},
4142 {P{1, 7}, addr(pointerStringer{})},
4143 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
4144 {P{1, 8}, addr((*pointerStringer)(nil))},
4145 {P{1, 9}, addr(any(addr(pointerStringer{})))},
4146 {P{1, 9}, addr(addr(pointerStringer{}))},
4147 {P{1, 9}, addr(pointerStringer{})},
4148 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
4149 {P{1, 10}, addr((**pointerStringer)(nil))},
4150 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
4151 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
4152 {P{1, 11}, addr((*pointerStringer)(nil))},
4153 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
4154 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
4155 {P{1, 12}, addr(addr(pointerStringer{}))},
4156 {P{1, 12}, addr(pointerStringer{})},
4157 {P{1, 13}, addr(any("LAST"))},
4158 {P{1, 13}, addr("LAST")},
4159 }
4160 checkAny := makeValueChecker("any", wantAny)
4161 anyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v any) error {
4162 return checkAny(enc, v)
4163 })
4164
4165 var wantPointerAny []PV
4166 for _, v := range wantAny {
4167 if _, ok := v.V.(*any); ok {
4168 wantPointerAny = append(wantPointerAny, v)
4169 }
4170 }
4171 checkPointerAny := makeValueChecker("*any", wantPointerAny)
4172 pointerAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *any) error {
4173 return checkPointerAny(enc, v)
4174 })
4175
4176 checkNamedAny := makeValueChecker("namedAny", wantAny)
4177 namedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v namedAny) error {
4178 return checkNamedAny(enc, v)
4179 })
4180
4181 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
4182 pointerNamedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *namedAny) error {
4183 return checkPointerNamedAny(enc, v)
4184 })
4185
4186 type stringer = fmt.Stringer
4187 var wantStringer []PV
4188 for _, v := range wantAny {
4189 if _, ok := v.V.(stringer); ok {
4190 wantStringer = append(wantStringer, v)
4191 }
4192 }
4193 checkStringer := makeValueChecker("stringer", wantStringer)
4194 stringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v stringer) error {
4195 return checkStringer(enc, v)
4196 })
4197
4198 checkPointerStringer := makeValueChecker("*stringer", nil)
4199 pointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *stringer) error {
4200 return checkPointerStringer(enc, v)
4201 })
4202
4203 wantValueStringer := []P{{1, 1}, {1, 3}, {1, 6}}
4204 checkValueValueStringer := makePositionChecker("valueStringer", wantValueStringer)
4205 valueValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4206 return checkValueValueStringer(enc, v)
4207 })
4208
4209 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
4210 pointerValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4211 return checkPointerValueStringer(enc, v)
4212 })
4213
4214 wantPointerStringer := []P{{1, 7}, {1, 9}, {1, 12}}
4215 checkValuePointerStringer := makePositionChecker("pointerStringer", wantPointerStringer)
4216 valuePointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v pointerStringer) error {
4217 return checkValuePointerStringer(enc, v)
4218 })
4219
4220 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
4221 pointerPointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *pointerStringer) error {
4222 return checkPointerPointerStringer(enc, v)
4223 })
4224
4225 lastMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
4226 return checkLast()
4227 })
4228
4229 return JoinMarshalers(
4230 anyMarshaler,
4231 pointerAnyMarshaler,
4232 namedAnyMarshaler,
4233 pointerNamedAnyMarshaler,
4234 stringerMarshaler,
4235 pointerStringerMarshaler,
4236 valueValueStringerMarshaler,
4237 pointerValueStringerMarshaler,
4238 valuePointerStringerMarshaler,
4239 pointerPointerStringerMarshaler,
4240 lastMarshaler,
4241 )
4242 }()),
4243 },
4244 }, {
4245 name: jsontest.Name("Functions/Precedence/V1First"),
4246 opts: []Options{
4247 WithMarshalers(JoinMarshalers(
4248 MarshalFunc(func(bool) ([]byte, error) {
4249 return []byte(`"called"`), nil
4250 }),
4251 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4252 panic("should not be called")
4253 }),
4254 )),
4255 },
4256 in: true,
4257 want: `"called"`,
4258 }, {
4259 name: jsontest.Name("Functions/Precedence/V2First"),
4260 opts: []Options{
4261 WithMarshalers(JoinMarshalers(
4262 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4263 return enc.WriteToken(jsontext.String("called"))
4264 }),
4265 MarshalFunc(func(bool) ([]byte, error) {
4266 panic("should not be called")
4267 }),
4268 )),
4269 },
4270 in: true,
4271 want: `"called"`,
4272 }, {
4273 name: jsontest.Name("Functions/Precedence/V2Skipped"),
4274 opts: []Options{
4275 WithMarshalers(JoinMarshalers(
4276 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4277 return SkipFunc
4278 }),
4279 MarshalFunc(func(bool) ([]byte, error) {
4280 return []byte(`"called"`), nil
4281 }),
4282 )),
4283 },
4284 in: true,
4285 want: `"called"`,
4286 }, {
4287 name: jsontest.Name("Functions/Precedence/NestedFirst"),
4288 opts: []Options{
4289 WithMarshalers(JoinMarshalers(
4290 JoinMarshalers(
4291 MarshalFunc(func(bool) ([]byte, error) {
4292 return []byte(`"called"`), nil
4293 }),
4294 ),
4295 MarshalFunc(func(bool) ([]byte, error) {
4296 panic("should not be called")
4297 }),
4298 )),
4299 },
4300 in: true,
4301 want: `"called"`,
4302 }, {
4303 name: jsontest.Name("Functions/Precedence/NestedLast"),
4304 opts: []Options{
4305 WithMarshalers(JoinMarshalers(
4306 MarshalFunc(func(bool) ([]byte, error) {
4307 return []byte(`"called"`), nil
4308 }),
4309 JoinMarshalers(
4310 MarshalFunc(func(bool) ([]byte, error) {
4311 panic("should not be called")
4312 }),
4313 ),
4314 )),
4315 },
4316 in: true,
4317 want: `"called"`,
4318 }, {
4319 name: jsontest.Name("Duration/Zero"),
4320 in: struct {
4321 D1 time.Duration `json:",format:units"`
4322 D2 time.Duration `json:",format:nano"`
4323 }{0, 0},
4324 want: `{"D1":"0s","D2":0}`,
4325 }, {
4326 name: jsontest.Name("Duration/Positive"),
4327 in: struct {
4328 D1 time.Duration `json:",format:units"`
4329 D2 time.Duration `json:",format:nano"`
4330 }{
4331 123456789123456789,
4332 123456789123456789,
4333 },
4334 want: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
4335 }, {
4336 name: jsontest.Name("Duration/Negative"),
4337 in: struct {
4338 D1 time.Duration `json:",format:units"`
4339 D2 time.Duration `json:",format:nano"`
4340 }{
4341 -123456789123456789,
4342 -123456789123456789,
4343 },
4344 want: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
4345 }, {
4346 name: jsontest.Name("Duration/Nanos/String"),
4347 in: struct {
4348 D1 time.Duration `json:",string,format:nano"`
4349 D2 time.Duration `json:",string,format:nano"`
4350 D3 time.Duration `json:",string,format:nano"`
4351 }{
4352 math.MinInt64,
4353 0,
4354 math.MaxInt64,
4355 },
4356 want: `{"D1":"-9223372036854775808","D2":"0","D3":"9223372036854775807"}`,
4357 }, {
4358 name: jsontest.Name("Duration/Format/Invalid"),
4359 in: struct {
4360 D time.Duration `json:",format:invalid"`
4361 }{},
4362 want: `{"D"`,
4363 wantErr: EM(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, T[time.Duration]()),
4364 }, {
4365
4371 name: jsontest.Name("Duration/Format"),
4372 opts: []Options{jsontext.Multiline(true)},
4373 in: structDurationFormat{
4374 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4375 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4376 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4377 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4378 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4379 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4380 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4381 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4382 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4383 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4384 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4385 },
4386 want: `{
4387 "D1": "12h34m56.078090012s",
4388 "D2": "12h34m56.078090012s",
4389 "D3": 45296.078090012,
4390 "D4": "45296.078090012",
4391 "D5": 45296078.090012,
4392 "D6": "45296078.090012",
4393 "D7": 45296078090.012,
4394 "D8": "45296078090.012",
4395 "D9": 45296078090012,
4396 "D10": "45296078090012",
4397 "D11": "PT12H34M56.078090012S"
4398 }`,
4399 }, {
4400
4409
4414 name: jsontest.Name("Duration/MapKey/Legacy"),
4415 opts: []Options{jsonflags.FormatDurationAsNano | 1},
4416 in: map[time.Duration]string{time.Second: ""},
4417 want: `{"1000000000":""}`,
4418 }, {
4419 name: jsontest.Name("Time/Zero"),
4420 in: struct {
4421 T1 time.Time
4422 T2 time.Time `json:",format:RFC822"`
4423 T3 time.Time `json:",format:'2006-01-02'"`
4424 T4 time.Time `json:",omitzero"`
4425 T5 time.Time `json:",omitempty"`
4426 }{
4427 time.Time{},
4428 time.Time{},
4429 time.Time{},
4430
4431
4432 time.Date(1, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC", 0)),
4433 time.Time{},
4434 },
4435 want: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T5":"0001-01-01T00:00:00Z"}`,
4436 }, {
4437 name: jsontest.Name("Time/Format"),
4438 opts: []Options{jsontext.Multiline(true)},
4439 in: structTimeFormat{
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 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4454 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4455 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4456 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4457 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4458 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4459 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4460 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4461 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4462 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4463 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4464 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4465 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4466 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4467 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4468 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4469 },
4470 want: `{
4471 "T1": "1234-01-02T03:04:05.000000006Z",
4472 "T2": "Mon Jan 2 03:04:05 1234",
4473 "T3": "Mon Jan 2 03:04:05 UTC 1234",
4474 "T4": "Mon Jan 02 03:04:05 +0000 1234",
4475 "T5": "02 Jan 34 03:04 UTC",
4476 "T6": "02 Jan 34 03:04 +0000",
4477 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
4478 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
4479 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
4480 "T10": "1234-01-02T03:04:05Z",
4481 "T11": "1234-01-02T03:04:05.000000006Z",
4482 "T12": "3:04AM",
4483 "T13": "Jan 2 03:04:05",
4484 "T14": "Jan 2 03:04:05.000",
4485 "T15": "Jan 2 03:04:05.000000",
4486 "T16": "Jan 2 03:04:05.000000006",
4487 "T17": "1234-01-02 03:04:05",
4488 "T18": "1234-01-02",
4489 "T19": "03:04:05",
4490 "T20": "1234-01-02",
4491 "T21": "\"weird\"1234",
4492 "T22": -23225777754.999999994,
4493 "T23": "-23225777754.999999994",
4494 "T24": -23225777754999.999994,
4495 "T25": "-23225777754999.999994",
4496 "T26": -23225777754999999.994,
4497 "T27": "-23225777754999999.994",
4498 "T28": -23225777754999999994,
4499 "T29": "-23225777754999999994"
4500 }`,
4501 }, {
4502 name: jsontest.Name("Time/Format/Invalid"),
4503 in: struct {
4504 T time.Time `json:",format:UndefinedConstant"`
4505 }{},
4506 want: `{"T"`,
4507 wantErr: EM(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4508 }, {
4509 name: jsontest.Name("Time/Format/YearOverflow"),
4510 in: struct {
4511 T1 time.Time
4512 T2 time.Time
4513 }{
4514 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4515 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC),
4516 },
4517 want: `{"T1":"9999-12-31T23:59:59Z","T2"`,
4518 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"9999-12-31T23:59:59Z","T2":`, "/T2").withType(0, timeTimeType),
4519 }, {
4520 name: jsontest.Name("Time/Format/YearUnderflow"),
4521 in: struct {
4522 T1 time.Time
4523 T2 time.Time
4524 }{
4525 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
4526 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4527 },
4528 want: `{"T1":"0000-01-01T00:00:00Z","T2"`,
4529 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"0000-01-01T00:00:00Z","T2":`, "/T2").withType(0, timeTimeType),
4530 }, {
4531 name: jsontest.Name("Time/Format/YearUnderflow"),
4532 in: struct{ T time.Time }{time.Date(-998, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second)},
4533 want: `{"T"`,
4534 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4535 }, {
4536 name: jsontest.Name("Time/Format/ZoneExact"),
4537 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 23*60*60+59*60))},
4538 want: `{"T":"2020-01-01T00:00:00+23:59"}`,
4539 }, {
4540 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4541 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 24*60*60))},
4542 want: `{"T"`,
4543 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4544 }, {
4545 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4546 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 123*60*60))},
4547 want: `{"T"`,
4548 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4549 }, {
4550 name: jsontest.Name("Time/IgnoreInvalidFormat"),
4551 opts: []Options{invalidFormatOption},
4552 in: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
4553 want: `"2000-01-01T00:00:00Z"`,
4554 }}
4555
4556 for _, tt := range tests {
4557 t.Run(tt.name.Name, func(t *testing.T) {
4558 var got []byte
4559 var gotErr error
4560 if tt.useWriter {
4561 bb := new(struct{ bytes.Buffer })
4562 gotErr = MarshalWrite(bb, tt.in, tt.opts...)
4563 got = bb.Bytes()
4564 } else {
4565 got, gotErr = Marshal(tt.in, tt.opts...)
4566 }
4567 if tt.canonicalize {
4568 (*jsontext.Value)(&got).Canonicalize()
4569 }
4570 if string(got) != tt.want {
4571 t.Errorf("%s: Marshal output mismatch:\ngot %s\nwant %s", tt.name.Where, got, tt.want)
4572 }
4573 if !reflect.DeepEqual(gotErr, tt.wantErr) {
4574 t.Errorf("%s: Marshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
4575 }
4576 })
4577 }
4578 }
4579
4580 func TestUnmarshal(t *testing.T) {
4581 tests := []struct {
4582 name jsontest.CaseName
4583 opts []Options
4584 inBuf string
4585 inVal any
4586 want any
4587 wantErr error
4588 }{{
4589 name: jsontest.Name("Nil"),
4590 inBuf: `null`,
4591 wantErr: EU(internal.ErrNonNilReference),
4592 }, {
4593 name: jsontest.Name("NilPointer"),
4594 inBuf: `null`,
4595 inVal: (*string)(nil),
4596 want: (*string)(nil),
4597 wantErr: EU(internal.ErrNonNilReference).withType(0, T[*string]()),
4598 }, {
4599 name: jsontest.Name("NonPointer"),
4600 inBuf: `null`,
4601 inVal: "unchanged",
4602 want: "unchanged",
4603 wantErr: EU(internal.ErrNonNilReference).withType(0, T[string]()),
4604 }, {
4605 name: jsontest.Name("Bools/TrailingJunk"),
4606 inBuf: `falsetrue`,
4607 inVal: addr(true),
4608 want: addr(false),
4609 wantErr: newInvalidCharacterError("t", "after top-level value", len64(`false`), ""),
4610 }, {
4611 name: jsontest.Name("Bools/Null"),
4612 inBuf: `null`,
4613 inVal: addr(true),
4614 want: addr(false),
4615 }, {
4616 name: jsontest.Name("Bools"),
4617 inBuf: `[null,false,true]`,
4618 inVal: new([]bool),
4619 want: addr([]bool{false, false, true}),
4620 }, {
4621 name: jsontest.Name("Bools/Named"),
4622 inBuf: `[null,false,true]`,
4623 inVal: new([]namedBool),
4624 want: addr([]namedBool{false, false, true}),
4625 }, {
4626 name: jsontest.Name("Bools/Invalid/StringifiedFalse"),
4627 opts: []Options{StringifyNumbers(true)},
4628 inBuf: `"false"`,
4629 inVal: addr(true),
4630 want: addr(true),
4631 wantErr: EU(nil).withType('"', boolType),
4632 }, {
4633 name: jsontest.Name("Bools/Invalid/StringifiedTrue"),
4634 opts: []Options{StringifyNumbers(true)},
4635 inBuf: `"true"`,
4636 inVal: addr(true),
4637 want: addr(true),
4638 wantErr: EU(nil).withType('"', boolType),
4639 }, {
4640 name: jsontest.Name("Bools/StringifiedBool/True"),
4641 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4642 inBuf: `"true"`,
4643 inVal: addr(false),
4644 want: addr(true),
4645 }, {
4646 name: jsontest.Name("Bools/StringifiedBool/False"),
4647 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4648 inBuf: `"false"`,
4649 inVal: addr(true),
4650 want: addr(false),
4651 }, {
4652 name: jsontest.Name("Bools/StringifiedBool/InvalidWhitespace"),
4653 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4654 inBuf: `"false "`,
4655 inVal: addr(true),
4656 want: addr(true),
4657 wantErr: EU(strconv.ErrSyntax).withVal(`"false "`).withType('"', boolType),
4658 }, {
4659 name: jsontest.Name("Bools/StringifiedBool/InvalidBool"),
4660 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4661 inBuf: `false`,
4662 inVal: addr(true),
4663 want: addr(true),
4664 wantErr: EU(nil).withType('f', boolType),
4665 }, {
4666 name: jsontest.Name("Bools/Invalid/Number"),
4667 inBuf: `0`,
4668 inVal: addr(true),
4669 want: addr(true),
4670 wantErr: EU(nil).withType('0', boolType),
4671 }, {
4672 name: jsontest.Name("Bools/Invalid/String"),
4673 inBuf: `""`,
4674 inVal: addr(true),
4675 want: addr(true),
4676 wantErr: EU(nil).withType('"', boolType),
4677 }, {
4678 name: jsontest.Name("Bools/Invalid/Object"),
4679 inBuf: `{}`,
4680 inVal: addr(true),
4681 want: addr(true),
4682 wantErr: EU(nil).withType('{', boolType),
4683 }, {
4684 name: jsontest.Name("Bools/Invalid/Array"),
4685 inBuf: `[]`,
4686 inVal: addr(true),
4687 want: addr(true),
4688 wantErr: EU(nil).withType('[', boolType),
4689 }, {
4690 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
4691 opts: []Options{invalidFormatOption},
4692 inBuf: `false`,
4693 inVal: addr(true),
4694 want: addr(false),
4695 }, {
4696 name: jsontest.Name("Strings/Null"),
4697 inBuf: `null`,
4698 inVal: addr("something"),
4699 want: addr(""),
4700 }, {
4701 name: jsontest.Name("Strings"),
4702 inBuf: `[null,"","hello","世界"]`,
4703 inVal: new([]string),
4704 want: addr([]string{"", "", "hello", "世界"}),
4705 }, {
4706 name: jsontest.Name("Strings/Escaped"),
4707 inBuf: `[null,"","\u0068\u0065\u006c\u006c\u006f","\u4e16\u754c"]`,
4708 inVal: new([]string),
4709 want: addr([]string{"", "", "hello", "世界"}),
4710 }, {
4711 name: jsontest.Name("Strings/Named"),
4712 inBuf: `[null,"","hello","世界"]`,
4713 inVal: new([]namedString),
4714 want: addr([]namedString{"", "", "hello", "世界"}),
4715 }, {
4716 name: jsontest.Name("Strings/Invalid/False"),
4717 inBuf: `false`,
4718 inVal: addr("nochange"),
4719 want: addr("nochange"),
4720 wantErr: EU(nil).withType('f', stringType),
4721 }, {
4722 name: jsontest.Name("Strings/Invalid/True"),
4723 inBuf: `true`,
4724 inVal: addr("nochange"),
4725 want: addr("nochange"),
4726 wantErr: EU(nil).withType('t', stringType),
4727 }, {
4728 name: jsontest.Name("Strings/Invalid/Object"),
4729 inBuf: `{}`,
4730 inVal: addr("nochange"),
4731 want: addr("nochange"),
4732 wantErr: EU(nil).withType('{', stringType),
4733 }, {
4734 name: jsontest.Name("Strings/Invalid/Array"),
4735 inBuf: `[]`,
4736 inVal: addr("nochange"),
4737 want: addr("nochange"),
4738 wantErr: EU(nil).withType('[', stringType),
4739 }, {
4740 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
4741 opts: []Options{invalidFormatOption},
4742 inBuf: `"hello"`,
4743 inVal: addr("goodbye"),
4744 want: addr("hello"),
4745 }, {
4746 name: jsontest.Name("Strings/StringifiedString"),
4747 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4748 inBuf: `"\"foo\""`,
4749 inVal: new(string),
4750 want: addr("foo"),
4751 }, {
4752 name: jsontest.Name("Strings/StringifiedString/InvalidWhitespace"),
4753 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4754 inBuf: `"\"foo\" "`,
4755 inVal: new(string),
4756 want: new(string),
4757 wantErr: EU(newInvalidCharacterError(" ", "after string value", 0, "")).withType('"', stringType),
4758 }, {
4759 name: jsontest.Name("Strings/StringifiedString/InvalidString"),
4760 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4761 inBuf: `""`,
4762 inVal: new(string),
4763 want: new(string),
4764 wantErr: EU(&jsontext.SyntacticError{Err: io.ErrUnexpectedEOF}).withType('"', stringType),
4765 }, {
4766 name: jsontest.Name("Bytes/Null"),
4767 inBuf: `null`,
4768 inVal: addr([]byte("something")),
4769 want: addr([]byte(nil)),
4770 }, {
4771 name: jsontest.Name("Bytes"),
4772 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4773 inVal: new([][]byte),
4774 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4775 }, {
4776 name: jsontest.Name("Bytes/Large"),
4777 inBuf: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
4778 inVal: new([]byte),
4779 want: addr([]byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on.")),
4780 }, {
4781 name: jsontest.Name("Bytes/Reuse"),
4782 inBuf: `"AQID"`,
4783 inVal: addr([]byte("changed")),
4784 want: addr([]byte{1, 2, 3}),
4785 }, {
4786 name: jsontest.Name("Bytes/Escaped"),
4787 inBuf: `[null,"","\u0041\u0051\u003d\u003d","\u0041\u0051\u0049\u003d","\u0041\u0051\u0049\u0044"]`,
4788 inVal: new([][]byte),
4789 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4790 }, {
4791 name: jsontest.Name("Bytes/Named"),
4792 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4793 inVal: new([]namedBytes),
4794 want: addr([]namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4795 }, {
4796 name: jsontest.Name("Bytes/NotStringified"),
4797 opts: []Options{StringifyNumbers(true)},
4798 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4799 inVal: new([][]byte),
4800 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4801 }, {
4802
4803
4804 name: jsontest.Name("Bytes/Invariant"),
4805 inBuf: `[null,[],[1],[1,2],[1,2,3]]`,
4806 inVal: new([][]namedByte),
4807 want: addr([][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4808 }, {
4809
4810
4811 name: jsontest.Name("Bytes/ByteArray"),
4812 inBuf: `"aGVsbG8="`,
4813 inVal: new([5]byte),
4814 want: addr([5]byte{'h', 'e', 'l', 'l', 'o'}),
4815 }, {
4816 name: jsontest.Name("Bytes/ByteArray0/Valid"),
4817 inBuf: `""`,
4818 inVal: new([0]byte),
4819 want: addr([0]byte{}),
4820 }, {
4821 name: jsontest.Name("Bytes/ByteArray0/Invalid"),
4822 inBuf: `"A"`,
4823 inVal: new([0]byte),
4824 want: addr([0]byte{}),
4825 wantErr: EU(func() error {
4826 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("A"))
4827 return err
4828 }()).withType('"', T[[0]byte]()),
4829 }, {
4830 name: jsontest.Name("Bytes/ByteArray0/Overflow"),
4831 inBuf: `"AA=="`,
4832 inVal: new([0]byte),
4833 want: addr([0]byte{}),
4834 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 0")).withType('"', T[[0]byte]()),
4835 }, {
4836 name: jsontest.Name("Bytes/ByteArray1/Valid"),
4837 inBuf: `"AQ=="`,
4838 inVal: new([1]byte),
4839 want: addr([1]byte{1}),
4840 }, {
4841 name: jsontest.Name("Bytes/ByteArray1/Invalid"),
4842 inBuf: `"$$=="`,
4843 inVal: new([1]byte),
4844 want: addr([1]byte{}),
4845 wantErr: EU(func() error {
4846 _, err := base64.StdEncoding.Decode(make([]byte, 1), []byte("$$=="))
4847 return err
4848 }()).withType('"', T[[1]byte]()),
4849 }, {
4850 name: jsontest.Name("Bytes/ByteArray1/Underflow"),
4851 inBuf: `""`,
4852 inVal: new([1]byte),
4853 want: addr([1]byte{}),
4854 wantErr: EU(errors.New("decoded length of 0 mismatches array length of 1")).withType('"', T[[1]byte]()),
4855 }, {
4856 name: jsontest.Name("Bytes/ByteArray1/Overflow"),
4857 inBuf: `"AQI="`,
4858 inVal: new([1]byte),
4859 want: addr([1]byte{1}),
4860 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 1")).withType('"', T[[1]byte]()),
4861 }, {
4862 name: jsontest.Name("Bytes/ByteArray2/Valid"),
4863 inBuf: `"AQI="`,
4864 inVal: new([2]byte),
4865 want: addr([2]byte{1, 2}),
4866 }, {
4867 name: jsontest.Name("Bytes/ByteArray2/Invalid"),
4868 inBuf: `"$$$="`,
4869 inVal: new([2]byte),
4870 want: addr([2]byte{}),
4871 wantErr: EU(func() error {
4872 _, err := base64.StdEncoding.Decode(make([]byte, 2), []byte("$$$="))
4873 return err
4874 }()).withType('"', T[[2]byte]()),
4875 }, {
4876 name: jsontest.Name("Bytes/ByteArray2/Underflow"),
4877 inBuf: `"AQ=="`,
4878 inVal: new([2]byte),
4879 want: addr([2]byte{1, 0}),
4880 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 2")).withType('"', T[[2]byte]()),
4881 }, {
4882 name: jsontest.Name("Bytes/ByteArray2/Underflow/Allowed"),
4883 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4884 inBuf: `"AQ=="`,
4885 inVal: new([2]byte),
4886 want: addr([2]byte{1, 0}),
4887 }, {
4888 name: jsontest.Name("Bytes/ByteArray2/Overflow"),
4889 inBuf: `"AQID"`,
4890 inVal: new([2]byte),
4891 want: addr([2]byte{1, 2}),
4892 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 2")).withType('"', T[[2]byte]()),
4893 }, {
4894 name: jsontest.Name("Bytes/ByteArray2/Overflow/Allowed"),
4895 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4896 inBuf: `"AQID"`,
4897 inVal: new([2]byte),
4898 want: addr([2]byte{1, 2}),
4899 }, {
4900 name: jsontest.Name("Bytes/ByteArray3/Valid"),
4901 inBuf: `"AQID"`,
4902 inVal: new([3]byte),
4903 want: addr([3]byte{1, 2, 3}),
4904 }, {
4905 name: jsontest.Name("Bytes/ByteArray3/Invalid"),
4906 inBuf: `"$$$$"`,
4907 inVal: new([3]byte),
4908 want: addr([3]byte{}),
4909 wantErr: EU(func() error {
4910 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("$$$$"))
4911 return err
4912 }()).withType('"', T[[3]byte]()),
4913 }, {
4914 name: jsontest.Name("Bytes/ByteArray3/Underflow"),
4915 inBuf: `"AQI="`,
4916 inVal: addr([3]byte{0xff, 0xff, 0xff}),
4917 want: addr([3]byte{1, 2, 0}),
4918 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 3")).withType('"', T[[3]byte]()),
4919 }, {
4920 name: jsontest.Name("Bytes/ByteArray3/Overflow"),
4921 inBuf: `"AQIDAQ=="`,
4922 inVal: new([3]byte),
4923 want: addr([3]byte{1, 2, 3}),
4924 wantErr: EU(errors.New("decoded length of 4 mismatches array length of 3")).withType('"', T[[3]byte]()),
4925 }, {
4926 name: jsontest.Name("Bytes/ByteArray4/Valid"),
4927 inBuf: `"AQIDBA=="`,
4928 inVal: new([4]byte),
4929 want: addr([4]byte{1, 2, 3, 4}),
4930 }, {
4931 name: jsontest.Name("Bytes/ByteArray4/Invalid"),
4932 inBuf: `"$$$$$$=="`,
4933 inVal: new([4]byte),
4934 want: addr([4]byte{}),
4935 wantErr: EU(func() error {
4936 _, err := base64.StdEncoding.Decode(make([]byte, 4), []byte("$$$$$$=="))
4937 return err
4938 }()).withType('"', T[[4]byte]()),
4939 }, {
4940 name: jsontest.Name("Bytes/ByteArray4/Underflow"),
4941 inBuf: `"AQID"`,
4942 inVal: new([4]byte),
4943 want: addr([4]byte{1, 2, 3, 0}),
4944 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 4")).withType('"', T[[4]byte]()),
4945 }, {
4946 name: jsontest.Name("Bytes/ByteArray4/Overflow"),
4947 inBuf: `"AQIDBAU="`,
4948 inVal: new([4]byte),
4949 want: addr([4]byte{1, 2, 3, 4}),
4950 wantErr: EU(errors.New("decoded length of 5 mismatches array length of 4")).withType('"', T[[4]byte]()),
4951 }, {
4952
4953
4954 name: jsontest.Name("Bytes/NamedByteArray"),
4955 inBuf: `[104,101,108,108,111]`,
4956 inVal: new([5]namedByte),
4957 want: addr([5]namedByte{'h', 'e', 'l', 'l', 'o'}),
4958 }, {
4959 name: jsontest.Name("Bytes/Valid/Denormalized"),
4960 inBuf: `"AR=="`,
4961 inVal: new([]byte),
4962 want: addr([]byte{1}),
4963 }, {
4964 name: jsontest.Name("Bytes/Invalid/Unpadded1"),
4965 inBuf: `"AQ="`,
4966 inVal: addr([]byte("nochange")),
4967 want: addr([]byte("nochange")),
4968 wantErr: EU(func() error {
4969 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ="))
4970 return err
4971 }()).withType('"', bytesType),
4972 }, {
4973 name: jsontest.Name("Bytes/Invalid/Unpadded2"),
4974 inBuf: `"AQ"`,
4975 inVal: addr([]byte("nochange")),
4976 want: addr([]byte("nochange")),
4977 wantErr: EU(func() error {
4978 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ"))
4979 return err
4980 }()).withType('"', bytesType),
4981 }, {
4982 name: jsontest.Name("Bytes/Invalid/Character"),
4983 inBuf: `"@@@@"`,
4984 inVal: addr([]byte("nochange")),
4985 want: addr([]byte("nochange")),
4986 wantErr: EU(func() error {
4987 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("@@@@"))
4988 return err
4989 }()).withType('"', bytesType),
4990 }, {
4991 name: jsontest.Name("Bytes/Invalid/Bool"),
4992 inBuf: `true`,
4993 inVal: addr([]byte("nochange")),
4994 want: addr([]byte("nochange")),
4995 wantErr: EU(nil).withType('t', bytesType),
4996 }, {
4997 name: jsontest.Name("Bytes/Invalid/Number"),
4998 inBuf: `0`,
4999 inVal: addr([]byte("nochange")),
5000 want: addr([]byte("nochange")),
5001 wantErr: EU(nil).withType('0', bytesType),
5002 }, {
5003 name: jsontest.Name("Bytes/Invalid/Object"),
5004 inBuf: `{}`,
5005 inVal: addr([]byte("nochange")),
5006 want: addr([]byte("nochange")),
5007 wantErr: EU(nil).withType('{', bytesType),
5008 }, {
5009 name: jsontest.Name("Bytes/Invalid/Array"),
5010 inBuf: `[]`,
5011 inVal: addr([]byte("nochange")),
5012 want: addr([]byte("nochange")),
5013 wantErr: EU(nil).withType('[', bytesType),
5014 }, {
5015 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
5016 opts: []Options{invalidFormatOption},
5017 inBuf: `"aGVsbG8="`,
5018 inVal: new([]byte),
5019 want: addr([]byte("hello")),
5020 }, {
5021 name: jsontest.Name("Ints/Null"),
5022 inBuf: `null`,
5023 inVal: addr(int(1)),
5024 want: addr(int(0)),
5025 }, {
5026 name: jsontest.Name("Ints/Int"),
5027 inBuf: `1`,
5028 inVal: addr(int(0)),
5029 want: addr(int(1)),
5030 }, {
5031 name: jsontest.Name("Ints/Int8/MinOverflow"),
5032 inBuf: `-129`,
5033 inVal: addr(int8(-1)),
5034 want: addr(int8(-1)),
5035 wantErr: EU(strconv.ErrRange).withVal(`-129`).withType('0', T[int8]()),
5036 }, {
5037 name: jsontest.Name("Ints/Int8/Min"),
5038 inBuf: `-128`,
5039 inVal: addr(int8(0)),
5040 want: addr(int8(-128)),
5041 }, {
5042 name: jsontest.Name("Ints/Int8/Max"),
5043 inBuf: `127`,
5044 inVal: addr(int8(0)),
5045 want: addr(int8(127)),
5046 }, {
5047 name: jsontest.Name("Ints/Int8/MaxOverflow"),
5048 inBuf: `128`,
5049 inVal: addr(int8(-1)),
5050 want: addr(int8(-1)),
5051 wantErr: EU(strconv.ErrRange).withVal(`128`).withType('0', T[int8]()),
5052 }, {
5053 name: jsontest.Name("Ints/Int16/MinOverflow"),
5054 inBuf: `-32769`,
5055 inVal: addr(int16(-1)),
5056 want: addr(int16(-1)),
5057 wantErr: EU(strconv.ErrRange).withVal(`-32769`).withType('0', T[int16]()),
5058 }, {
5059 name: jsontest.Name("Ints/Int16/Min"),
5060 inBuf: `-32768`,
5061 inVal: addr(int16(0)),
5062 want: addr(int16(-32768)),
5063 }, {
5064 name: jsontest.Name("Ints/Int16/Max"),
5065 inBuf: `32767`,
5066 inVal: addr(int16(0)),
5067 want: addr(int16(32767)),
5068 }, {
5069 name: jsontest.Name("Ints/Int16/MaxOverflow"),
5070 inBuf: `32768`,
5071 inVal: addr(int16(-1)),
5072 want: addr(int16(-1)),
5073 wantErr: EU(strconv.ErrRange).withVal(`32768`).withType('0', T[int16]()),
5074 }, {
5075 name: jsontest.Name("Ints/Int32/MinOverflow"),
5076 inBuf: `-2147483649`,
5077 inVal: addr(int32(-1)),
5078 want: addr(int32(-1)),
5079 wantErr: EU(strconv.ErrRange).withVal(`-2147483649`).withType('0', T[int32]()),
5080 }, {
5081 name: jsontest.Name("Ints/Int32/Min"),
5082 inBuf: `-2147483648`,
5083 inVal: addr(int32(0)),
5084 want: addr(int32(-2147483648)),
5085 }, {
5086 name: jsontest.Name("Ints/Int32/Max"),
5087 inBuf: `2147483647`,
5088 inVal: addr(int32(0)),
5089 want: addr(int32(2147483647)),
5090 }, {
5091 name: jsontest.Name("Ints/Int32/MaxOverflow"),
5092 inBuf: `2147483648`,
5093 inVal: addr(int32(-1)),
5094 want: addr(int32(-1)),
5095 wantErr: EU(strconv.ErrRange).withVal(`2147483648`).withType('0', T[int32]()),
5096 }, {
5097 name: jsontest.Name("Ints/Int64/MinOverflow"),
5098 inBuf: `-9223372036854775809`,
5099 inVal: addr(int64(-1)),
5100 want: addr(int64(-1)),
5101 wantErr: EU(strconv.ErrRange).withVal(`-9223372036854775809`).withType('0', T[int64]()),
5102 }, {
5103 name: jsontest.Name("Ints/Int64/Min"),
5104 inBuf: `-9223372036854775808`,
5105 inVal: addr(int64(0)),
5106 want: addr(int64(-9223372036854775808)),
5107 }, {
5108 name: jsontest.Name("Ints/Int64/Max"),
5109 inBuf: `9223372036854775807`,
5110 inVal: addr(int64(0)),
5111 want: addr(int64(9223372036854775807)),
5112 }, {
5113 name: jsontest.Name("Ints/Int64/MaxOverflow"),
5114 inBuf: `9223372036854775808`,
5115 inVal: addr(int64(-1)),
5116 want: addr(int64(-1)),
5117 wantErr: EU(strconv.ErrRange).withVal(`9223372036854775808`).withType('0', T[int64]()),
5118 }, {
5119 name: jsontest.Name("Ints/Named"),
5120 inBuf: `-6464`,
5121 inVal: addr(namedInt64(0)),
5122 want: addr(namedInt64(-6464)),
5123 }, {
5124 name: jsontest.Name("Ints/Stringified"),
5125 opts: []Options{StringifyNumbers(true)},
5126 inBuf: `"-6464"`,
5127 inVal: new(int),
5128 want: addr(int(-6464)),
5129 }, {
5130 name: jsontest.Name("Ints/Stringified/Invalid"),
5131 opts: []Options{StringifyNumbers(true)},
5132 inBuf: `-6464`,
5133 inVal: new(int),
5134 want: new(int),
5135 wantErr: EU(nil).withType('0', T[int]()),
5136 }, {
5137 name: jsontest.Name("Ints/Stringified/LeadingZero"),
5138 opts: []Options{StringifyNumbers(true)},
5139 inBuf: `"00"`,
5140 inVal: addr(int(-1)),
5141 want: addr(int(-1)),
5142 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[int]()),
5143 }, {
5144 name: jsontest.Name("Ints/Escaped"),
5145 opts: []Options{StringifyNumbers(true)},
5146 inBuf: `"\u002d\u0036\u0034\u0036\u0034"`,
5147 inVal: new(int),
5148 want: addr(int(-6464)),
5149 }, {
5150 name: jsontest.Name("Ints/Valid/NegativeZero"),
5151 inBuf: `-0`,
5152 inVal: addr(int(1)),
5153 want: addr(int(0)),
5154 }, {
5155 name: jsontest.Name("Ints/Invalid/Fraction"),
5156 inBuf: `1.0`,
5157 inVal: addr(int(-1)),
5158 want: addr(int(-1)),
5159 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[int]()),
5160 }, {
5161 name: jsontest.Name("Ints/Invalid/Exponent"),
5162 inBuf: `1e0`,
5163 inVal: addr(int(-1)),
5164 want: addr(int(-1)),
5165 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[int]()),
5166 }, {
5167 name: jsontest.Name("Ints/Invalid/StringifiedFraction"),
5168 opts: []Options{StringifyNumbers(true)},
5169 inBuf: `"1.0"`,
5170 inVal: addr(int(-1)),
5171 want: addr(int(-1)),
5172 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[int]()),
5173 }, {
5174 name: jsontest.Name("Ints/Invalid/StringifiedExponent"),
5175 opts: []Options{StringifyNumbers(true)},
5176 inBuf: `"1e0"`,
5177 inVal: addr(int(-1)),
5178 want: addr(int(-1)),
5179 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[int]()),
5180 }, {
5181 name: jsontest.Name("Ints/Invalid/Overflow"),
5182 inBuf: `100000000000000000000000000000`,
5183 inVal: addr(int(-1)),
5184 want: addr(int(-1)),
5185 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[int]()),
5186 }, {
5187 name: jsontest.Name("Ints/Invalid/OverflowSyntax"),
5188 opts: []Options{StringifyNumbers(true)},
5189 inBuf: `"100000000000000000000000000000x"`,
5190 inVal: addr(int(-1)),
5191 want: addr(int(-1)),
5192 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[int]()),
5193 }, {
5194 name: jsontest.Name("Ints/Invalid/Whitespace"),
5195 opts: []Options{StringifyNumbers(true)},
5196 inBuf: `"0 "`,
5197 inVal: addr(int(-1)),
5198 want: addr(int(-1)),
5199 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[int]()),
5200 }, {
5201 name: jsontest.Name("Ints/Invalid/Bool"),
5202 inBuf: `true`,
5203 inVal: addr(int(-1)),
5204 want: addr(int(-1)),
5205 wantErr: EU(nil).withType('t', T[int]()),
5206 }, {
5207 name: jsontest.Name("Ints/Invalid/String"),
5208 inBuf: `"0"`,
5209 inVal: addr(int(-1)),
5210 want: addr(int(-1)),
5211 wantErr: EU(nil).withType('"', T[int]()),
5212 }, {
5213 name: jsontest.Name("Ints/Invalid/Object"),
5214 inBuf: `{}`,
5215 inVal: addr(int(-1)),
5216 want: addr(int(-1)),
5217 wantErr: EU(nil).withType('{', T[int]()),
5218 }, {
5219 name: jsontest.Name("Ints/Invalid/Array"),
5220 inBuf: `[]`,
5221 inVal: addr(int(-1)),
5222 want: addr(int(-1)),
5223 wantErr: EU(nil).withType('[', T[int]()),
5224 }, {
5225 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
5226 opts: []Options{invalidFormatOption},
5227 inBuf: `1`,
5228 inVal: addr(int(0)),
5229 want: addr(int(1)),
5230 }, {
5231 name: jsontest.Name("Uints/Null"),
5232 inBuf: `null`,
5233 inVal: addr(uint(1)),
5234 want: addr(uint(0)),
5235 }, {
5236 name: jsontest.Name("Uints/Uint"),
5237 inBuf: `1`,
5238 inVal: addr(uint(0)),
5239 want: addr(uint(1)),
5240 }, {
5241 name: jsontest.Name("Uints/Uint8/Min"),
5242 inBuf: `0`,
5243 inVal: addr(uint8(1)),
5244 want: addr(uint8(0)),
5245 }, {
5246 name: jsontest.Name("Uints/Uint8/Max"),
5247 inBuf: `255`,
5248 inVal: addr(uint8(0)),
5249 want: addr(uint8(255)),
5250 }, {
5251 name: jsontest.Name("Uints/Uint8/MaxOverflow"),
5252 inBuf: `256`,
5253 inVal: addr(uint8(1)),
5254 want: addr(uint8(1)),
5255 wantErr: EU(strconv.ErrRange).withVal(`256`).withType('0', T[uint8]()),
5256 }, {
5257 name: jsontest.Name("Uints/Uint16/Min"),
5258 inBuf: `0`,
5259 inVal: addr(uint16(1)),
5260 want: addr(uint16(0)),
5261 }, {
5262 name: jsontest.Name("Uints/Uint16/Max"),
5263 inBuf: `65535`,
5264 inVal: addr(uint16(0)),
5265 want: addr(uint16(65535)),
5266 }, {
5267 name: jsontest.Name("Uints/Uint16/MaxOverflow"),
5268 inBuf: `65536`,
5269 inVal: addr(uint16(1)),
5270 want: addr(uint16(1)),
5271 wantErr: EU(strconv.ErrRange).withVal(`65536`).withType('0', T[uint16]()),
5272 }, {
5273 name: jsontest.Name("Uints/Uint32/Min"),
5274 inBuf: `0`,
5275 inVal: addr(uint32(1)),
5276 want: addr(uint32(0)),
5277 }, {
5278 name: jsontest.Name("Uints/Uint32/Max"),
5279 inBuf: `4294967295`,
5280 inVal: addr(uint32(0)),
5281 want: addr(uint32(4294967295)),
5282 }, {
5283 name: jsontest.Name("Uints/Uint32/MaxOverflow"),
5284 inBuf: `4294967296`,
5285 inVal: addr(uint32(1)),
5286 want: addr(uint32(1)),
5287 wantErr: EU(strconv.ErrRange).withVal(`4294967296`).withType('0', T[uint32]()),
5288 }, {
5289 name: jsontest.Name("Uints/Uint64/Min"),
5290 inBuf: `0`,
5291 inVal: addr(uint64(1)),
5292 want: addr(uint64(0)),
5293 }, {
5294 name: jsontest.Name("Uints/Uint64/Max"),
5295 inBuf: `18446744073709551615`,
5296 inVal: addr(uint64(0)),
5297 want: addr(uint64(18446744073709551615)),
5298 }, {
5299 name: jsontest.Name("Uints/Uint64/MaxOverflow"),
5300 inBuf: `18446744073709551616`,
5301 inVal: addr(uint64(1)),
5302 want: addr(uint64(1)),
5303 wantErr: EU(strconv.ErrRange).withVal(`18446744073709551616`).withType('0', T[uint64]()),
5304 }, {
5305 name: jsontest.Name("Uints/Uintptr"),
5306 inBuf: `1`,
5307 inVal: addr(uintptr(0)),
5308 want: addr(uintptr(1)),
5309 }, {
5310 name: jsontest.Name("Uints/Named"),
5311 inBuf: `6464`,
5312 inVal: addr(namedUint64(0)),
5313 want: addr(namedUint64(6464)),
5314 }, {
5315 name: jsontest.Name("Uints/Stringified"),
5316 opts: []Options{StringifyNumbers(true)},
5317 inBuf: `"6464"`,
5318 inVal: new(uint),
5319 want: addr(uint(6464)),
5320 }, {
5321 name: jsontest.Name("Uints/Stringified/Invalid"),
5322 opts: []Options{StringifyNumbers(true)},
5323 inBuf: `6464`,
5324 inVal: new(uint),
5325 want: new(uint),
5326 wantErr: EU(nil).withType('0', T[uint]()),
5327 }, {
5328 name: jsontest.Name("Uints/Stringified/LeadingZero"),
5329 opts: []Options{StringifyNumbers(true)},
5330 inBuf: `"00"`,
5331 inVal: addr(uint(1)),
5332 want: addr(uint(1)),
5333 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[uint]()),
5334 }, {
5335 name: jsontest.Name("Uints/Escaped"),
5336 opts: []Options{StringifyNumbers(true)},
5337 inBuf: `"\u0036\u0034\u0036\u0034"`,
5338 inVal: new(uint),
5339 want: addr(uint(6464)),
5340 }, {
5341 name: jsontest.Name("Uints/Invalid/NegativeOne"),
5342 inBuf: `-1`,
5343 inVal: addr(uint(1)),
5344 want: addr(uint(1)),
5345 wantErr: EU(strconv.ErrSyntax).withVal(`-1`).withType('0', T[uint]()),
5346 }, {
5347 name: jsontest.Name("Uints/Invalid/NegativeZero"),
5348 inBuf: `-0`,
5349 inVal: addr(uint(1)),
5350 want: addr(uint(1)),
5351 wantErr: EU(strconv.ErrSyntax).withVal(`-0`).withType('0', T[uint]()),
5352 }, {
5353 name: jsontest.Name("Uints/Invalid/Fraction"),
5354 inBuf: `1.0`,
5355 inVal: addr(uint(10)),
5356 want: addr(uint(10)),
5357 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[uint]()),
5358 }, {
5359 name: jsontest.Name("Uints/Invalid/Exponent"),
5360 inBuf: `1e0`,
5361 inVal: addr(uint(10)),
5362 want: addr(uint(10)),
5363 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[uint]()),
5364 }, {
5365 name: jsontest.Name("Uints/Invalid/StringifiedFraction"),
5366 opts: []Options{StringifyNumbers(true)},
5367 inBuf: `"1.0"`,
5368 inVal: addr(uint(10)),
5369 want: addr(uint(10)),
5370 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[uint]()),
5371 }, {
5372 name: jsontest.Name("Uints/Invalid/StringifiedExponent"),
5373 opts: []Options{StringifyNumbers(true)},
5374 inBuf: `"1e0"`,
5375 inVal: addr(uint(10)),
5376 want: addr(uint(10)),
5377 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[uint]()),
5378 }, {
5379 name: jsontest.Name("Uints/Invalid/Overflow"),
5380 inBuf: `100000000000000000000000000000`,
5381 inVal: addr(uint(1)),
5382 want: addr(uint(1)),
5383 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[uint]()),
5384 }, {
5385 name: jsontest.Name("Uints/Invalid/OverflowSyntax"),
5386 opts: []Options{StringifyNumbers(true)},
5387 inBuf: `"100000000000000000000000000000x"`,
5388 inVal: addr(uint(1)),
5389 want: addr(uint(1)),
5390 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[uint]()),
5391 }, {
5392 name: jsontest.Name("Uints/Invalid/Whitespace"),
5393 opts: []Options{StringifyNumbers(true)},
5394 inBuf: `"0 "`,
5395 inVal: addr(uint(1)),
5396 want: addr(uint(1)),
5397 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[uint]()),
5398 }, {
5399 name: jsontest.Name("Uints/Invalid/Bool"),
5400 inBuf: `true`,
5401 inVal: addr(uint(1)),
5402 want: addr(uint(1)),
5403 wantErr: EU(nil).withType('t', T[uint]()),
5404 }, {
5405 name: jsontest.Name("Uints/Invalid/String"),
5406 inBuf: `"0"`,
5407 inVal: addr(uint(1)),
5408 want: addr(uint(1)),
5409 wantErr: EU(nil).withType('"', T[uint]()),
5410 }, {
5411 name: jsontest.Name("Uints/Invalid/Object"),
5412 inBuf: `{}`,
5413 inVal: addr(uint(1)),
5414 want: addr(uint(1)),
5415 wantErr: EU(nil).withType('{', T[uint]()),
5416 }, {
5417 name: jsontest.Name("Uints/Invalid/Array"),
5418 inBuf: `[]`,
5419 inVal: addr(uint(1)),
5420 want: addr(uint(1)),
5421 wantErr: EU(nil).withType('[', T[uint]()),
5422 }, {
5423 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
5424 opts: []Options{invalidFormatOption},
5425 inBuf: `1`,
5426 inVal: addr(uint(0)),
5427 want: addr(uint(1)),
5428 }, {
5429 name: jsontest.Name("Floats/Null"),
5430 inBuf: `null`,
5431 inVal: addr(float64(64.64)),
5432 want: addr(float64(0)),
5433 }, {
5434 name: jsontest.Name("Floats/Float32/Pi"),
5435 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5436 inVal: addr(float32(32.32)),
5437 want: addr(float32(math.Pi)),
5438 }, {
5439 name: jsontest.Name("Floats/Float32/Underflow"),
5440 inBuf: `1e-1000`,
5441 inVal: addr(float32(32.32)),
5442 want: addr(float32(0)),
5443 }, {
5444 name: jsontest.Name("Floats/Float32/Overflow"),
5445 inBuf: `-1e1000`,
5446 inVal: addr(float32(32.32)),
5447 want: addr(float32(-math.MaxFloat32)),
5448 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float32]()),
5449 }, {
5450 name: jsontest.Name("Floats/Float64/Pi"),
5451 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5452 inVal: addr(float64(64.64)),
5453 want: addr(float64(math.Pi)),
5454 }, {
5455 name: jsontest.Name("Floats/Float64/Underflow"),
5456 inBuf: `1e-1000`,
5457 inVal: addr(float64(64.64)),
5458 want: addr(float64(0)),
5459 }, {
5460 name: jsontest.Name("Floats/Float64/Overflow"),
5461 inBuf: `-1e1000`,
5462 inVal: addr(float64(64.64)),
5463 want: addr(float64(-math.MaxFloat64)),
5464 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float64]()),
5465 }, {
5466 name: jsontest.Name("Floats/Any/Overflow"),
5467 inBuf: `1e1000`,
5468 inVal: new(any),
5469 want: addr(any(float64(math.MaxFloat64))),
5470 wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float64]()),
5471 }, {
5472 name: jsontest.Name("Floats/Named"),
5473 inBuf: `64.64`,
5474 inVal: addr(namedFloat64(0)),
5475 want: addr(namedFloat64(64.64)),
5476 }, {
5477 name: jsontest.Name("Floats/Stringified"),
5478 opts: []Options{StringifyNumbers(true)},
5479 inBuf: `"64.64"`,
5480 inVal: new(float64),
5481 want: addr(float64(64.64)),
5482 }, {
5483 name: jsontest.Name("Floats/Stringified/Invalid"),
5484 opts: []Options{StringifyNumbers(true)},
5485 inBuf: `64.64`,
5486 inVal: new(float64),
5487 want: new(float64),
5488 wantErr: EU(nil).withType('0', T[float64]()),
5489 }, {
5490 name: jsontest.Name("Floats/Escaped"),
5491 opts: []Options{StringifyNumbers(true)},
5492 inBuf: `"\u0036\u0034\u002e\u0036\u0034"`,
5493 inVal: new(float64),
5494 want: addr(float64(64.64)),
5495 }, {
5496 name: jsontest.Name("Floats/Invalid/NaN"),
5497 opts: []Options{StringifyNumbers(true)},
5498 inBuf: `"NaN"`,
5499 inVal: addr(float64(64.64)),
5500 want: addr(float64(64.64)),
5501 wantErr: EU(strconv.ErrSyntax).withVal(`"NaN"`).withType('"', float64Type),
5502 }, {
5503 name: jsontest.Name("Floats/Invalid/Infinity"),
5504 opts: []Options{StringifyNumbers(true)},
5505 inBuf: `"Infinity"`,
5506 inVal: addr(float64(64.64)),
5507 want: addr(float64(64.64)),
5508 wantErr: EU(strconv.ErrSyntax).withVal(`"Infinity"`).withType('"', float64Type),
5509 }, {
5510 name: jsontest.Name("Floats/Invalid/Whitespace"),
5511 opts: []Options{StringifyNumbers(true)},
5512 inBuf: `"1 "`,
5513 inVal: addr(float64(64.64)),
5514 want: addr(float64(64.64)),
5515 wantErr: EU(strconv.ErrSyntax).withVal(`"1 "`).withType('"', float64Type),
5516 }, {
5517 name: jsontest.Name("Floats/Invalid/GoSyntax"),
5518 opts: []Options{StringifyNumbers(true)},
5519 inBuf: `"1p-2"`,
5520 inVal: addr(float64(64.64)),
5521 want: addr(float64(64.64)),
5522 wantErr: EU(strconv.ErrSyntax).withVal(`"1p-2"`).withType('"', float64Type),
5523 }, {
5524 name: jsontest.Name("Floats/Invalid/Bool"),
5525 inBuf: `true`,
5526 inVal: addr(float64(64.64)),
5527 want: addr(float64(64.64)),
5528 wantErr: EU(nil).withType('t', float64Type),
5529 }, {
5530 name: jsontest.Name("Floats/Invalid/String"),
5531 inBuf: `"0"`,
5532 inVal: addr(float64(64.64)),
5533 want: addr(float64(64.64)),
5534 wantErr: EU(nil).withType('"', float64Type),
5535 }, {
5536 name: jsontest.Name("Floats/Invalid/Object"),
5537 inBuf: `{}`,
5538 inVal: addr(float64(64.64)),
5539 want: addr(float64(64.64)),
5540 wantErr: EU(nil).withType('{', float64Type),
5541 }, {
5542 name: jsontest.Name("Floats/Invalid/Array"),
5543 inBuf: `[]`,
5544 inVal: addr(float64(64.64)),
5545 want: addr(float64(64.64)),
5546 wantErr: EU(nil).withType('[', float64Type),
5547 }, {
5548 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
5549 opts: []Options{invalidFormatOption},
5550 inBuf: `1`,
5551 inVal: addr(float64(0)),
5552 want: addr(float64(1)),
5553 }, {
5554 name: jsontest.Name("Maps/Null"),
5555 inBuf: `null`,
5556 inVal: addr(map[string]string{"key": "value"}),
5557 want: new(map[string]string),
5558 }, {
5559 name: jsontest.Name("Maps/InvalidKey/Bool"),
5560 inBuf: `{"true":"false"}`,
5561 inVal: new(map[bool]bool),
5562 want: addr(make(map[bool]bool)),
5563 wantErr: EU(nil).withPos(`{`, "/true").withType('"', boolType),
5564 }, {
5565 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
5566 inBuf: `{"true":"false"}`,
5567 inVal: new(map[namedBool]bool),
5568 want: addr(make(map[namedBool]bool)),
5569 wantErr: EU(nil).withPos(`{`, "/true").withType('"', T[namedBool]()),
5570 }, {
5571 name: jsontest.Name("Maps/InvalidKey/Array"),
5572 inBuf: `{"key":"value"}`,
5573 inVal: new(map[[1]string]string),
5574 want: addr(make(map[[1]string]string)),
5575 wantErr: EU(nil).withPos(`{`, "/key").withType('"', T[[1]string]()),
5576 }, {
5577 name: jsontest.Name("Maps/InvalidKey/Channel"),
5578 inBuf: `{"key":"value"}`,
5579 inVal: new(map[chan string]string),
5580 want: addr(make(map[chan string]string)),
5581 wantErr: EU(nil).withPos(`{`, "").withType(0, T[chan string]()),
5582 }, {
5583 name: jsontest.Name("Maps/ValidKey/Int"),
5584 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5585 inVal: new(map[int]int),
5586 want: addr(map[int]int{0: 0, -1: 1, 2: 2, -3: 3}),
5587 }, {
5588 name: jsontest.Name("Maps/ValidKey/NamedInt"),
5589 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5590 inVal: new(map[namedInt64]int),
5591 want: addr(map[namedInt64]int{0: 0, -1: 1, 2: 2, -3: 3}),
5592 }, {
5593 name: jsontest.Name("Maps/ValidKey/Uint"),
5594 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5595 inVal: new(map[uint]uint),
5596 want: addr(map[uint]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5597 }, {
5598 name: jsontest.Name("Maps/ValidKey/NamedUint"),
5599 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5600 inVal: new(map[namedUint64]uint),
5601 want: addr(map[namedUint64]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5602 }, {
5603 name: jsontest.Name("Maps/ValidKey/Float"),
5604 inBuf: `{"1.234":1.234,"12.34":12.34,"123.4":123.4}`,
5605 inVal: new(map[float64]float64),
5606 want: addr(map[float64]float64{1.234: 1.234, 12.34: 12.34, 123.4: 123.4}),
5607 }, {
5608 name: jsontest.Name("Maps/DuplicateName/Int"),
5609 inBuf: `{"0":1,"-0":-1}`,
5610 inVal: new(map[int]int),
5611 want: addr(map[int]int{0: 1}),
5612 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5613 }, {
5614 name: jsontest.Name("Maps/DuplicateName/Int/MergeWithLegacySemantics"),
5615 opts: []Options{jsonflags.MergeWithLegacySemantics | 1},
5616 inBuf: `{"0":1,"-0":-1}`,
5617 inVal: new(map[int]int),
5618 want: addr(map[int]int{0: 1}),
5619 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5620 }, {
5621 name: jsontest.Name("Maps/DuplicateName/Int/AllowDuplicateNames"),
5622 opts: []Options{jsontext.AllowDuplicateNames(true)},
5623 inBuf: `{"0":1,"-0":-1}`,
5624 inVal: new(map[int]int),
5625 want: addr(map[int]int{0: -1}),
5626 }, {
5627 name: jsontest.Name("Maps/DuplicateName/Int/OverwriteExisting"),
5628 inBuf: `{"-0":-1}`,
5629 inVal: addr(map[int]int{0: 1}),
5630 want: addr(map[int]int{0: -1}),
5631 }, {
5632 name: jsontest.Name("Maps/DuplicateName/Float"),
5633 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5634 inVal: new(map[float64]string),
5635 want: addr(map[float64]string{1: "1.0"}),
5636 wantErr: newDuplicateNameError("", []byte(`"1"`), len64(`{"1.0":"1.0",`)),
5637 }, {
5638 name: jsontest.Name("Maps/DuplicateName/Float/AllowDuplicateNames"),
5639 opts: []Options{jsontext.AllowDuplicateNames(true)},
5640 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5641 inVal: new(map[float64]string),
5642 want: addr(map[float64]string{1: "1e0"}),
5643 }, {
5644 name: jsontest.Name("Maps/DuplicateName/Float/OverwriteExisting"),
5645 inBuf: `{"1.0":"1.0"}`,
5646 inVal: addr(map[float64]string{1: "1"}),
5647 want: addr(map[float64]string{1: "1.0"}),
5648 }, {
5649 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
5650 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5651 inVal: new(map[nocaseString]string),
5652 want: addr(map[nocaseString]string{"hello": "hello"}),
5653 wantErr: newDuplicateNameError("", []byte(`"HELLO"`), len64(`{"hello":"hello",`)),
5654 }, {
5655 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
5656 opts: []Options{jsontext.AllowDuplicateNames(true)},
5657 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5658 inVal: new(map[nocaseString]string),
5659 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5660 }, {
5661 name: jsontest.Name("Maps/DuplicateName/NoCaseString/OverwriteExisting"),
5662 opts: []Options{jsontext.AllowDuplicateNames(true)},
5663 inBuf: `{"HELLO":"HELLO"}`,
5664 inVal: addr(map[nocaseString]string{"hello": "hello"}),
5665 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5666 }, {
5667 name: jsontest.Name("Maps/ValidKey/Interface"),
5668 inBuf: `{"false":"false","true":"true","string":"string","0":"0","[]":"[]","{}":"{}"}`,
5669 inVal: new(map[any]string),
5670 want: addr(map[any]string{
5671 "false": "false",
5672 "true": "true",
5673 "string": "string",
5674 "0": "0",
5675 "[]": "[]",
5676 "{}": "{}",
5677 }),
5678 }, {
5679 name: jsontest.Name("Maps/InvalidValue/Channel"),
5680 inBuf: `{"key":"value"}`,
5681 inVal: new(map[string]chan string),
5682 want: addr(map[string]chan string{
5683 "key": nil,
5684 }),
5685 wantErr: EU(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
5686 }, {
5687 name: jsontest.Name("Maps/RecursiveMap"),
5688 inBuf: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
5689 inVal: new(recursiveMap),
5690 want: addr(recursiveMap{
5691 "fizz": {
5692 "foo": {},
5693 "bar": {},
5694 },
5695 "buzz": {},
5696 }),
5697 }, {
5698
5699
5700
5701 name: jsontest.Name("Maps/Merge"),
5702 opts: []Options{jsontext.AllowDuplicateNames(true)},
5703 inBuf: `{"k1":{"k2":"v2"},"k2":{"k1":"v1"},"k2":{"k2":"v2"}}`,
5704 inVal: addr(map[string]map[string]string{
5705 "k1": {"k1": "v1"},
5706 }),
5707 want: addr(map[string]map[string]string{
5708 "k1": {"k1": "v1", "k2": "v2"},
5709 "k2": {"k1": "v1", "k2": "v2"},
5710 }),
5711 }, {
5712 name: jsontest.Name("Maps/Invalid/Bool"),
5713 inBuf: `true`,
5714 inVal: addr(map[string]string{"key": "value"}),
5715 want: addr(map[string]string{"key": "value"}),
5716 wantErr: EU(nil).withType('t', T[map[string]string]()),
5717 }, {
5718 name: jsontest.Name("Maps/Invalid/String"),
5719 inBuf: `""`,
5720 inVal: addr(map[string]string{"key": "value"}),
5721 want: addr(map[string]string{"key": "value"}),
5722 wantErr: EU(nil).withType('"', T[map[string]string]()),
5723 }, {
5724 name: jsontest.Name("Maps/Invalid/Number"),
5725 inBuf: `0`,
5726 inVal: addr(map[string]string{"key": "value"}),
5727 want: addr(map[string]string{"key": "value"}),
5728 wantErr: EU(nil).withType('0', T[map[string]string]()),
5729 }, {
5730 name: jsontest.Name("Maps/Invalid/Array"),
5731 inBuf: `[]`,
5732 inVal: addr(map[string]string{"key": "value"}),
5733 want: addr(map[string]string{"key": "value"}),
5734 wantErr: EU(nil).withType('[', T[map[string]string]()),
5735 }, {
5736 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
5737 opts: []Options{invalidFormatOption},
5738 inBuf: `{"hello":"goodbye"}`,
5739 inVal: addr(map[string]string{}),
5740 want: addr(map[string]string{"hello": "goodbye"}),
5741 }, {
5742 name: jsontest.Name("Structs/Null"),
5743 inBuf: `null`,
5744 inVal: addr(structAll{String: "something"}),
5745 want: addr(structAll{}),
5746 }, {
5747 name: jsontest.Name("Structs/Empty"),
5748 inBuf: `{}`,
5749 inVal: addr(structAll{
5750 String: "hello",
5751 Map: map[string]string{},
5752 Slice: []string{},
5753 }),
5754 want: addr(structAll{
5755 String: "hello",
5756 Map: map[string]string{},
5757 Slice: []string{},
5758 }),
5759 }, {
5760 name: jsontest.Name("Structs/Normal"),
5761 inBuf: `{
5762 "Bool": true,
5763 "String": "hello",
5764 "Bytes": "AQID",
5765 "Int": -64,
5766 "Uint": 64,
5767 "Float": 3.14159,
5768 "Map": {"key": "value"},
5769 "StructScalars": {
5770 "Bool": true,
5771 "String": "hello",
5772 "Bytes": "AQID",
5773 "Int": -64,
5774 "Uint": 64,
5775 "Float": 3.14159
5776 },
5777 "StructMaps": {
5778 "MapBool": {"": true},
5779 "MapString": {"": "hello"},
5780 "MapBytes": {"": "AQID"},
5781 "MapInt": {"": -64},
5782 "MapUint": {"": 64},
5783 "MapFloat": {"": 3.14159}
5784 },
5785 "StructSlices": {
5786 "SliceBool": [true],
5787 "SliceString": ["hello"],
5788 "SliceBytes": ["AQID"],
5789 "SliceInt": [-64],
5790 "SliceUint": [64],
5791 "SliceFloat": [3.14159]
5792 },
5793 "Slice": ["fizz","buzz"],
5794 "Array": ["goodbye"],
5795 "Pointer": {},
5796 "Interface": null
5797 }`,
5798 inVal: new(structAll),
5799 want: addr(structAll{
5800 Bool: true,
5801 String: "hello",
5802 Bytes: []byte{1, 2, 3},
5803 Int: -64,
5804 Uint: +64,
5805 Float: 3.14159,
5806 Map: map[string]string{"key": "value"},
5807 StructScalars: structScalars{
5808 Bool: true,
5809 String: "hello",
5810 Bytes: []byte{1, 2, 3},
5811 Int: -64,
5812 Uint: +64,
5813 Float: 3.14159,
5814 },
5815 StructMaps: structMaps{
5816 MapBool: map[string]bool{"": true},
5817 MapString: map[string]string{"": "hello"},
5818 MapBytes: map[string][]byte{"": {1, 2, 3}},
5819 MapInt: map[string]int64{"": -64},
5820 MapUint: map[string]uint64{"": +64},
5821 MapFloat: map[string]float64{"": 3.14159},
5822 },
5823 StructSlices: structSlices{
5824 SliceBool: []bool{true},
5825 SliceString: []string{"hello"},
5826 SliceBytes: [][]byte{{1, 2, 3}},
5827 SliceInt: []int64{-64},
5828 SliceUint: []uint64{+64},
5829 SliceFloat: []float64{3.14159},
5830 },
5831 Slice: []string{"fizz", "buzz"},
5832 Array: [1]string{"goodbye"},
5833 Pointer: new(structAll),
5834 }),
5835 }, {
5836 name: jsontest.Name("Structs/Merge"),
5837 inBuf: `{
5838 "Bool": false,
5839 "String": "goodbye",
5840 "Int": -64,
5841 "Float": 3.14159,
5842 "Map": {"k2": "v2"},
5843 "StructScalars": {
5844 "Bool": true,
5845 "String": "hello",
5846 "Bytes": "AQID",
5847 "Int": -64
5848 },
5849 "StructMaps": {
5850 "MapBool": {"": true},
5851 "MapString": {"": "hello"},
5852 "MapBytes": {"": "AQID"},
5853 "MapInt": {"": -64},
5854 "MapUint": {"": 64},
5855 "MapFloat": {"": 3.14159}
5856 },
5857 "StructSlices": {
5858 "SliceString": ["hello"],
5859 "SliceBytes": ["AQID"],
5860 "SliceInt": [-64],
5861 "SliceUint": [64]
5862 },
5863 "Slice": ["fizz","buzz"],
5864 "Array": ["goodbye"],
5865 "Pointer": {},
5866 "Interface": {"k2":"v2"}
5867 }`,
5868 inVal: addr(structAll{
5869 Bool: true,
5870 String: "hello",
5871 Bytes: []byte{1, 2, 3},
5872 Uint: +64,
5873 Float: math.NaN(),
5874 Map: map[string]string{"k1": "v1"},
5875 StructScalars: structScalars{
5876 String: "hello",
5877 Bytes: make([]byte, 2, 4),
5878 Uint: +64,
5879 Float: 3.14159,
5880 },
5881 StructMaps: structMaps{
5882 MapBool: map[string]bool{"": false},
5883 MapBytes: map[string][]byte{"": {}},
5884 MapInt: map[string]int64{"": 123},
5885 MapFloat: map[string]float64{"": math.Inf(+1)},
5886 },
5887 StructSlices: structSlices{
5888 SliceBool: []bool{true},
5889 SliceBytes: [][]byte{nil, nil},
5890 SliceInt: []int64{-123},
5891 SliceUint: []uint64{+123},
5892 SliceFloat: []float64{3.14159},
5893 },
5894 Slice: []string{"buzz", "fizz", "gizz"},
5895 Array: [1]string{"hello"},
5896 Pointer: new(structAll),
5897 Interface: map[string]string{"k1": "v1"},
5898 }),
5899 want: addr(structAll{
5900 Bool: false,
5901 String: "goodbye",
5902 Bytes: []byte{1, 2, 3},
5903 Int: -64,
5904 Uint: +64,
5905 Float: 3.14159,
5906 Map: map[string]string{"k1": "v1", "k2": "v2"},
5907 StructScalars: structScalars{
5908 Bool: true,
5909 String: "hello",
5910 Bytes: []byte{1, 2, 3},
5911 Int: -64,
5912 Uint: +64,
5913 Float: 3.14159,
5914 },
5915 StructMaps: structMaps{
5916 MapBool: map[string]bool{"": true},
5917 MapString: map[string]string{"": "hello"},
5918 MapBytes: map[string][]byte{"": {1, 2, 3}},
5919 MapInt: map[string]int64{"": -64},
5920 MapUint: map[string]uint64{"": +64},
5921 MapFloat: map[string]float64{"": 3.14159},
5922 },
5923 StructSlices: structSlices{
5924 SliceBool: []bool{true},
5925 SliceString: []string{"hello"},
5926 SliceBytes: [][]byte{{1, 2, 3}},
5927 SliceInt: []int64{-64},
5928 SliceUint: []uint64{+64},
5929 SliceFloat: []float64{3.14159},
5930 },
5931 Slice: []string{"fizz", "buzz"},
5932 Array: [1]string{"goodbye"},
5933 Pointer: new(structAll),
5934 Interface: map[string]string{"k1": "v1", "k2": "v2"},
5935 }),
5936 }, {
5937 name: jsontest.Name("Structs/Stringified/Normal"),
5938 inBuf: `{
5939 "Bool": true,
5940 "String": "hello",
5941 "Bytes": "AQID",
5942 "Int": "-64",
5943 "Uint": "64",
5944 "Float": "3.14159",
5945 "Map": {"key": "value"},
5946 "StructScalars": {
5947 "Bool": true,
5948 "String": "hello",
5949 "Bytes": "AQID",
5950 "Int": "-64",
5951 "Uint": "64",
5952 "Float": "3.14159"
5953 },
5954 "StructMaps": {
5955 "MapBool": {"": true},
5956 "MapString": {"": "hello"},
5957 "MapBytes": {"": "AQID"},
5958 "MapInt": {"": "-64"},
5959 "MapUint": {"": "64"},
5960 "MapFloat": {"": "3.14159"}
5961 },
5962 "StructSlices": {
5963 "SliceBool": [true],
5964 "SliceString": ["hello"],
5965 "SliceBytes": ["AQID"],
5966 "SliceInt": ["-64"],
5967 "SliceUint": ["64"],
5968 "SliceFloat": ["3.14159"]
5969 },
5970 "Slice": ["fizz","buzz"],
5971 "Array": ["goodbye"],
5972 "Pointer": {},
5973 "Interface": null
5974 }`,
5975 inVal: new(structStringifiedAll),
5976 want: addr(structStringifiedAll{
5977 Bool: true,
5978 String: "hello",
5979 Bytes: []byte{1, 2, 3},
5980 Int: -64,
5981 Uint: +64,
5982 Float: 3.14159,
5983 Map: map[string]string{"key": "value"},
5984 StructScalars: structScalars{
5985 Bool: true,
5986 String: "hello",
5987 Bytes: []byte{1, 2, 3},
5988 Int: -64,
5989 Uint: +64,
5990 Float: 3.14159,
5991 },
5992 StructMaps: structMaps{
5993 MapBool: map[string]bool{"": true},
5994 MapString: map[string]string{"": "hello"},
5995 MapBytes: map[string][]byte{"": {1, 2, 3}},
5996 MapInt: map[string]int64{"": -64},
5997 MapUint: map[string]uint64{"": +64},
5998 MapFloat: map[string]float64{"": 3.14159},
5999 },
6000 StructSlices: structSlices{
6001 SliceBool: []bool{true},
6002 SliceString: []string{"hello"},
6003 SliceBytes: [][]byte{{1, 2, 3}},
6004 SliceInt: []int64{-64},
6005 SliceUint: []uint64{+64},
6006 SliceFloat: []float64{3.14159},
6007 },
6008 Slice: []string{"fizz", "buzz"},
6009 Array: [1]string{"goodbye"},
6010 Pointer: new(structStringifiedAll),
6011 }),
6012 }, {
6013 name: jsontest.Name("Structs/Stringified/String"),
6014 inBuf: `{
6015 "Bool": true,
6016 "String": "hello",
6017 "Bytes": "AQID",
6018 "Int": "-64",
6019 "Uint": "64",
6020 "Float": "3.14159",
6021 "Map": {"key": "value"},
6022 "StructScalars": {
6023 "Bool": true,
6024 "String": "hello",
6025 "Bytes": "AQID",
6026 "Int": "-64",
6027 "Uint": "64",
6028 "Float": "3.14159"
6029 },
6030 "StructMaps": {
6031 "MapBool": {"": true},
6032 "MapString": {"": "hello"},
6033 "MapBytes": {"": "AQID"},
6034 "MapInt": {"": "-64"},
6035 "MapUint": {"": "64"},
6036 "MapFloat": {"": "3.14159"}
6037 },
6038 "StructSlices": {
6039 "SliceBool": [true],
6040 "SliceString": ["hello"],
6041 "SliceBytes": ["AQID"],
6042 "SliceInt": ["-64"],
6043 "SliceUint": ["64"],
6044 "SliceFloat": ["3.14159"]
6045 },
6046 "Slice": ["fizz","buzz"],
6047 "Array": ["goodbye"],
6048 "Pointer": {},
6049 "Interface": null
6050 }`,
6051 inVal: new(structStringifiedAll),
6052 want: addr(structStringifiedAll{
6053 Bool: true,
6054 String: "hello",
6055 Bytes: []byte{1, 2, 3},
6056 Int: -64,
6057 Uint: +64,
6058 Float: 3.14159,
6059 Map: map[string]string{"key": "value"},
6060 StructScalars: structScalars{
6061 Bool: true,
6062 String: "hello",
6063 Bytes: []byte{1, 2, 3},
6064 Int: -64,
6065 Uint: +64,
6066 Float: 3.14159,
6067 },
6068 StructMaps: structMaps{
6069 MapBool: map[string]bool{"": true},
6070 MapString: map[string]string{"": "hello"},
6071 MapBytes: map[string][]byte{"": {1, 2, 3}},
6072 MapInt: map[string]int64{"": -64},
6073 MapUint: map[string]uint64{"": +64},
6074 MapFloat: map[string]float64{"": 3.14159},
6075 },
6076 StructSlices: structSlices{
6077 SliceBool: []bool{true},
6078 SliceString: []string{"hello"},
6079 SliceBytes: [][]byte{{1, 2, 3}},
6080 SliceInt: []int64{-64},
6081 SliceUint: []uint64{+64},
6082 SliceFloat: []float64{3.14159},
6083 },
6084 Slice: []string{"fizz", "buzz"},
6085 Array: [1]string{"goodbye"},
6086 Pointer: new(structStringifiedAll),
6087 }),
6088 }, {
6089 name: jsontest.Name("Structs/Stringified/InvalidEmpty"),
6090 inBuf: `{"Int":""}`,
6091 inVal: new(structStringifiedAll),
6092 want: new(structStringifiedAll),
6093 wantErr: EU(strconv.ErrSyntax).withVal(`""`).withPos(`{"Int":`, "/Int").withType('"', T[int64]()),
6094 }, {
6095 name: jsontest.Name("Structs/LegacyStringified"),
6096 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6097 inBuf: `{
6098 "Bool": "true",
6099 "String": "\"hello\"",
6100 "Bytes": "AQID",
6101 "Int": "-64",
6102 "Uint": "64",
6103 "Float": "3.14159",
6104 "Map": {"key": "value"},
6105 "StructScalars": {
6106 "Bool": true,
6107 "String": "hello",
6108 "Bytes": "AQID",
6109 "Int": -64,
6110 "Uint": 64,
6111 "Float": 3.14159
6112 },
6113 "StructMaps": {
6114 "MapBool": {"": true},
6115 "MapString": {"": "hello"},
6116 "MapBytes": {"": "AQID"},
6117 "MapInt": {"": -64},
6118 "MapUint": {"": 64},
6119 "MapFloat": {"": 3.14159}
6120 },
6121 "StructSlices": {
6122 "SliceBool": [true],
6123 "SliceString": ["hello"],
6124 "SliceBytes": ["AQID"],
6125 "SliceInt": [-64],
6126 "SliceUint": [64],
6127 "SliceFloat": [3.14159]
6128 },
6129 "Slice": ["fizz", "buzz"],
6130 "Array": ["goodbye"]
6131 }`,
6132 inVal: new(structStringifiedAll),
6133 want: addr(structStringifiedAll{
6134 Bool: true,
6135 String: "hello",
6136 Bytes: []byte{1, 2, 3},
6137 Int: -64,
6138 Uint: +64,
6139 Float: 3.14159,
6140 Map: map[string]string{"key": "value"},
6141 StructScalars: structScalars{
6142 Bool: true,
6143 String: "hello",
6144 Bytes: []byte{1, 2, 3},
6145 Int: -64,
6146 Uint: +64,
6147 Float: 3.14159,
6148 },
6149 StructMaps: structMaps{
6150 MapBool: map[string]bool{"": true},
6151 MapString: map[string]string{"": "hello"},
6152 MapBytes: map[string][]byte{"": {1, 2, 3}},
6153 MapInt: map[string]int64{"": -64},
6154 MapUint: map[string]uint64{"": +64},
6155 MapFloat: map[string]float64{"": 3.14159},
6156 },
6157 StructSlices: structSlices{
6158 SliceBool: []bool{true},
6159 SliceString: []string{"hello"},
6160 SliceBytes: [][]byte{{1, 2, 3}},
6161 SliceInt: []int64{-64},
6162 SliceUint: []uint64{+64},
6163 SliceFloat: []float64{3.14159},
6164 },
6165 Slice: []string{"fizz", "buzz"},
6166 Array: [1]string{"goodbye"},
6167 }),
6168 }, {
6169 name: jsontest.Name("Structs/LegacyStringified/InvalidBool"),
6170 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6171 inBuf: `{"Bool": true}`,
6172 inVal: new(structStringifiedAll),
6173 wantErr: EU(nil).withPos(`{"Bool": `, "/Bool").withType('t', T[bool]()),
6174 }, {
6175 name: jsontest.Name("Structs/LegacyStringified/InvalidString"),
6176 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6177 inBuf: `{"String": "string"}`,
6178 inVal: new(structStringifiedAll),
6179 wantErr: EU(newInvalidCharacterError("s", "at start of string (expecting '\"')", 0, "")).
6180 withPos(`{"String": `, "/String").withType('"', T[string]()),
6181 }, {
6182 name: jsontest.Name("Structs/Format/Bytes"),
6183 inBuf: `{
6184 "Base16": "0123456789abcdef",
6185 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
6186 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
6187 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
6188 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
6189 "Array": [1, 2, 3, 4]
6190 }`,
6191 inVal: new(structFormatBytes),
6192 want: addr(structFormatBytes{
6193 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
6194 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6195 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6196 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߿"),
6197 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߿"),
6198 Array: []byte{1, 2, 3, 4},
6199 }),
6200 }, {
6201 name: jsontest.Name("Structs/Format/ArrayBytes"),
6202 inBuf: `{
6203 "Base16": "01020304",
6204 "Base32": "AEBAGBA=",
6205 "Base32Hex": "0410610=",
6206 "Base64": "AQIDBA==",
6207 "Base64URL": "AQIDBA==",
6208 "Array": [1, 2, 3, 4],
6209 "Default": "AQIDBA=="
6210 }`,
6211 inVal: new(structFormatArrayBytes),
6212 want: addr(structFormatArrayBytes{
6213 Base16: [4]byte{1, 2, 3, 4},
6214 Base32: [4]byte{1, 2, 3, 4},
6215 Base32Hex: [4]byte{1, 2, 3, 4},
6216 Base64: [4]byte{1, 2, 3, 4},
6217 Base64URL: [4]byte{1, 2, 3, 4},
6218 Array: [4]byte{1, 2, 3, 4},
6219 Default: [4]byte{1, 2, 3, 4},
6220 }),
6221 }, {
6222 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
6223 opts: []Options{jsonflags.FormatBytesWithLegacySemantics | 1},
6224 inBuf: `{
6225 "Base16": "01020304",
6226 "Base32": "AEBAGBA=",
6227 "Base32Hex": "0410610=",
6228 "Base64": "AQIDBA==",
6229 "Base64URL": "AQIDBA==",
6230 "Array": [1, 2, 3, 4],
6231 "Default": [1, 2, 3, 4]
6232 }`,
6233 inVal: new(structFormatArrayBytes),
6234 want: addr(structFormatArrayBytes{
6235 Base16: [4]byte{1, 2, 3, 4},
6236 Base32: [4]byte{1, 2, 3, 4},
6237 Base32Hex: [4]byte{1, 2, 3, 4},
6238 Base64: [4]byte{1, 2, 3, 4},
6239 Base64URL: [4]byte{1, 2, 3, 4},
6240 Array: [4]byte{1, 2, 3, 4},
6241 Default: [4]byte{1, 2, 3, 4},
6242 }),
6243 }, {
6244 name: jsontest.Name("Structs/Format/Bytes/Array"),
6245 opts: []Options{
6246 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *byte) error {
6247 if string(b) == "true" {
6248 *v = 1
6249 } else {
6250 *v = 0
6251 }
6252 return nil
6253 })),
6254 },
6255 inBuf: `{"Array":[false,true,false,true,false,true]}`,
6256 inVal: new(struct {
6257 Array []byte `json:",format:array"`
6258 }),
6259 want: addr(struct {
6260 Array []byte `json:",format:array"`
6261 }{
6262 Array: []byte{0, 1, 0, 1, 0, 1},
6263 }),
6264 }, {
6265 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/WrongKind"),
6266 inBuf: `{"Base16": [1,2,3,4]}`,
6267 inVal: new(structFormatBytes),
6268 wantErr: EU(nil).withPos(`{"Base16": `, "/Base16").withType('[', T[[]byte]()),
6269 }, {
6270 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/AllPadding"),
6271 inBuf: `{"Base16": "===="}`,
6272 inVal: new(structFormatBytes),
6273 wantErr: EU(func() error {
6274 _, err := hex.Decode(make([]byte, 2), []byte("====="))
6275 return err
6276 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6277 }, {
6278 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/EvenPadding"),
6279 inBuf: `{"Base16": "0123456789abcdef="}`,
6280 inVal: new(structFormatBytes),
6281 wantErr: EU(func() error {
6282 _, err := hex.Decode(make([]byte, 8), []byte("0123456789abcdef="))
6283 return err
6284 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6285 }, {
6286 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/OddPadding"),
6287 inBuf: `{"Base16": "0123456789abcdef0="}`,
6288 inVal: new(structFormatBytes),
6289 wantErr: EU(func() error {
6290 _, err := hex.Decode(make([]byte, 9), []byte("0123456789abcdef0="))
6291 return err
6292 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6293 }, {
6294 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/LineFeed"),
6295 inBuf: `{"Base16": "aa\naa"}`,
6296 inVal: new(structFormatBytes),
6297 wantErr: EU(func() error {
6298 _, err := hex.Decode(make([]byte, 9), []byte("aa\naa"))
6299 return err
6300 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6301 }, {
6302 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/CarriageReturn"),
6303 inBuf: `{"Base16": "aa\raa"}`,
6304 inVal: new(structFormatBytes),
6305 wantErr: EU(func() error {
6306 _, err := hex.Decode(make([]byte, 9), []byte("aa\raa"))
6307 return err
6308 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6309 }, {
6310 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/Space"),
6311 inBuf: `{"Base16": "aa aa"}`,
6312 inVal: new(structFormatBytes),
6313 wantErr: EU(func() error {
6314 _, err := hex.Decode(make([]byte, 9), []byte("aa aa"))
6315 return err
6316 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6317 }, {
6318 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Padding"),
6319 inBuf: `[
6320 {"Base32": "NA======"},
6321 {"Base32": "NBSQ===="},
6322 {"Base32": "NBSWY==="},
6323 {"Base32": "NBSWY3A="},
6324 {"Base32": "NBSWY3DP"}
6325 ]`,
6326 inVal: new([]structFormatBytes),
6327 want: addr([]structFormatBytes{
6328 {Base32: []byte("h")},
6329 {Base32: []byte("he")},
6330 {Base32: []byte("hel")},
6331 {Base32: []byte("hell")},
6332 {Base32: []byte("hello")},
6333 }),
6334 }, {
6335 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Invalid/NoPadding"),
6336 inBuf: `[
6337 {"Base32": "NA"},
6338 {"Base32": "NBSQ"},
6339 {"Base32": "NBSWY"},
6340 {"Base32": "NBSWY3A"},
6341 {"Base32": "NBSWY3DP"}
6342 ]`,
6343 inVal: new([]structFormatBytes),
6344 wantErr: EU(func() error {
6345 _, err := base32.StdEncoding.Decode(make([]byte, 1), []byte("NA"))
6346 return err
6347 }()).withPos(`[`+"\n\t\t\t\t"+`{"Base32": `, "/0/Base32").withType('"', T[[]byte]()),
6348 }, {
6349 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/WrongAlphabet"),
6350 inBuf: `{"Base32": "0123456789ABCDEFGHIJKLMNOPQRSTUV"}`,
6351 inVal: new(structFormatBytes),
6352 wantErr: EU(func() error {
6353 _, err := base32.StdEncoding.Decode(make([]byte, 20), []byte("0123456789ABCDEFGHIJKLMNOPQRSTUV"))
6354 return err
6355 }()).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6356 }, {
6357 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32Hex/WrongAlphabet"),
6358 inBuf: `{"Base32Hex": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"}`,
6359 inVal: new(structFormatBytes),
6360 wantErr: EU(func() error {
6361 _, err := base32.HexEncoding.Decode(make([]byte, 20), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"))
6362 return err
6363 }()).withPos(`{"Base32Hex": `, "/Base32Hex").withType('"', T[[]byte]()),
6364 }, {
6365 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/LineFeed"),
6366 inBuf: `{"Base32": "AAAA\nAAAA"}`,
6367 inVal: new(structFormatBytes),
6368 wantErr: EU(errors.New("illegal character '\\n' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6369 }, {
6370 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/CarriageReturn"),
6371 inBuf: `{"Base32": "AAAA\rAAAA"}`,
6372 inVal: new(structFormatBytes),
6373 wantErr: EU(errors.New("illegal character '\\r' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6374 }, {
6375 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/Space"),
6376 inBuf: `{"Base32": "AAAA AAAA"}`,
6377 inVal: new(structFormatBytes),
6378 wantErr: EU(base32.CorruptInputError(4)).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6379 }, {
6380 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/WrongAlphabet"),
6381 inBuf: `{"Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"}`,
6382 inVal: new(structFormatBytes),
6383 wantErr: EU(func() error {
6384 _, err := base64.StdEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"))
6385 return err
6386 }()).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6387 }, {
6388 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64URL/WrongAlphabet"),
6389 inBuf: `{"Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}`,
6390 inVal: new(structFormatBytes),
6391 wantErr: EU(func() error {
6392 _, err := base64.URLEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
6393 return err
6394 }()).withPos(`{"Base64URL": `, "/Base64URL").withType('"', T[[]byte]()),
6395 }, {
6396 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/LineFeed"),
6397 inBuf: `{"Base64": "aa=\n="}`,
6398 inVal: new(structFormatBytes),
6399 wantErr: EU(errors.New("illegal character '\\n' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6400 }, {
6401 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/CarriageReturn"),
6402 inBuf: `{"Base64": "aa=\r="}`,
6403 inVal: new(structFormatBytes),
6404 wantErr: EU(errors.New("illegal character '\\r' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6405 }, {
6406 name: jsontest.Name("Structs/Format/Bytes/Base64/NonAlphabet/Ignored"),
6407 opts: []Options{jsonflags.ParseBytesWithLooseRFC4648 | 1},
6408 inBuf: `{"Base64": "aa=\r\n="}`,
6409 inVal: new(structFormatBytes),
6410 want: &structFormatBytes{Base64: []byte{105}},
6411 }, {
6412 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/Space"),
6413 inBuf: `{"Base64": "aa= ="}`,
6414 inVal: new(structFormatBytes),
6415 wantErr: EU(base64.CorruptInputError(2)).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6416 }, {
6417 name: jsontest.Name("Structs/Format/Floats"),
6418 inBuf: `[
6419 {"NonFinite": 3.141592653589793, "PointerNonFinite": 3.141592653589793},
6420 {"NonFinite": "-Infinity", "PointerNonFinite": "-Infinity"},
6421 {"NonFinite": "Infinity", "PointerNonFinite": "Infinity"}
6422 ]`,
6423 inVal: new([]structFormatFloats),
6424 want: addr([]structFormatFloats{
6425 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
6426 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
6427 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
6428 }),
6429 }, {
6430 name: jsontest.Name("Structs/Format/Floats/NaN"),
6431 inBuf: `{"NonFinite": "NaN"}`,
6432 inVal: new(structFormatFloats),
6433
6434 }, {
6435 name: jsontest.Name("Structs/Format/Floats/Invalid/NaN"),
6436 inBuf: `{"NonFinite": "nan"}`,
6437 inVal: new(structFormatFloats),
6438 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6439 }, {
6440 name: jsontest.Name("Structs/Format/Floats/Invalid/PositiveInfinity"),
6441 inBuf: `{"NonFinite": "+Infinity"}`,
6442 inVal: new(structFormatFloats),
6443 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6444 }, {
6445 name: jsontest.Name("Structs/Format/Floats/Invalid/NegativeInfinitySpace"),
6446 inBuf: `{"NonFinite": "-Infinity "}`,
6447 inVal: new(structFormatFloats),
6448 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6449 }, {
6450 name: jsontest.Name("Structs/Format/Maps"),
6451 inBuf: `[
6452 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6453 {"EmitNull": {}, "PointerEmitNull": {}, "EmitEmpty": {}, "PointerEmitEmpty": {}, "EmitDefault": {}, "PointerEmitDefault": {}},
6454 {"EmitNull": {"k": "v"}, "PointerEmitNull": {"k": "v"}, "EmitEmpty": {"k": "v"}, "PointerEmitEmpty": {"k": "v"}, "EmitDefault": {"k": "v"}, "PointerEmitDefault": {"k": "v"}}
6455 ]`,
6456 inVal: new([]structFormatMaps),
6457 want: addr([]structFormatMaps{{
6458 EmitNull: map[string]string(nil), PointerEmitNull: (*map[string]string)(nil),
6459 EmitEmpty: map[string]string(nil), PointerEmitEmpty: (*map[string]string)(nil),
6460 EmitDefault: map[string]string(nil), PointerEmitDefault: (*map[string]string)(nil),
6461 }, {
6462 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
6463 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
6464 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
6465 }, {
6466 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
6467 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
6468 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
6469 }}),
6470 }, {
6471 name: jsontest.Name("Structs/Format/Slices"),
6472 inBuf: `[
6473 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6474 {"EmitNull": [], "PointerEmitNull": [], "EmitEmpty": [], "PointerEmitEmpty": [], "EmitDefault": [], "PointerEmitDefault": []},
6475 {"EmitNull": ["v"], "PointerEmitNull": ["v"], "EmitEmpty": ["v"], "PointerEmitEmpty": ["v"], "EmitDefault": ["v"], "PointerEmitDefault": ["v"]}
6476 ]`,
6477 inVal: new([]structFormatSlices),
6478 want: addr([]structFormatSlices{{
6479 EmitNull: []string(nil), PointerEmitNull: (*[]string)(nil),
6480 EmitEmpty: []string(nil), PointerEmitEmpty: (*[]string)(nil),
6481 EmitDefault: []string(nil), PointerEmitDefault: (*[]string)(nil),
6482 }, {
6483 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
6484 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
6485 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
6486 }, {
6487 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
6488 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
6489 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
6490 }}),
6491 }, {
6492 name: jsontest.Name("Structs/Format/Invalid/Bool"),
6493 inBuf: `{"Bool":true}`,
6494 inVal: new(structFormatInvalid),
6495 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, T[bool]()),
6496 }, {
6497 name: jsontest.Name("Structs/Format/Invalid/String"),
6498 inBuf: `{"String": "string"}`,
6499 inVal: new(structFormatInvalid),
6500 wantErr: EU(errInvalidFormatFlag).withPos(`{"String": `, "/String").withType(0, T[string]()),
6501 }, {
6502 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
6503 inBuf: `{"Bytes": "bytes"}`,
6504 inVal: new(structFormatInvalid),
6505 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bytes": `, "/Bytes").withType(0, T[[]byte]()),
6506 }, {
6507 name: jsontest.Name("Structs/Format/Invalid/Int"),
6508 inBuf: `{"Int": 1}`,
6509 inVal: new(structFormatInvalid),
6510 wantErr: EU(errInvalidFormatFlag).withPos(`{"Int": `, "/Int").withType(0, T[int64]()),
6511 }, {
6512 name: jsontest.Name("Structs/Format/Invalid/Uint"),
6513 inBuf: `{"Uint": 1}`,
6514 inVal: new(structFormatInvalid),
6515 wantErr: EU(errInvalidFormatFlag).withPos(`{"Uint": `, "/Uint").withType(0, T[uint64]()),
6516 }, {
6517 name: jsontest.Name("Structs/Format/Invalid/Float"),
6518 inBuf: `{"Float" : 1}`,
6519 inVal: new(structFormatInvalid),
6520 wantErr: EU(errInvalidFormatFlag).withPos(`{"Float" : `, "/Float").withType(0, T[float64]()),
6521 }, {
6522 name: jsontest.Name("Structs/Format/Invalid/Map"),
6523 inBuf: `{"Map":{}}`,
6524 inVal: new(structFormatInvalid),
6525 wantErr: EU(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
6526 }, {
6527 name: jsontest.Name("Structs/Format/Invalid/Struct"),
6528 inBuf: `{"Struct": {}}`,
6529 inVal: new(structFormatInvalid),
6530 wantErr: EU(errInvalidFormatFlag).withPos(`{"Struct": `, "/Struct").withType(0, T[structAll]()),
6531 }, {
6532 name: jsontest.Name("Structs/Format/Invalid/Slice"),
6533 inBuf: `{"Slice": {}}`,
6534 inVal: new(structFormatInvalid),
6535 wantErr: EU(errInvalidFormatFlag).withPos(`{"Slice": `, "/Slice").withType(0, T[[]string]()),
6536 }, {
6537 name: jsontest.Name("Structs/Format/Invalid/Array"),
6538 inBuf: `{"Array": []}`,
6539 inVal: new(structFormatInvalid),
6540 wantErr: EU(errInvalidFormatFlag).withPos(`{"Array": `, "/Array").withType(0, T[[1]string]()),
6541 }, {
6542 name: jsontest.Name("Structs/Format/Invalid/Interface"),
6543 inBuf: `{"Interface": "anything"}`,
6544 inVal: new(structFormatInvalid),
6545 wantErr: EU(errInvalidFormatFlag).withPos(`{"Interface": `, "/Interface").withType(0, T[any]()),
6546 }, {
6547 name: jsontest.Name("Structs/Inline/Zero"),
6548 inBuf: `{"D":""}`,
6549 inVal: new(structInlined),
6550 want: new(structInlined),
6551 }, {
6552 name: jsontest.Name("Structs/Inline/Alloc"),
6553 inBuf: `{"E":"","F":"","G":"","A":"","B":"","D":""}`,
6554 inVal: new(structInlined),
6555 want: addr(structInlined{
6556 X: structInlinedL1{
6557 X: &structInlinedL2{},
6558 StructEmbed1: StructEmbed1{},
6559 },
6560 StructEmbed2: &StructEmbed2{},
6561 }),
6562 }, {
6563 name: jsontest.Name("Structs/Inline/NonZero"),
6564 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6565 inVal: new(structInlined),
6566 want: addr(structInlined{
6567 X: structInlinedL1{
6568 X: &structInlinedL2{A: "A1", B: "B1" },
6569 StructEmbed1: StructEmbed1{ D: "D2" },
6570 },
6571 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6572 }),
6573 }, {
6574 name: jsontest.Name("Structs/Inline/Merge"),
6575 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6576 inVal: addr(structInlined{
6577 X: structInlinedL1{
6578 X: &structInlinedL2{B: "##", C: "C1"},
6579 StructEmbed1: StructEmbed1{C: "C2", E: "E2"},
6580 },
6581 StructEmbed2: &StructEmbed2{E: "##", G: "G3"},
6582 }),
6583 want: addr(structInlined{
6584 X: structInlinedL1{
6585 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
6586 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
6587 },
6588 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6589 }),
6590 }, {
6591 name: jsontest.Name("Structs/InlinedFallback/TextValue/Noop"),
6592 inBuf: `{"A":1,"B":2}`,
6593 inVal: new(structInlineTextValue),
6594 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(nil), B: 2}),
6595 }, {
6596 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Nil"),
6597 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6598 inVal: new(structInlineTextValue),
6599 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6600 }, {
6601 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Empty"),
6602 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6603 inVal: addr(structInlineTextValue{X: jsontext.Value{}}),
6604 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6605 }, {
6606 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Whitespace"),
6607 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6608 inVal: addr(structInlineTextValue{X: jsontext.Value("\n\r\t ")}),
6609 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("")}),
6610 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6611 }, {
6612 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Null"),
6613 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6614 inVal: addr(structInlineTextValue{X: jsontext.Value("null")}),
6615 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("null")}),
6616 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6617 }, {
6618 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/ObjectN0"),
6619 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6620 inVal: addr(structInlineTextValue{X: jsontext.Value(` { } `)}),
6621 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` {"fizz":"buzz"}`), B: 2}),
6622 }, {
6623 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN2/ObjectN1"),
6624 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6625 inVal: addr(structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)}),
6626 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` { "fizz" : "buzz","fizz":"buzz","foo":[ 1 , 2 , 3 ]}`), B: 2}),
6627 }, {
6628 name: jsontest.Name("Structs/InlinedFallback/TextValue/Merge/EndObject"),
6629 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6630 inVal: addr(structInlineTextValue{X: jsontext.Value(` } `)}),
6631
6632
6633 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`,"fizz":"buzz"}`), B: 2}),
6634 }, {
6635 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeInvalidValue"),
6636 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6637 inVal: new(structInlineTextValue),
6638 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":`)}),
6639 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6640 }, {
6641 name: jsontest.Name("Structs/InlinedFallback/TextValue/CaseSensitive"),
6642 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6643 inVal: new(structInlineTextValue),
6644 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","a":3}`), B: 2}),
6645 }, {
6646 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
6647 opts: []Options{jsontext.AllowDuplicateNames(false)},
6648 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6649 inVal: new(structInlineTextValue),
6650 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6651 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6652 }, {
6653 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
6654 opts: []Options{jsontext.AllowDuplicateNames(true)},
6655 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6656 inVal: new(structInlineTextValue),
6657 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`), B: 2}),
6658 }, {
6659 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Noop"),
6660 inBuf: `{}`,
6661 inVal: new(structInlinePointerInlineTextValue),
6662 want: new(structInlinePointerInlineTextValue),
6663 }, {
6664 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Alloc"),
6665 inBuf: `{"A":1,"fizz":"buzz"}`,
6666 inVal: new(structInlinePointerInlineTextValue),
6667 want: addr(structInlinePointerInlineTextValue{
6668 X: &struct {
6669 A int
6670 X jsontext.Value `json:",inline"`
6671 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6672 }),
6673 }, {
6674 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Merge"),
6675 inBuf: `{"fizz":"buzz"}`,
6676 inVal: addr(structInlinePointerInlineTextValue{
6677 X: &struct {
6678 A int
6679 X jsontext.Value `json:",inline"`
6680 }{A: 1},
6681 }),
6682 want: addr(structInlinePointerInlineTextValue{
6683 X: &struct {
6684 A int
6685 X jsontext.Value `json:",inline"`
6686 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6687 }),
6688 }, {
6689 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Noop"),
6690 inBuf: `{"A":1,"B":2}`,
6691 inVal: new(structInlinePointerTextValue),
6692 want: addr(structInlinePointerTextValue{A: 1, X: nil, B: 2}),
6693 }, {
6694 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Alloc"),
6695 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6696 inVal: new(structInlinePointerTextValue),
6697 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz"}`)), B: 2}),
6698 }, {
6699 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Merge"),
6700 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6701 inVal: addr(structInlinePointerTextValue{X: addr(jsontext.Value(`{"fizz":"buzz"}`))}),
6702 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`)), B: 2}),
6703 }, {
6704 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
6705 inBuf: `{"fizz":"buzz"}`,
6706 inVal: new(structInlineInlinePointerTextValue),
6707 want: addr(structInlineInlinePointerTextValue{
6708 X: struct {
6709 X *jsontext.Value `json:",inline"`
6710 }{X: addr(jsontext.Value(`{"fizz":"buzz"}`))},
6711 }),
6712 }, {
6713 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Noop"),
6714 inBuf: `{"A":1,"B":2}`,
6715 inVal: new(structInlineMapStringAny),
6716 want: addr(structInlineMapStringAny{A: 1, X: nil, B: 2}),
6717 }, {
6718 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Nil"),
6719 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6720 inVal: new(structInlineMapStringAny),
6721 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6722 }, {
6723 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Empty"),
6724 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6725 inVal: addr(structInlineMapStringAny{X: jsonObject{}}),
6726 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6727 }, {
6728 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/ObjectN1"),
6729 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6730 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": jsonObject{
6731 "alpha": "bravo",
6732 "charlie": "delta",
6733 }}}),
6734 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{
6735 "alpha": "bravo",
6736 "charlie": "DELTA",
6737 "echo": "foxtrot",
6738 }}, B: 2}),
6739 }, {
6740 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN2/ObjectN1"),
6741 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6742 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": "wuzz"}}),
6743 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6744 }, {
6745 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue"),
6746 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6747 inVal: new(structInlineMapStringAny),
6748 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": nil}}),
6749 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6750 }, {
6751 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue/Existing"),
6752 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6753 inVal: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6754 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6755 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6756 }, {
6757 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/CaseSensitive"),
6758 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6759 inVal: new(structInlineMapStringAny),
6760 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "a": 3.0}, B: 2}),
6761 }, {
6762 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectDuplicateNames"),
6763 opts: []Options{jsontext.AllowDuplicateNames(false)},
6764 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6765 inVal: new(structInlineMapStringAny),
6766 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6767 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6768 }, {
6769 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowDuplicateNames"),
6770 opts: []Options{jsontext.AllowDuplicateNames(true)},
6771 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
6772 inVal: new(structInlineMapStringAny),
6773 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
6774 }, {
6775 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Noop"),
6776 inBuf: `{}`,
6777 inVal: new(structInlinePointerInlineMapStringAny),
6778 want: new(structInlinePointerInlineMapStringAny),
6779 }, {
6780 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Alloc"),
6781 inBuf: `{"A":1,"fizz":"buzz"}`,
6782 inVal: new(structInlinePointerInlineMapStringAny),
6783 want: addr(structInlinePointerInlineMapStringAny{
6784 X: &struct {
6785 A int
6786 X jsonObject `json:",inline"`
6787 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6788 }),
6789 }, {
6790 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Merge"),
6791 inBuf: `{"fizz":"buzz"}`,
6792 inVal: addr(structInlinePointerInlineMapStringAny{
6793 X: &struct {
6794 A int
6795 X jsonObject `json:",inline"`
6796 }{A: 1},
6797 }),
6798 want: addr(structInlinePointerInlineMapStringAny{
6799 X: &struct {
6800 A int
6801 X jsonObject `json:",inline"`
6802 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6803 }),
6804 }, {
6805 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6806 opts: []Options{
6807 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
6808 var err error
6809 *v, err = strconv.ParseFloat(string(bytes.Trim(b, `"`)), 64)
6810 return err
6811 })),
6812 },
6813 inBuf: `{"D":"1.1","E":"2.2","F":"3.3"}`,
6814 inVal: new(structInlineMapStringAny),
6815 want: addr(structInlineMapStringAny{X: jsonObject{"D": 1.1, "E": 2.2, "F": 3.3}}),
6816 }, {
6817 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Noop"),
6818 inBuf: `{"A":1,"B":2}`,
6819 inVal: new(structInlinePointerMapStringAny),
6820 want: addr(structInlinePointerMapStringAny{A: 1, X: nil, B: 2}),
6821 }, {
6822 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Alloc"),
6823 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6824 inVal: new(structInlinePointerMapStringAny),
6825 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "buzz"}), B: 2}),
6826 }, {
6827 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Merge"),
6828 inBuf: `{"A":1,"fizz":"wuzz","B":2}`,
6829 inVal: addr(structInlinePointerMapStringAny{X: addr(jsonObject{"fizz": "buzz"})}),
6830 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "wuzz"}), B: 2}),
6831 }, {
6832 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
6833 inBuf: `{"fizz":"buzz"}`,
6834 inVal: new(structInlineInlinePointerMapStringAny),
6835 want: addr(structInlineInlinePointerMapStringAny{
6836 X: struct {
6837 X *jsonObject `json:",inline"`
6838 }{X: addr(jsonObject{"fizz": "buzz"})},
6839 }),
6840 }, {
6841 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
6842 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6843 inVal: new(structInlineMapStringInt),
6844 want: addr(structInlineMapStringInt{
6845 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6846 }),
6847 }, {
6848 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Null"),
6849 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6850 inVal: new(structInlineMapStringInt),
6851 want: addr(structInlineMapStringInt{
6852 X: map[string]int{"zero": 0, "one": 0, "two": 2},
6853 }),
6854 }, {
6855 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Invalid"),
6856 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6857 inVal: new(structInlineMapStringInt),
6858 want: addr(structInlineMapStringInt{
6859 X: map[string]int{"zero": 0, "one": 0},
6860 }),
6861 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6862 }, {
6863 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
6864 opts: []Options{StringifyNumbers(true)},
6865 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6866 inVal: new(structInlineMapStringInt),
6867 want: addr(structInlineMapStringInt{
6868 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6869 }),
6870 }, {
6871 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6872 opts: []Options{
6873 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6874 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6875 if err != nil {
6876 return err
6877 }
6878 *v = int(i)
6879 return nil
6880 })),
6881 },
6882 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6883 inVal: new(structInlineMapStringInt),
6884 want: addr(structInlineMapStringInt{
6885 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6886 }),
6887 }, {
6888 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
6889 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6890 inVal: new(structInlineMapNamedStringInt),
6891 want: addr(structInlineMapNamedStringInt{
6892 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6893 }),
6894 }, {
6895 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Null"),
6896 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6897 inVal: new(structInlineMapNamedStringInt),
6898 want: addr(structInlineMapNamedStringInt{
6899 X: map[namedString]int{"zero": 0, "one": 0, "two": 2},
6900 }),
6901 }, {
6902 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Invalid"),
6903 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6904 inVal: new(structInlineMapNamedStringInt),
6905 want: addr(structInlineMapNamedStringInt{
6906 X: map[namedString]int{"zero": 0, "one": 0},
6907 }),
6908 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6909 }, {
6910 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/StringifiedNumbers"),
6911 opts: []Options{StringifyNumbers(true)},
6912 inBuf: `{"zero": "0", "one": 1, "two": "2"}`,
6913 inVal: new(structInlineMapNamedStringInt),
6914 want: addr(structInlineMapNamedStringInt{
6915 X: map[namedString]int{"zero": 0, "one": 0},
6916 }),
6917 wantErr: EU(nil).withPos(`{"zero": "0", "one": `, "/one").withType('0', T[int]()),
6918 }, {
6919 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/UnmarshalFunc"),
6920 opts: []Options{
6921 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6922 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6923 if err != nil {
6924 return err
6925 }
6926 *v = int(i)
6927 return nil
6928 })),
6929 },
6930 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6931 inVal: new(structInlineMapNamedStringInt),
6932 want: addr(structInlineMapNamedStringInt{
6933 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6934 }),
6935 }, {
6936 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Noop"),
6937 inBuf: `{"A":1,"B":2}`,
6938 inVal: new(structInlineMapNamedStringAny),
6939 want: addr(structInlineMapNamedStringAny{A: 1, X: nil, B: 2}),
6940 }, {
6941 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Nil"),
6942 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6943 inVal: new(structInlineMapNamedStringAny),
6944 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6945 }, {
6946 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Empty"),
6947 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6948 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{}}),
6949 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6950 }, {
6951 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/ObjectN1"),
6952 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6953 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": jsonObject{
6954 "alpha": "bravo",
6955 "charlie": "delta",
6956 }}}),
6957 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": jsonObject{
6958 "alpha": "bravo",
6959 "charlie": "DELTA",
6960 "echo": "foxtrot",
6961 }}, B: 2}),
6962 }, {
6963 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN2/ObjectN1"),
6964 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6965 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": "wuzz"}}),
6966 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6967 }, {
6968 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue"),
6969 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6970 inVal: new(structInlineMapNamedStringAny),
6971 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": nil}}),
6972 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6973 }, {
6974 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue/Existing"),
6975 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6976 inVal: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
6977 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
6978 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6979 }, {
6980 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/CaseSensitive"),
6981 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6982 inVal: new(structInlineMapNamedStringAny),
6983 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "a": 3.0}, B: 2}),
6984 }, {
6985 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectDuplicateNames"),
6986 opts: []Options{jsontext.AllowDuplicateNames(false)},
6987 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6988 inVal: new(structInlineMapNamedStringAny),
6989 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6990 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6991 }, {
6992 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowDuplicateNames"),
6993 opts: []Options{jsontext.AllowDuplicateNames(true)},
6994 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
6995 inVal: new(structInlineMapNamedStringAny),
6996 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": map[string]any{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
6997 }, {
6998 name: jsontest.Name("Structs/InlinedFallback/RejectUnknownMembers"),
6999 opts: []Options{RejectUnknownMembers(true)},
7000 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7001 inVal: new(structInlineTextValue),
7002
7003 want: addr(structInlineTextValue{
7004 A: 1,
7005 X: jsontext.Value(`{"fizz":"buzz"}`),
7006 B: 2,
7007 }),
7008 }, {
7009 name: jsontest.Name("Structs/UnknownFallback/RejectUnknownMembers"),
7010 opts: []Options{RejectUnknownMembers(true)},
7011 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7012 inVal: new(structUnknownTextValue),
7013 want: addr(structUnknownTextValue{A: 1}),
7014 wantErr: EU(ErrUnknownName).withPos(`{"A":1,`, "/fizz").withType('"', T[structUnknownTextValue]()),
7015 }, {
7016 name: jsontest.Name("Structs/UnknownFallback"),
7017 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7018 inVal: new(structUnknownTextValue),
7019 want: addr(structUnknownTextValue{
7020 A: 1,
7021 X: jsontext.Value(`{"fizz":"buzz"}`),
7022 B: 2,
7023 }),
7024 }, {
7025 name: jsontest.Name("Structs/UnknownIgnored"),
7026 opts: []Options{RejectUnknownMembers(false)},
7027 inBuf: `{"unknown":"fizzbuzz"}`,
7028 inVal: new(structAll),
7029 want: new(structAll),
7030 }, {
7031 name: jsontest.Name("Structs/RejectUnknownMembers"),
7032 opts: []Options{RejectUnknownMembers(true)},
7033 inBuf: `{"unknown":"fizzbuzz"}`,
7034 inVal: new(structAll),
7035 want: new(structAll),
7036 wantErr: EU(ErrUnknownName).withPos(`{`, "/unknown").withType('"', T[structAll]()),
7037 }, {
7038 name: jsontest.Name("Structs/UnexportedIgnored"),
7039 inBuf: `{"ignored":"unused"}`,
7040 inVal: new(structUnexportedIgnored),
7041 want: new(structUnexportedIgnored),
7042 }, {
7043 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
7044 inBuf: `{"namedString":"unused"}`,
7045 inVal: new(structIgnoredUnexportedEmbedded),
7046 want: new(structIgnoredUnexportedEmbedded),
7047 }, {
7048 name: jsontest.Name("Structs/WeirdNames"),
7049 inBuf: `{"":"empty",",":"comma","\"":"quote"}`,
7050 inVal: new(structWeirdNames),
7051 want: addr(structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"}),
7052 }, {
7053 name: jsontest.Name("Structs/NoCase/Exact"),
7054 inBuf: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
7055 inVal: new(structNoCase),
7056 want: addr(structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"}),
7057 }, {
7058 name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault"),
7059 inBuf: `{"aa_a":"aa_a"}`,
7060 inVal: new(structNoCase),
7061 want: addr(structNoCase{AaA: "aa_a"}),
7062 }, {
7063 name: jsontest.Name("Structs/NoCase/MatchCaseSensitiveDelimiter"),
7064 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
7065 inBuf: `{"aa_a":"aa_a"}`,
7066 inVal: new(structNoCase),
7067 want: addr(structNoCase{}),
7068 }, {
7069 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
7070 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
7071 inBuf: `{"aa_a":"aa_a"}`,
7072 inVal: new(structNoCase),
7073 want: addr(structNoCase{AA_A: "aa_a"}),
7074 }, {
7075 name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames"),
7076 opts: []Options{jsontext.AllowDuplicateNames(true)},
7077 inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`,
7078 inVal: new(structNoCase),
7079 want: addr(structNoCase{AaA: "aAa"}),
7080 }, {
7081 name: jsontest.Name("Structs/NoCase/Merge/RejectDuplicateNames"),
7082 opts: []Options{jsontext.AllowDuplicateNames(false)},
7083 inBuf: `{"AaA":"AaA","aaa":"aaa"}`,
7084 inVal: new(structNoCase),
7085 want: addr(structNoCase{AaA: "AaA"}),
7086 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AaA":"AaA",`)),
7087 }, {
7088 name: jsontest.Name("Structs/CaseSensitive"),
7089 inBuf: `{"BOOL": true, "STRING": "hello", "BYTES": "AQID", "INT": -64, "UINT": 64, "FLOAT": 3.14159}`,
7090 inVal: new(structScalars),
7091 want: addr(structScalars{}),
7092 }, {
7093 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactDifferent"),
7094 inBuf: `{"AAA":"AAA","AaA":"AaA","AAa":"AAa","Aaa":"Aaa"}`,
7095 inVal: addr(structNoCaseInlineTextValue{}),
7096 want: addr(structNoCaseInlineTextValue{AAA: "AAA", AaA: "AaA", AAa: "AAa", Aaa: "Aaa"}),
7097 }, {
7098 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactConflict"),
7099 inBuf: `{"AAA":"AAA","AAA":"AAA"}`,
7100 inVal: addr(structNoCaseInlineTextValue{}),
7101 want: addr(structNoCaseInlineTextValue{AAA: "AAA"}),
7102 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"AAA",`)),
7103 }, {
7104 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteExact"),
7105 inBuf: `{"AAA":"after"}`,
7106 inVal: addr(structNoCaseInlineTextValue{AAA: "before"}),
7107 want: addr(structNoCaseInlineTextValue{AAA: "after"}),
7108 }, {
7109 name: jsontest.Name("Structs/DuplicateName/NoCase/NoCaseConflict"),
7110 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7111 inVal: addr(structNoCaseInlineTextValue{}),
7112 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7113 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7114 }, {
7115 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteNoCase"),
7116 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7117 inVal: addr(structNoCaseInlineTextValue{}),
7118 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7119 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7120 }, {
7121 name: jsontest.Name("Structs/DuplicateName/Inline/Unknown"),
7122 inBuf: `{"unknown":""}`,
7123 inVal: addr(structNoCaseInlineTextValue{}),
7124 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7125 }, {
7126 name: jsontest.Name("Structs/DuplicateName/Inline/UnknownMerge"),
7127 inBuf: `{"unknown":""}`,
7128 inVal: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7129 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":"","unknown":""}`)}),
7130 }, {
7131 name: jsontest.Name("Structs/DuplicateName/Inline/NoCaseOkay"),
7132 inBuf: `{"b":"","B":""}`,
7133 inVal: addr(structNoCaseInlineTextValue{}),
7134 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":"","B":""}`)}),
7135 }, {
7136 name: jsontest.Name("Structs/DuplicateName/Inline/ExactConflict"),
7137 inBuf: `{"b":"","b":""}`,
7138 inVal: addr(structNoCaseInlineTextValue{}),
7139 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":""}`)}),
7140 wantErr: newDuplicateNameError("", []byte(`"b"`), len64(`{"b":"",`)),
7141 }, {
7142 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7143 inBuf: ``,
7144 inVal: addr(structAll{}),
7145 want: addr(structAll{}),
7146 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF},
7147 }, {
7148 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7149 inBuf: " \n\r\t",
7150 inVal: addr(structAll{}),
7151 want: addr(structAll{}),
7152 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF, ByteOffset: len64(" \n\r\t")},
7153 }, {
7154 name: jsontest.Name("Structs/Invalid/NestedErrUnexpectedEOF"),
7155 inBuf: `{"Pointer":`,
7156 inVal: addr(structAll{}),
7157 want: addr(structAll{Pointer: new(structAll)}),
7158 wantErr: &jsontext.SyntacticError{ByteOffset: len64(`{"Pointer":`), JSONPointer: "/Pointer", Err: io.ErrUnexpectedEOF},
7159 }, {
7160 name: jsontest.Name("Structs/Invalid/Conflicting"),
7161 inBuf: `{}`,
7162 inVal: addr(structConflicting{}),
7163 want: addr(structConflicting{}),
7164 wantErr: EU(errors.New(`Go struct fields A and B conflict over JSON object name "conflict"`)).withType('{', T[structConflicting]()),
7165 }, {
7166 name: jsontest.Name("Structs/Invalid/NoneExported"),
7167 inBuf: ` {}`,
7168 inVal: addr(structNoneExported{}),
7169 want: addr(structNoneExported{}),
7170 wantErr: EU(errNoExportedFields).withPos(` `, "").withType('{', T[structNoneExported]()),
7171 }, {
7172 name: jsontest.Name("Structs/Invalid/MalformedTag"),
7173 inBuf: `{}`,
7174 inVal: addr(structMalformedTag{}),
7175 want: addr(structMalformedTag{}),
7176 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]()),
7177 }, {
7178 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
7179 inBuf: `{}`,
7180 inVal: addr(structUnexportedTag{}),
7181 want: addr(structUnexportedTag{}),
7182 wantErr: EU(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType('{', T[structUnexportedTag]()),
7183 }, {
7184 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
7185 inBuf: `{"NamedString":"hello"}`,
7186 inVal: addr(structExportedEmbedded{}),
7187 want: addr(structExportedEmbedded{}),
7188 wantErr: EU(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structExportedEmbedded]()),
7189 }, {
7190 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
7191 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
7192 inBuf: `{"NamedString":"hello"}`,
7193 inVal: addr(structExportedEmbedded{}),
7194 want: addr(structExportedEmbedded{"hello"}),
7195 }, {
7196 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
7197 inBuf: `{"name":"hello"}`,
7198 inVal: addr(structExportedEmbeddedTag{}),
7199 want: addr(structExportedEmbeddedTag{"hello"}),
7200 }, {
7201 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
7202 inBuf: `{}`,
7203 inVal: addr(structUnexportedEmbedded{}),
7204 want: addr(structUnexportedEmbedded{}),
7205 wantErr: EU(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structUnexportedEmbedded]()),
7206 }, {
7207 name: jsontest.Name("Structs/UnexportedEmbeddedStruct"),
7208 inBuf: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7209 inVal: addr(structUnexportedEmbeddedStruct{}),
7210 want: addr(structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7211 }, {
7212 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7213 inBuf: `{"Bool":true,"FizzBuzz":5}`,
7214 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7215 wantErr: EU(errNilField).withPos(`{"Bool":`, "/Bool").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7216 }, {
7217 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7218 inBuf: `{"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7219 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7220 wantErr: EU(errNilField).withPos(`{"FizzBuzz":5,"Addr":`, "/Addr").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7221 }, {
7222 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7223 inBuf: `{"Bool":true,"FizzBuzz":10,"Addr":"192.168.0.1"}`,
7224 inVal: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Int: 5}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{127, 0, 0, 1})}}),
7225 want: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true, Int: 5}, 10, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7226 }, {
7227 name: jsontest.Name("Structs/Unknown"),
7228 inBuf: `{
7229 "object0": {},
7230 "object1": {"key1": "value"},
7231 "object2": {"key1": "value", "key2": "value"},
7232 "objects": {"":{"":{"":{}}}},
7233 "array0": [],
7234 "array1": ["value1"],
7235 "array2": ["value1", "value2"],
7236 "array": [[[]]],
7237 "scalars": [null, false, true, "string", 12.345]
7238 }`,
7239 inVal: addr(struct{}{}),
7240 want: addr(struct{}{}),
7241 }, {
7242 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
7243 opts: []Options{invalidFormatOption},
7244 inBuf: `{"Field":"Value"}`,
7245 inVal: addr(struct{ Field string }{}),
7246 want: addr(struct{ Field string }{"Value"}),
7247 }, {
7248 name: jsontest.Name("Slices/Null"),
7249 inBuf: `null`,
7250 inVal: addr([]string{"something"}),
7251 want: addr([]string(nil)),
7252 }, {
7253 name: jsontest.Name("Slices/Bool"),
7254 inBuf: `[true,false]`,
7255 inVal: new([]bool),
7256 want: addr([]bool{true, false}),
7257 }, {
7258 name: jsontest.Name("Slices/String"),
7259 inBuf: `["hello","goodbye"]`,
7260 inVal: new([]string),
7261 want: addr([]string{"hello", "goodbye"}),
7262 }, {
7263 name: jsontest.Name("Slices/Bytes"),
7264 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7265 inVal: new([][]byte),
7266 want: addr([][]byte{[]byte("hello"), []byte("goodbye")}),
7267 }, {
7268 name: jsontest.Name("Slices/Int"),
7269 inBuf: `[-2,-1,0,1,2]`,
7270 inVal: new([]int),
7271 want: addr([]int{-2, -1, 0, 1, 2}),
7272 }, {
7273 name: jsontest.Name("Slices/Uint"),
7274 inBuf: `[0,1,2,3,4]`,
7275 inVal: new([]uint),
7276 want: addr([]uint{0, 1, 2, 3, 4}),
7277 }, {
7278 name: jsontest.Name("Slices/Float"),
7279 inBuf: `[3.14159,12.34]`,
7280 inVal: new([]float64),
7281 want: addr([]float64{3.14159, 12.34}),
7282 }, {
7283
7284
7285
7286 name: jsontest.Name("Slices/Merge"),
7287 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7288 inVal: addr([]map[string]string{{"k1": "v1"}, {"k2": "v2"}}[:1]),
7289 want: addr([]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7290 }, {
7291 name: jsontest.Name("Slices/Invalid/Channel"),
7292 inBuf: `["hello"]`,
7293 inVal: new([]chan string),
7294 want: addr([]chan string{nil}),
7295 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7296 }, {
7297 name: jsontest.Name("Slices/RecursiveSlice"),
7298 inBuf: `[[],[],[[]],[[],[]]]`,
7299 inVal: new(recursiveSlice),
7300 want: addr(recursiveSlice{
7301 {},
7302 {},
7303 {{}},
7304 {{}, {}},
7305 }),
7306 }, {
7307 name: jsontest.Name("Slices/Invalid/Bool"),
7308 inBuf: `true`,
7309 inVal: addr([]string{"nochange"}),
7310 want: addr([]string{"nochange"}),
7311 wantErr: EU(nil).withType('t', T[[]string]()),
7312 }, {
7313 name: jsontest.Name("Slices/Invalid/String"),
7314 inBuf: `""`,
7315 inVal: addr([]string{"nochange"}),
7316 want: addr([]string{"nochange"}),
7317 wantErr: EU(nil).withType('"', T[[]string]()),
7318 }, {
7319 name: jsontest.Name("Slices/Invalid/Number"),
7320 inBuf: `0`,
7321 inVal: addr([]string{"nochange"}),
7322 want: addr([]string{"nochange"}),
7323 wantErr: EU(nil).withType('0', T[[]string]()),
7324 }, {
7325 name: jsontest.Name("Slices/Invalid/Object"),
7326 inBuf: `{}`,
7327 inVal: addr([]string{"nochange"}),
7328 want: addr([]string{"nochange"}),
7329 wantErr: EU(nil).withType('{', T[[]string]()),
7330 }, {
7331 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
7332 opts: []Options{invalidFormatOption},
7333 inBuf: `[false,true]`,
7334 inVal: addr([]bool{true, false}),
7335 want: addr([]bool{false, true}),
7336 }, {
7337 name: jsontest.Name("Arrays/Null"),
7338 inBuf: `null`,
7339 inVal: addr([1]string{"something"}),
7340 want: addr([1]string{}),
7341 }, {
7342 name: jsontest.Name("Arrays/Bool"),
7343 inBuf: `[true,false]`,
7344 inVal: new([2]bool),
7345 want: addr([2]bool{true, false}),
7346 }, {
7347 name: jsontest.Name("Arrays/String"),
7348 inBuf: `["hello","goodbye"]`,
7349 inVal: new([2]string),
7350 want: addr([2]string{"hello", "goodbye"}),
7351 }, {
7352 name: jsontest.Name("Arrays/Bytes"),
7353 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7354 inVal: new([2][]byte),
7355 want: addr([2][]byte{[]byte("hello"), []byte("goodbye")}),
7356 }, {
7357 name: jsontest.Name("Arrays/Int"),
7358 inBuf: `[-2,-1,0,1,2]`,
7359 inVal: new([5]int),
7360 want: addr([5]int{-2, -1, 0, 1, 2}),
7361 }, {
7362 name: jsontest.Name("Arrays/Uint"),
7363 inBuf: `[0,1,2,3,4]`,
7364 inVal: new([5]uint),
7365 want: addr([5]uint{0, 1, 2, 3, 4}),
7366 }, {
7367 name: jsontest.Name("Arrays/Float"),
7368 inBuf: `[3.14159,12.34]`,
7369 inVal: new([2]float64),
7370 want: addr([2]float64{3.14159, 12.34}),
7371 }, {
7372
7373
7374 name: jsontest.Name("Arrays/Merge"),
7375 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7376 inVal: addr([2]map[string]string{{"k1": "v1"}, {"k2": "v2"}}),
7377 want: addr([2]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7378 }, {
7379 name: jsontest.Name("Arrays/Invalid/Channel"),
7380 inBuf: `["hello"]`,
7381 inVal: new([1]chan string),
7382 want: new([1]chan string),
7383 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7384 }, {
7385 name: jsontest.Name("Arrays/Invalid/Underflow"),
7386 inBuf: `{"F":[ ]}`,
7387 inVal: new(struct{ F [1]string }),
7388 want: addr(struct{ F [1]string }{}),
7389 wantErr: EU(errArrayUnderflow).withPos(`{"F":[ `, "/F").withType(']', T[[1]string]()),
7390 }, {
7391 name: jsontest.Name("Arrays/Invalid/Underflow/UnmarshalArrayFromAnyLength"),
7392 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7393 inBuf: `[-1,-2]`,
7394 inVal: addr([4]int{1, 2, 3, 4}),
7395 want: addr([4]int{-1, -2, 0, 0}),
7396 }, {
7397 name: jsontest.Name("Arrays/Invalid/Overflow"),
7398 inBuf: `["1","2"]`,
7399 inVal: new([1]string),
7400 want: addr([1]string{"1"}),
7401 wantErr: EU(errArrayOverflow).withPos(`["1","2"`, "").withType(']', T[[1]string]()),
7402 }, {
7403 name: jsontest.Name("Arrays/Invalid/Overflow/UnmarshalArrayFromAnyLength"),
7404 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7405 inBuf: `[-1,-2,-3,-4,-5,-6]`,
7406 inVal: addr([4]int{1, 2, 3, 4}),
7407 want: addr([4]int{-1, -2, -3, -4}),
7408 }, {
7409 name: jsontest.Name("Arrays/Invalid/Bool"),
7410 inBuf: `true`,
7411 inVal: addr([1]string{"nochange"}),
7412 want: addr([1]string{"nochange"}),
7413 wantErr: EU(nil).withType('t', T[[1]string]()),
7414 }, {
7415 name: jsontest.Name("Arrays/Invalid/String"),
7416 inBuf: `""`,
7417 inVal: addr([1]string{"nochange"}),
7418 want: addr([1]string{"nochange"}),
7419 wantErr: EU(nil).withType('"', T[[1]string]()),
7420 }, {
7421 name: jsontest.Name("Arrays/Invalid/Number"),
7422 inBuf: `0`,
7423 inVal: addr([1]string{"nochange"}),
7424 want: addr([1]string{"nochange"}),
7425 wantErr: EU(nil).withType('0', T[[1]string]()),
7426 }, {
7427 name: jsontest.Name("Arrays/Invalid/Object"),
7428 inBuf: `{}`,
7429 inVal: addr([1]string{"nochange"}),
7430 want: addr([1]string{"nochange"}),
7431 wantErr: EU(nil).withType('{', T[[1]string]()),
7432 }, {
7433 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
7434 opts: []Options{invalidFormatOption},
7435 inBuf: `[false,true]`,
7436 inVal: addr([2]bool{true, false}),
7437 want: addr([2]bool{false, true}),
7438 }, {
7439 name: jsontest.Name("Pointers/NullL0"),
7440 inBuf: `null`,
7441 inVal: new(*string),
7442 want: addr((*string)(nil)),
7443 }, {
7444 name: jsontest.Name("Pointers/NullL1"),
7445 inBuf: `null`,
7446 inVal: addr(new(*string)),
7447 want: addr((**string)(nil)),
7448 }, {
7449 name: jsontest.Name("Pointers/Bool"),
7450 inBuf: `true`,
7451 inVal: addr(new(bool)),
7452 want: addr(addr(true)),
7453 }, {
7454 name: jsontest.Name("Pointers/String"),
7455 inBuf: `"hello"`,
7456 inVal: addr(new(string)),
7457 want: addr(addr("hello")),
7458 }, {
7459 name: jsontest.Name("Pointers/Bytes"),
7460 inBuf: `"aGVsbG8="`,
7461 inVal: addr(new([]byte)),
7462 want: addr(addr([]byte("hello"))),
7463 }, {
7464 name: jsontest.Name("Pointers/Int"),
7465 inBuf: `-123`,
7466 inVal: addr(new(int)),
7467 want: addr(addr(int(-123))),
7468 }, {
7469 name: jsontest.Name("Pointers/Uint"),
7470 inBuf: `123`,
7471 inVal: addr(new(int)),
7472 want: addr(addr(int(123))),
7473 }, {
7474 name: jsontest.Name("Pointers/Float"),
7475 inBuf: `123.456`,
7476 inVal: addr(new(float64)),
7477 want: addr(addr(float64(123.456))),
7478 }, {
7479 name: jsontest.Name("Pointers/Allocate"),
7480 inBuf: `"hello"`,
7481 inVal: addr((*string)(nil)),
7482 want: addr(addr("hello")),
7483 }, {
7484 name: jsontest.Name("Points/IgnoreInvalidFormat"),
7485 opts: []Options{invalidFormatOption},
7486 inBuf: `true`,
7487 inVal: addr(new(bool)),
7488 want: addr(addr(true)),
7489 }, {
7490 name: jsontest.Name("Interfaces/Empty/Null"),
7491 inBuf: `null`,
7492 inVal: new(any),
7493 want: new(any),
7494 }, {
7495 name: jsontest.Name("Interfaces/NonEmpty/Null"),
7496 inBuf: `null`,
7497 inVal: new(io.Reader),
7498 want: new(io.Reader),
7499 }, {
7500 name: jsontest.Name("Interfaces/NonEmpty/Invalid"),
7501 inBuf: `"hello"`,
7502 inVal: new(io.Reader),
7503 want: new(io.Reader),
7504 wantErr: EU(internal.ErrNilInterface).withType(0, T[io.Reader]()),
7505 }, {
7506 name: jsontest.Name("Interfaces/Empty/False"),
7507 inBuf: `false`,
7508 inVal: new(any),
7509 want: func() any {
7510 var vi any = false
7511 return &vi
7512 }(),
7513 }, {
7514 name: jsontest.Name("Interfaces/Empty/True"),
7515 inBuf: `true`,
7516 inVal: new(any),
7517 want: func() any {
7518 var vi any = true
7519 return &vi
7520 }(),
7521 }, {
7522 name: jsontest.Name("Interfaces/Empty/String"),
7523 inBuf: `"string"`,
7524 inVal: new(any),
7525 want: func() any {
7526 var vi any = "string"
7527 return &vi
7528 }(),
7529 }, {
7530 name: jsontest.Name("Interfaces/Empty/Number"),
7531 inBuf: `3.14159`,
7532 inVal: new(any),
7533 want: func() any {
7534 var vi any = 3.14159
7535 return &vi
7536 }(),
7537 }, {
7538 name: jsontest.Name("Interfaces/Empty/Object"),
7539 inBuf: `{"k":"v"}`,
7540 inVal: new(any),
7541 want: func() any {
7542 var vi any = map[string]any{"k": "v"}
7543 return &vi
7544 }(),
7545 }, {
7546 name: jsontest.Name("Interfaces/Empty/Array"),
7547 inBuf: `["v"]`,
7548 inVal: new(any),
7549 want: func() any {
7550 var vi any = []any{"v"}
7551 return &vi
7552 }(),
7553 }, {
7554 name: jsontest.Name("Interfaces/NamedAny/String"),
7555 inBuf: `"string"`,
7556 inVal: new(namedAny),
7557 want: func() namedAny {
7558 var vi namedAny = "string"
7559 return &vi
7560 }(),
7561 }, {
7562 name: jsontest.Name("Interfaces/Invalid"),
7563 inBuf: `]`,
7564 inVal: new(any),
7565 want: new(any),
7566 wantErr: newInvalidCharacterError("]", "at start of value", 0, ""),
7567 }, {
7568
7569
7570
7571
7572 name: jsontest.Name("Interfaces/Merge/Map"),
7573 inBuf: `{"k2":"v2"}`,
7574 inVal: func() any {
7575 var vi any = map[string]string{"k1": "v1"}
7576 return &vi
7577 }(),
7578 want: func() any {
7579 var vi any = map[string]string{"k1": "v1", "k2": "v2"}
7580 return &vi
7581 }(),
7582 }, {
7583 name: jsontest.Name("Interfaces/Merge/Struct"),
7584 inBuf: `{"Array":["goodbye"]}`,
7585 inVal: func() any {
7586 var vi any = structAll{String: "hello"}
7587 return &vi
7588 }(),
7589 want: func() any {
7590 var vi any = structAll{String: "hello", Array: [1]string{"goodbye"}}
7591 return &vi
7592 }(),
7593 }, {
7594 name: jsontest.Name("Interfaces/Merge/NamedInt"),
7595 inBuf: `64`,
7596 inVal: func() any {
7597 var vi any = namedInt64(-64)
7598 return &vi
7599 }(),
7600 want: func() any {
7601 var vi any = namedInt64(+64)
7602 return &vi
7603 }(),
7604 }, {
7605 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
7606 opts: []Options{invalidFormatOption},
7607 inBuf: `true`,
7608 inVal: new(any),
7609 want: func() any {
7610 var vi any = true
7611 return &vi
7612 }(),
7613 }, {
7614 name: jsontest.Name("Interfaces/Any"),
7615 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7616 inVal: new(struct{ X any }),
7617 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7618 }, {
7619 name: jsontest.Name("Interfaces/Any/Named"),
7620 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7621 inVal: new(struct{ X namedAny }),
7622 want: addr(struct{ X namedAny }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7623 }, {
7624 name: jsontest.Name("Interfaces/Any/Stringified"),
7625 opts: []Options{StringifyNumbers(true)},
7626 inBuf: `{"X":"0"}`,
7627 inVal: new(struct{ X any }),
7628 want: addr(struct{ X any }{"0"}),
7629 }, {
7630 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Any"),
7631 opts: []Options{
7632 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
7633 *v = "called"
7634 return nil
7635 })),
7636 },
7637 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7638 inVal: new(struct{ X any }),
7639 want: addr(struct{ X any }{"called"}),
7640 }, {
7641 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Bool"),
7642 opts: []Options{
7643 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *bool) error {
7644 *v = string(b) != "true"
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, true, false, "", 0.0, map[string]any{}, []any{}}}),
7651 }, {
7652 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/String"),
7653 opts: []Options{
7654 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7655 *v = "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{nil, false, true, "called", 0.0, map[string]any{}, []any{}}}),
7662 }, {
7663 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Float64"),
7664 opts: []Options{
7665 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *float64) error {
7666 *v = 3.14159
7667 return nil
7668 })),
7669 },
7670 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7671 inVal: new(struct{ X any }),
7672 want: addr(struct{ X any }{[]any{nil, false, true, "", 3.14159, map[string]any{}, []any{}}}),
7673 }, {
7674 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/MapStringAny"),
7675 opts: []Options{
7676 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *map[string]any) error {
7677 *v = map[string]any{"called": nil}
7678 return nil
7679 })),
7680 },
7681 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7682 inVal: new(struct{ X any }),
7683 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{"called": nil}, []any{}}}),
7684 }, {
7685 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/SliceAny"),
7686 opts: []Options{
7687 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *[]any) error {
7688 *v = []any{"called"}
7689 return nil
7690 })),
7691 },
7692 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7693 inVal: new(struct{ X any }),
7694 want: addr(struct{ X any }{[]any{"called"}}),
7695 }, {
7696 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
7697 inBuf: `{"X":{"fizz":"buzz"}}`,
7698 inVal: new(struct{ X any }),
7699 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7700 }, {
7701 name: jsontest.Name("Interfaces/Any/Maps/RejectDuplicateNames"),
7702 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7703 inVal: new(struct{ X any }),
7704 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7705 wantErr: newDuplicateNameError("/X", []byte(`"fizz"`), len64(`{"X":{"fizz":"buzz",`)),
7706 }, {
7707 name: jsontest.Name("Interfaces/Any/Maps/AllowDuplicateNames"),
7708 opts: []Options{jsontext.AllowDuplicateNames(true)},
7709 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7710 inVal: new(struct{ X any }),
7711 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7712 wantErr: EU(nil).withPos(`{"X":{"fizz":"buzz","fizz":`, "/X/fizz").withType('t', T[string]()),
7713 }, {
7714 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
7715 inBuf: `{"X":["fizz","buzz"]}`,
7716 inVal: new(struct{ X any }),
7717 want: addr(struct{ X any }{[]any{"fizz", "buzz"}}),
7718 }, {
7719 name: jsontest.Name("Methods/NilPointer/Null"),
7720 inBuf: `{"X":null}`,
7721 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7722 want: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7723 }, {
7724 name: jsontest.Name("Methods/NilPointer/Value"),
7725 inBuf: `{"X":"value"}`,
7726 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7727 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7728 }, {
7729 name: jsontest.Name("Methods/NilInterface/Null"),
7730 inBuf: `{"X":null}`,
7731 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7732 want: addr(struct{ X MarshalerTo }{X: nil}),
7733 }, {
7734 name: jsontest.Name("Methods/NilInterface/Value"),
7735 inBuf: `{"X":"value"}`,
7736 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7737 want: addr(struct{ X MarshalerTo }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7738 }, {
7739 name: jsontest.Name("Methods/AllMethods"),
7740 inBuf: `{"X":"hello"}`,
7741 inVal: new(struct{ X *allMethods }),
7742 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}),
7743 }, {
7744 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
7745 inBuf: `{"X":"hello"}`,
7746 inVal: new(struct{ X *allMethodsExceptJSONv2 }),
7747 want: addr(struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7748 }, {
7749 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
7750 inBuf: `{"X":"hello"}`,
7751 inVal: new(struct{ X *allMethodsExceptJSONv1 }),
7752 want: addr(struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7753 }, {
7754 name: jsontest.Name("Methods/AllMethodsExceptText"),
7755 inBuf: `{"X":"hello"}`,
7756 inVal: new(struct{ X *allMethodsExceptText }),
7757 want: addr(struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7758 }, {
7759 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
7760 inBuf: `{"X":"hello"}`,
7761 inVal: new(struct{ X *onlyMethodJSONv2 }),
7762 want: addr(struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7763 }, {
7764 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
7765 inBuf: `{"X":"hello"}`,
7766 inVal: new(struct{ X *onlyMethodJSONv1 }),
7767 want: addr(struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7768 }, {
7769 name: jsontest.Name("Methods/OnlyMethodText"),
7770 inBuf: `{"X":"hello"}`,
7771 inVal: new(struct{ X *onlyMethodText }),
7772 want: addr(struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "UnmarshalText", value: []byte(`hello`)}}}),
7773 }, {
7774 name: jsontest.Name("Methods/Text/Null"),
7775 inBuf: `{"X":null}`,
7776 inVal: addr(struct{ X unmarshalTextFunc }{unmarshalTextFunc(func(b []byte) error {
7777 return errMustNotCall
7778 })}),
7779 want: addr(struct{ X unmarshalTextFunc }{nil}),
7780 }, {
7781 name: jsontest.Name("Methods/IP"),
7782 inBuf: `"192.168.0.100"`,
7783 inVal: new(net.IP),
7784 want: addr(net.IPv4(192, 168, 0, 100)),
7785 }, {
7786
7787 name: jsontest.Name("Methods/Anonymous"),
7788 inBuf: `{"X":"hello"}`,
7789 inVal: new(struct{ X struct{ allMethods } }),
7790 want: addr(struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7791 }, {
7792
7793 name: jsontest.Name("Methods/Addressable"),
7794 inBuf: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
7795 inVal: addr(struct {
7796 V allMethods
7797 M map[string]allMethods
7798 I any
7799 }{
7800 I: allMethods{},
7801 }),
7802 want: addr(struct {
7803 V allMethods
7804 M map[string]allMethods
7805 I any
7806 }{
7807 V: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7808 M: map[string]allMethods{"K": {method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}},
7809 I: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7810 }),
7811 }, {
7812
7813 name: jsontest.Name("Methods/MapKey/JSONv2"),
7814 inBuf: `{"k1":"v1b","k2":"v2"}`,
7815 inVal: addr(map[structMethodJSONv2]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7816 want: addr(map[structMethodJSONv2]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7817 }, {
7818
7819 name: jsontest.Name("Methods/MapKey/JSONv1"),
7820 inBuf: `{"k1":"v1b","k2":"v2"}`,
7821 inVal: addr(map[structMethodJSONv1]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7822 want: addr(map[structMethodJSONv1]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7823 }, {
7824 name: jsontest.Name("Methods/MapKey/Text"),
7825 inBuf: `{"k1":"v1b","k2":"v2"}`,
7826 inVal: addr(map[structMethodText]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7827 want: addr(map[structMethodText]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7828 }, {
7829 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
7830 inBuf: `{}`,
7831 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7832 return errSomeError
7833 })),
7834 wantErr: EU(errSomeError).withType(0, T[unmarshalJSONv2Func]()),
7835 }, {
7836 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
7837 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7838 return nil
7839 })),
7840 wantErr: EU(errNonSingularValue).withType(0, T[unmarshalJSONv2Func]()),
7841 }, {
7842 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
7843 inBuf: `{}{}`,
7844 inVal: addr(unmarshalJSONv2Func(func(dec *jsontext.Decoder) error {
7845 dec.ReadValue()
7846 dec.ReadValue()
7847 return nil
7848 })),
7849 wantErr: EU(errNonSingularValue).withPos(`{}`, "").withType(0, T[unmarshalJSONv2Func]()),
7850 }, {
7851 name: jsontest.Name("Methods/Invalid/JSONv2/SkipFunc"),
7852 inBuf: `{}`,
7853 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7854 return SkipFunc
7855 })),
7856 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType(0, T[unmarshalJSONv2Func]()),
7857 }, {
7858 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
7859 inBuf: `{}`,
7860 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7861 return errSomeError
7862 })),
7863 wantErr: EU(errSomeError).withType('{', T[unmarshalJSONv1Func]()),
7864 }, {
7865 name: jsontest.Name("Methods/Invalid/JSONv1/SkipFunc"),
7866 inBuf: `{}`,
7867 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7868 return SkipFunc
7869 })),
7870 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType('{', T[unmarshalJSONv1Func]()),
7871 }, {
7872 name: jsontest.Name("Methods/Invalid/Text/Error"),
7873 inBuf: `"value"`,
7874 inVal: addr(unmarshalTextFunc(func([]byte) error {
7875 return errSomeError
7876 })),
7877 wantErr: EU(errSomeError).withType('"', T[unmarshalTextFunc]()),
7878 }, {
7879 name: jsontest.Name("Methods/Invalid/Text/Syntax"),
7880 inBuf: `{}`,
7881 inVal: addr(unmarshalTextFunc(func([]byte) error {
7882 panic("should not be called")
7883 })),
7884 wantErr: EU(errNonStringValue).withType('{', T[unmarshalTextFunc]()),
7885 }, {
7886 name: jsontest.Name("Methods/Invalid/Text/SkipFunc"),
7887 inBuf: `"value"`,
7888 inVal: addr(unmarshalTextFunc(func([]byte) error {
7889 return SkipFunc
7890 })),
7891 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType('"', T[unmarshalTextFunc]()),
7892 }, {
7893 name: jsontest.Name("Functions/String/V1"),
7894 opts: []Options{
7895 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7896 if string(b) != `""` {
7897 return fmt.Errorf("got %s, want %s", b, `""`)
7898 }
7899 *v = "called"
7900 return nil
7901 })),
7902 },
7903 inBuf: `""`,
7904 inVal: addr(""),
7905 want: addr("called"),
7906 }, {
7907 name: jsontest.Name("Functions/String/Empty"),
7908 opts: []Options{WithUnmarshalers(nil)},
7909 inBuf: `"hello"`,
7910 inVal: addr(""),
7911 want: addr("hello"),
7912 }, {
7913 name: jsontest.Name("Functions/NamedString/V1/NoMatch"),
7914 opts: []Options{
7915 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7916 panic("should not be called")
7917 })),
7918 },
7919 inBuf: `""`,
7920 inVal: addr(""),
7921 want: addr(""),
7922 }, {
7923 name: jsontest.Name("Functions/NamedString/V1/Match"),
7924 opts: []Options{
7925 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7926 if string(b) != `""` {
7927 return fmt.Errorf("got %s, want %s", b, `""`)
7928 }
7929 *v = "called"
7930 return nil
7931 })),
7932 },
7933 inBuf: `""`,
7934 inVal: addr(namedString("")),
7935 want: addr(namedString("called")),
7936 }, {
7937 name: jsontest.Name("Functions/String/V2"),
7938 opts: []Options{
7939 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
7940 switch b, err := dec.ReadValue(); {
7941 case err != nil:
7942 return err
7943 case string(b) != `""`:
7944 return fmt.Errorf("got %s, want %s", b, `""`)
7945 }
7946 *v = "called"
7947 return nil
7948 })),
7949 },
7950 inBuf: `""`,
7951 inVal: addr(""),
7952 want: addr("called"),
7953 }, {
7954 name: jsontest.Name("Functions/NamedString/V2/NoMatch"),
7955 opts: []Options{
7956 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7957 panic("should not be called")
7958 })),
7959 },
7960 inBuf: `""`,
7961 inVal: addr(""),
7962 want: addr(""),
7963 }, {
7964 name: jsontest.Name("Functions/NamedString/V2/Match"),
7965 opts: []Options{
7966 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7967 switch t, err := dec.ReadToken(); {
7968 case err != nil:
7969 return err
7970 case t.String() != ``:
7971 return fmt.Errorf("got %q, want %q", t, ``)
7972 }
7973 *v = "called"
7974 return nil
7975 })),
7976 },
7977 inBuf: `""`,
7978 inVal: addr(namedString("")),
7979 want: addr(namedString("called")),
7980 }, {
7981 name: jsontest.Name("Functions/String/Empty1/NoMatch"),
7982 opts: []Options{
7983 WithUnmarshalers(new(Unmarshalers)),
7984 },
7985 inBuf: `""`,
7986 inVal: addr(""),
7987 want: addr(""),
7988 }, {
7989 name: jsontest.Name("Functions/String/Empty2/NoMatch"),
7990 opts: []Options{
7991 WithUnmarshalers(JoinUnmarshalers()),
7992 },
7993 inBuf: `""`,
7994 inVal: addr(""),
7995 want: addr(""),
7996 }, {
7997 name: jsontest.Name("Functions/String/V1/DirectError"),
7998 opts: []Options{
7999 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8000 return errSomeError
8001 })),
8002 },
8003 inBuf: `""`,
8004 inVal: addr(""),
8005 want: addr(""),
8006 wantErr: EU(errSomeError).withType('"', reflect.PointerTo(stringType)),
8007 }, {
8008 name: jsontest.Name("Functions/String/V1/SkipError"),
8009 opts: []Options{
8010 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8011 return SkipFunc
8012 })),
8013 },
8014 inBuf: `""`,
8015 inVal: addr(""),
8016 want: addr(""),
8017 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal function of type func([]byte, T) error")).withType('"', reflect.PointerTo(stringType)),
8018 }, {
8019 name: jsontest.Name("Functions/String/V2/DirectError"),
8020 opts: []Options{
8021 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8022 return errSomeError
8023 })),
8024 },
8025 inBuf: `""`,
8026 inVal: addr(""),
8027 want: addr(""),
8028 wantErr: EU(errSomeError).withType(0, reflect.PointerTo(stringType)),
8029 }, {
8030 name: jsontest.Name("Functions/String/V2/TooFew"),
8031 opts: []Options{
8032 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8033 return nil
8034 })),
8035 },
8036 inBuf: `""`,
8037 inVal: addr(""),
8038 want: addr(""),
8039 wantErr: EU(errNonSingularValue).withType(0, reflect.PointerTo(stringType)),
8040 }, {
8041 name: jsontest.Name("Functions/String/V2/TooMany"),
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 if _, err := dec.ReadValue(); err != nil {
8048 return err
8049 }
8050 return nil
8051 })),
8052 },
8053 inBuf: `{"X":["",""]}`,
8054 inVal: addr(struct{ X []string }{}),
8055 want: addr(struct{ X []string }{[]string{""}}),
8056 wantErr: EU(errNonSingularValue).withPos(`{"X":["",`, "/X").withType(0, reflect.PointerTo(stringType)),
8057 }, {
8058 name: jsontest.Name("Functions/String/V2/Skipped"),
8059 opts: []Options{
8060 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8061 return SkipFunc
8062 })),
8063 },
8064 inBuf: `""`,
8065 inVal: addr(""),
8066 want: addr(""),
8067 }, {
8068 name: jsontest.Name("Functions/String/V2/ProcessBeforeSkip"),
8069 opts: []Options{
8070 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8071 if _, err := dec.ReadValue(); err != nil {
8072 return err
8073 }
8074 return SkipFunc
8075 })),
8076 },
8077 inBuf: `""`,
8078 inVal: addr(""),
8079 want: addr(""),
8080 wantErr: EU(errSkipMutation).withType(0, reflect.PointerTo(stringType)),
8081 }, {
8082 name: jsontest.Name("Functions/String/V2/WrappedSkipError"),
8083 opts: []Options{
8084 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8085 return fmt.Errorf("wrap: %w", SkipFunc)
8086 })),
8087 },
8088 inBuf: `""`,
8089 inVal: addr(""),
8090 want: addr(""),
8091 wantErr: EU(fmt.Errorf("wrap: %w", SkipFunc)).withType(0, reflect.PointerTo(stringType)),
8092 }, {
8093 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
8094 opts: []Options{
8095 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8096 if string(b) != `"hello"` {
8097 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8098 }
8099 *v = "called"
8100 return nil
8101 })),
8102 },
8103 inBuf: `{"hello":"world"}`,
8104 inVal: addr(map[nocaseString]string{}),
8105 want: addr(map[nocaseString]string{"called": "world"}),
8106 }, {
8107 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
8108 opts: []Options{
8109 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8110 if string(b) != `"hello"` {
8111 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8112 }
8113 *v.(*nocaseString) = "called"
8114 return nil
8115 })),
8116 },
8117 inBuf: `{"hello":"world"}`,
8118 inVal: addr(map[nocaseString]string{}),
8119 want: addr(map[nocaseString]string{"called": "world"}),
8120 }, {
8121 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
8122 opts: []Options{
8123 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8124 switch t, err := dec.ReadToken(); {
8125 case err != nil:
8126 return err
8127 case t.String() != "hello":
8128 return fmt.Errorf("got %q, want %q", t, "hello")
8129 }
8130 *v = "called"
8131 return nil
8132 })),
8133 },
8134 inBuf: `{"hello":"world"}`,
8135 inVal: addr(map[nocaseString]string{}),
8136 want: addr(map[nocaseString]string{"called": "world"}),
8137 }, {
8138 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
8139 opts: []Options{
8140 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8141 switch b, err := dec.ReadValue(); {
8142 case err != nil:
8143 return err
8144 case string(b) != `"hello"`:
8145 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8146 }
8147 *v.(*nocaseString) = "called"
8148 return nil
8149 })),
8150 },
8151 inBuf: `{"hello":"world"}`,
8152 inVal: addr(map[nocaseString]string{}),
8153 want: addr(map[nocaseString]string{"called": "world"}),
8154 }, {
8155 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
8156 opts: []Options{
8157 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8158 if _, err := dec.ReadValue(); err != nil {
8159 return err
8160 }
8161 xd := export.Decoder(dec)
8162 *v = fmt.Sprintf("%d-%d", len(xd.Tokens.Stack), xd.Tokens.Last.Length())
8163 return nil
8164 })),
8165 },
8166 inBuf: `{"name":"value","name":"value"}`,
8167 inVal: addr(map[string]string{}),
8168 want: addr(map[string]string{"1-1": "1-2"}),
8169 wantErr: newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"value",`)),
8170 }, {
8171 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
8172 opts: []Options{
8173 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8174 if string(b) != `"world"` {
8175 return fmt.Errorf("got %s, want %s", b, `"world"`)
8176 }
8177 *v = "called"
8178 return nil
8179 })),
8180 },
8181 inBuf: `{"hello":"world"}`,
8182 inVal: addr(map[string]nocaseString{}),
8183 want: addr(map[string]nocaseString{"hello": "called"}),
8184 }, {
8185 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
8186 opts: []Options{
8187 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8188 if string(b) != `"world"` {
8189 return fmt.Errorf("got %s, want %s", b, `"world"`)
8190 }
8191 *v.(*nocaseString) = "called"
8192 return nil
8193 })),
8194 },
8195 inBuf: `{"hello":"world"}`,
8196 inVal: addr(map[string]nocaseString{}),
8197 want: addr(map[string]nocaseString{"hello": "called"}),
8198 }, {
8199 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
8200 opts: []Options{
8201 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8202 switch t, err := dec.ReadToken(); {
8203 case err != nil:
8204 return err
8205 case t.String() != "world":
8206 return fmt.Errorf("got %q, want %q", t, "world")
8207 }
8208 *v = "called"
8209 return nil
8210 })),
8211 },
8212 inBuf: `{"hello":"world"}`,
8213 inVal: addr(map[string]nocaseString{}),
8214 want: addr(map[string]nocaseString{"hello": "called"}),
8215 }, {
8216 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
8217 opts: []Options{
8218 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8219 switch b, err := dec.ReadValue(); {
8220 case err != nil:
8221 return err
8222 case string(b) != `"world"`:
8223 return fmt.Errorf("got %s, want %s", b, `"world"`)
8224 }
8225 *v.(*nocaseString) = "called"
8226 return nil
8227 })),
8228 },
8229 inBuf: `{"hello":"world"}`,
8230 inVal: addr(map[string]nocaseString{}),
8231 want: addr(map[string]nocaseString{"hello": "called"}),
8232 }, {
8233 name: jsontest.Name("Funtions/Struct/Fields"),
8234 opts: []Options{
8235 WithUnmarshalers(JoinUnmarshalers(
8236 UnmarshalFunc(func(b []byte, v *bool) error {
8237 if string(b) != `"called1"` {
8238 return fmt.Errorf("got %s, want %s", b, `"called1"`)
8239 }
8240 *v = true
8241 return nil
8242 }),
8243 UnmarshalFunc(func(b []byte, v *string) error {
8244 if string(b) != `"called2"` {
8245 return fmt.Errorf("got %s, want %s", b, `"called2"`)
8246 }
8247 *v = "called2"
8248 return nil
8249 }),
8250 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[]byte) error {
8251 switch t, err := dec.ReadToken(); {
8252 case err != nil:
8253 return err
8254 case t.String() != "called3":
8255 return fmt.Errorf("got %q, want %q", t, "called3")
8256 }
8257 *v = []byte("called3")
8258 return nil
8259 }),
8260 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *int64) error {
8261 switch b, err := dec.ReadValue(); {
8262 case err != nil:
8263 return err
8264 case string(b) != `"called4"`:
8265 return fmt.Errorf("got %s, want %s", b, `"called4"`)
8266 }
8267 *v = 123
8268 return nil
8269 }),
8270 )),
8271 },
8272 inBuf: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":456,"Float":789}`,
8273 inVal: addr(structScalars{}),
8274 want: addr(structScalars{Bool: true, String: "called2", Bytes: []byte("called3"), Int: 123, Uint: 456, Float: 789}),
8275 }, {
8276 name: jsontest.Name("Functions/Struct/Inlined"),
8277 opts: []Options{
8278 WithUnmarshalers(JoinUnmarshalers(
8279 UnmarshalFunc(func([]byte, *structInlinedL1) error {
8280 panic("should not be called")
8281 }),
8282 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *StructEmbed2) error {
8283 panic("should not be called")
8284 }),
8285 )),
8286 },
8287 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
8288 inVal: new(structInlined),
8289 want: addr(structInlined{
8290 X: structInlinedL1{
8291 X: &structInlinedL2{A: "A1", B: "B1" },
8292 StructEmbed1: StructEmbed1{ D: "D2" },
8293 },
8294 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
8295 }),
8296 }, {
8297 name: jsontest.Name("Functions/Slice/Elem"),
8298 opts: []Options{
8299 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8300 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8301 return nil
8302 })),
8303 },
8304 inBuf: `["hello","World"]`,
8305 inVal: addr([]string{}),
8306 want: addr([]string{"HELLO", "WORLD"}),
8307 }, {
8308 name: jsontest.Name("Functions/Array/Elem"),
8309 opts: []Options{
8310 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8311 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8312 return nil
8313 })),
8314 },
8315 inBuf: `["hello","World"]`,
8316 inVal: addr([2]string{}),
8317 want: addr([2]string{"HELLO", "WORLD"}),
8318 }, {
8319 name: jsontest.Name("Functions/Pointer/Nil"),
8320 opts: []Options{
8321 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8322 t, err := dec.ReadToken()
8323 *v = strings.ToUpper(t.String())
8324 return err
8325 })),
8326 },
8327 inBuf: `{"X":"hello"}`,
8328 inVal: addr(struct{ X *string }{nil}),
8329 want: addr(struct{ X *string }{addr("HELLO")}),
8330 }, {
8331 name: jsontest.Name("Functions/Pointer/NonNil"),
8332 opts: []Options{
8333 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8334 t, err := dec.ReadToken()
8335 *v = strings.ToUpper(t.String())
8336 return err
8337 })),
8338 },
8339 inBuf: `{"X":"hello"}`,
8340 inVal: addr(struct{ X *string }{addr("")}),
8341 want: addr(struct{ X *string }{addr("HELLO")}),
8342 }, {
8343 name: jsontest.Name("Functions/Interface/Nil"),
8344 opts: []Options{
8345 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v fmt.Stringer) error {
8346 panic("should not be called")
8347 })),
8348 },
8349 inBuf: `{"X":"hello"}`,
8350 inVal: addr(struct{ X fmt.Stringer }{nil}),
8351 want: addr(struct{ X fmt.Stringer }{nil}),
8352 wantErr: EU(internal.ErrNilInterface).withPos(`{"X":`, "/X").withType(0, T[fmt.Stringer]()),
8353 }, {
8354 name: jsontest.Name("Functions/Interface/NetIP"),
8355 opts: []Options{
8356 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8357 *v = net.IP{}
8358 return SkipFunc
8359 })),
8360 },
8361 inBuf: `{"X":"1.1.1.1"}`,
8362 inVal: addr(struct{ X fmt.Stringer }{nil}),
8363 want: addr(struct{ X fmt.Stringer }{net.IPv4(1, 1, 1, 1)}),
8364 }, {
8365 name: jsontest.Name("Functions/Interface/NewPointerNetIP"),
8366 opts: []Options{
8367 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8368 *v = new(net.IP)
8369 return SkipFunc
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(1, 1, 1, 1))}),
8375 }, {
8376 name: jsontest.Name("Functions/Interface/NilPointerNetIP"),
8377 opts: []Options{
8378 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8379 *v = (*net.IP)(nil)
8380 return SkipFunc
8381 })),
8382 },
8383 inBuf: `{"X":"1.1.1.1"}`,
8384 inVal: addr(struct{ X fmt.Stringer }{nil}),
8385 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}),
8386 }, {
8387 name: jsontest.Name("Functions/Interface/NilPointerNetIP/Override"),
8388 opts: []Options{
8389 WithUnmarshalers(JoinUnmarshalers(
8390 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8391 *v = (*net.IP)(nil)
8392 return SkipFunc
8393 }),
8394 UnmarshalFunc(func(b []byte, v *net.IP) error {
8395 b = bytes.ReplaceAll(b, []byte(`1`), []byte(`8`))
8396 return v.UnmarshalText(bytes.Trim(b, `"`))
8397 }),
8398 )),
8399 },
8400 inBuf: `{"X":"1.1.1.1"}`,
8401 inVal: addr(struct{ X fmt.Stringer }{nil}),
8402 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(8, 8, 8, 8))}),
8403 }, {
8404 name: jsontest.Name("Functions/Interface/Any"),
8405 inBuf: `[null,{},{},{},{},{},{},{},{},{},{},{},{},"LAST"]`,
8406 inVal: addr([...]any{
8407 nil,
8408 valueStringer{},
8409 (*valueStringer)(nil),
8410 addr(valueStringer{}),
8411 (**valueStringer)(nil),
8412 addr((*valueStringer)(nil)),
8413 addr(addr(valueStringer{})),
8414 pointerStringer{},
8415 (*pointerStringer)(nil),
8416 addr(pointerStringer{}),
8417 (**pointerStringer)(nil),
8418 addr((*pointerStringer)(nil)),
8419 addr(addr(pointerStringer{})),
8420 "LAST",
8421 }),
8422 opts: []Options{
8423 WithUnmarshalers(func() *Unmarshalers {
8424 type P struct {
8425 D int
8426 N int64
8427 }
8428 type PV struct {
8429 P P
8430 V any
8431 }
8432
8433 var lastChecks []func() error
8434 checkLast := func() error {
8435 for _, fn := range lastChecks {
8436 if err := fn(); err != nil {
8437 return err
8438 }
8439 }
8440 return SkipFunc
8441 }
8442 makeValueChecker := func(name string, want []PV) func(d *jsontext.Decoder, v any) error {
8443 checkNext := func(d *jsontext.Decoder, v any) error {
8444 xd := export.Decoder(d)
8445 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8446 rv := reflect.ValueOf(v)
8447 pv := PV{p, v}
8448 switch {
8449 case len(want) == 0:
8450 return fmt.Errorf("%s: %v: got more values than expected", name, p)
8451 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
8452 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
8453 case !reflect.DeepEqual(pv, want[0]):
8454 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
8455 default:
8456 want = want[1:]
8457 return SkipFunc
8458 }
8459 }
8460 lastChecks = append(lastChecks, func() error {
8461 if len(want) > 0 {
8462 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8463 }
8464 return nil
8465 })
8466 return checkNext
8467 }
8468 makePositionChecker := func(name string, want []P) func(d *jsontext.Decoder, v any) error {
8469 checkNext := func(d *jsontext.Decoder, v any) error {
8470 xd := export.Decoder(d)
8471 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8472 switch {
8473 case len(want) == 0:
8474 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
8475 case p != want[0]:
8476 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
8477 default:
8478 want = want[1:]
8479 return SkipFunc
8480 }
8481 }
8482 lastChecks = append(lastChecks, func() error {
8483 if len(want) > 0 {
8484 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8485 }
8486 return nil
8487 })
8488 return checkNext
8489 }
8490
8491
8492
8493 wantAny := []PV{
8494 {P{1, 0}, addr(any(nil))},
8495 {P{1, 1}, addr(any(valueStringer{}))},
8496 {P{1, 1}, addr(valueStringer{})},
8497 {P{1, 2}, addr(any((*valueStringer)(nil)))},
8498 {P{1, 2}, addr((*valueStringer)(nil))},
8499 {P{1, 2}, addr(valueStringer{})},
8500 {P{1, 3}, addr(any(addr(valueStringer{})))},
8501 {P{1, 3}, addr(addr(valueStringer{}))},
8502 {P{1, 3}, addr(valueStringer{})},
8503 {P{1, 4}, addr(any((**valueStringer)(nil)))},
8504 {P{1, 4}, addr((**valueStringer)(nil))},
8505 {P{1, 4}, addr((*valueStringer)(nil))},
8506 {P{1, 4}, addr(valueStringer{})},
8507 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
8508 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
8509 {P{1, 5}, addr((*valueStringer)(nil))},
8510 {P{1, 5}, addr(valueStringer{})},
8511 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
8512 {P{1, 6}, addr(addr(addr(valueStringer{})))},
8513 {P{1, 6}, addr(addr(valueStringer{}))},
8514 {P{1, 6}, addr(valueStringer{})},
8515 {P{1, 7}, addr(any(pointerStringer{}))},
8516 {P{1, 7}, addr(pointerStringer{})},
8517 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
8518 {P{1, 8}, addr((*pointerStringer)(nil))},
8519 {P{1, 8}, addr(pointerStringer{})},
8520 {P{1, 9}, addr(any(addr(pointerStringer{})))},
8521 {P{1, 9}, addr(addr(pointerStringer{}))},
8522 {P{1, 9}, addr(pointerStringer{})},
8523 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
8524 {P{1, 10}, addr((**pointerStringer)(nil))},
8525 {P{1, 10}, addr((*pointerStringer)(nil))},
8526 {P{1, 10}, addr(pointerStringer{})},
8527 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
8528 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
8529 {P{1, 11}, addr((*pointerStringer)(nil))},
8530 {P{1, 11}, addr(pointerStringer{})},
8531 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
8532 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
8533 {P{1, 12}, addr(addr(pointerStringer{}))},
8534 {P{1, 12}, addr(pointerStringer{})},
8535 {P{1, 13}, addr(any("LAST"))},
8536 {P{1, 13}, addr("LAST")},
8537 }
8538 checkAny := makeValueChecker("any", wantAny)
8539 anyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v any) error {
8540 return checkAny(dec, v)
8541 })
8542
8543 var wantPointerAny []PV
8544 for _, v := range wantAny {
8545 if _, ok := v.V.(*any); ok {
8546 wantPointerAny = append(wantPointerAny, v)
8547 }
8548 }
8549 checkPointerAny := makeValueChecker("*any", wantPointerAny)
8550 pointerAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *any) error {
8551 return checkPointerAny(dec, v)
8552 })
8553
8554 checkNamedAny := makeValueChecker("namedAny", wantAny)
8555 namedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v namedAny) error {
8556 return checkNamedAny(dec, v)
8557 })
8558
8559 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
8560 pointerNamedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedAny) error {
8561 return checkPointerNamedAny(dec, v)
8562 })
8563
8564 type stringer = fmt.Stringer
8565 var wantStringer []PV
8566 for _, v := range wantAny {
8567 if _, ok := v.V.(stringer); ok {
8568 wantStringer = append(wantStringer, v)
8569 }
8570 }
8571 checkStringer := makeValueChecker("stringer", wantStringer)
8572 stringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v stringer) error {
8573 return checkStringer(dec, v)
8574 })
8575
8576 checkPointerStringer := makeValueChecker("*stringer", nil)
8577 pointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *stringer) error {
8578 return checkPointerStringer(dec, v)
8579 })
8580
8581 wantValueStringer := []P{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}}
8582 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
8583 pointerValueStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *valueStringer) error {
8584 return checkPointerValueStringer(dec, v)
8585 })
8586
8587 wantPointerStringer := []P{{1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}}
8588 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
8589 pointerPointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *pointerStringer) error {
8590 return checkPointerPointerStringer(dec, v)
8591 })
8592
8593 lastUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8594 return checkLast()
8595 })
8596
8597 return JoinUnmarshalers(
8598
8599
8600 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[14]any) error {
8601 if _, err := dec.ReadToken(); err != nil {
8602 return err
8603 }
8604 for i := range len(*v) {
8605 if err := UnmarshalDecode(dec, &(*v)[i]); err != nil {
8606 return err
8607 }
8608 }
8609 if _, err := dec.ReadToken(); err != nil {
8610 return err
8611 }
8612 return nil
8613 }),
8614
8615 anyUnmarshaler,
8616 pointerAnyUnmarshaler,
8617 namedAnyUnmarshaler,
8618 pointerNamedAnyUnmarshaler,
8619 stringerUnmarshaler,
8620 pointerStringerUnmarshaler,
8621 pointerValueStringerUnmarshaler,
8622 pointerPointerStringerUnmarshaler,
8623 lastUnmarshaler,
8624 )
8625 }()),
8626 },
8627 }, {
8628 name: jsontest.Name("Functions/Precedence/V1First"),
8629 opts: []Options{
8630 WithUnmarshalers(JoinUnmarshalers(
8631 UnmarshalFunc(func(b []byte, v *string) error {
8632 if string(b) != `"called"` {
8633 return fmt.Errorf("got %s, want %s", b, `"called"`)
8634 }
8635 *v = "called"
8636 return nil
8637 }),
8638 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8639 panic("should not be called")
8640 }),
8641 )),
8642 },
8643 inBuf: `"called"`,
8644 inVal: addr(""),
8645 want: addr("called"),
8646 }, {
8647 name: jsontest.Name("Functions/Precedence/V2First"),
8648 opts: []Options{
8649 WithUnmarshalers(JoinUnmarshalers(
8650 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8651 switch t, err := dec.ReadToken(); {
8652 case err != nil:
8653 return err
8654 case t.String() != "called":
8655 return fmt.Errorf("got %q, want %q", t, "called")
8656 }
8657 *v = "called"
8658 return nil
8659 }),
8660 UnmarshalFunc(func([]byte, *string) error {
8661 panic("should not be called")
8662 }),
8663 )),
8664 },
8665 inBuf: `"called"`,
8666 inVal: addr(""),
8667 want: addr("called"),
8668 }, {
8669 name: jsontest.Name("Functions/Precedence/V2Skipped"),
8670 opts: []Options{
8671 WithUnmarshalers(JoinUnmarshalers(
8672 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8673 return SkipFunc
8674 }),
8675 UnmarshalFunc(func(b []byte, v *string) error {
8676 if string(b) != `"called"` {
8677 return fmt.Errorf("got %s, want %s", b, `"called"`)
8678 }
8679 *v = "called"
8680 return nil
8681 }),
8682 )),
8683 },
8684 inBuf: `"called"`,
8685 inVal: addr(""),
8686 want: addr("called"),
8687 }, {
8688 name: jsontest.Name("Functions/Precedence/NestedFirst"),
8689 opts: []Options{
8690 WithUnmarshalers(JoinUnmarshalers(
8691 JoinUnmarshalers(
8692 UnmarshalFunc(func(b []byte, v *string) error {
8693 if string(b) != `"called"` {
8694 return fmt.Errorf("got %s, want %s", b, `"called"`)
8695 }
8696 *v = "called"
8697 return nil
8698 }),
8699 ),
8700 UnmarshalFunc(func([]byte, *string) error {
8701 panic("should not be called")
8702 }),
8703 )),
8704 },
8705 inBuf: `"called"`,
8706 inVal: addr(""),
8707 want: addr("called"),
8708 }, {
8709 name: jsontest.Name("Functions/Precedence/NestedLast"),
8710 opts: []Options{
8711 WithUnmarshalers(JoinUnmarshalers(
8712 UnmarshalFunc(func(b []byte, v *string) error {
8713 if string(b) != `"called"` {
8714 return fmt.Errorf("got %s, want %s", b, `"called"`)
8715 }
8716 *v = "called"
8717 return nil
8718 }),
8719 JoinUnmarshalers(
8720 UnmarshalFunc(func([]byte, *string) error {
8721 panic("should not be called")
8722 }),
8723 ),
8724 )),
8725 },
8726 inBuf: `"called"`,
8727 inVal: addr(""),
8728 want: addr("called"),
8729 }, {
8730 name: jsontest.Name("Duration/Null"),
8731 inBuf: `{"D1":null,"D2":null}`,
8732 inVal: addr(struct {
8733 D1 time.Duration `json:",format:units"`
8734 D2 time.Duration `json:",format:nano"`
8735 }{1, 1}),
8736 want: addr(struct {
8737 D1 time.Duration `json:",format:units"`
8738 D2 time.Duration `json:",format:nano"`
8739 }{0, 0}),
8740 }, {
8741 name: jsontest.Name("Duration/Zero"),
8742 inBuf: `{"D1":"0s","D2":0}`,
8743 inVal: addr(struct {
8744 D1 time.Duration `json:",format:units"`
8745 D2 time.Duration `json:",format:nano"`
8746 }{1, 1}),
8747 want: addr(struct {
8748 D1 time.Duration `json:",format:units"`
8749 D2 time.Duration `json:",format:nano"`
8750 }{0, 0}),
8751 }, {
8752 name: jsontest.Name("Duration/Positive"),
8753 inBuf: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
8754 inVal: new(struct {
8755 D1 time.Duration `json:",format:units"`
8756 D2 time.Duration `json:",format:nano"`
8757 }),
8758 want: addr(struct {
8759 D1 time.Duration `json:",format:units"`
8760 D2 time.Duration `json:",format:nano"`
8761 }{
8762 123456789123456789,
8763 123456789123456789,
8764 }),
8765 }, {
8766 name: jsontest.Name("Duration/Negative"),
8767 inBuf: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
8768 inVal: new(struct {
8769 D1 time.Duration `json:",format:units"`
8770 D2 time.Duration `json:",format:nano"`
8771 }),
8772 want: addr(struct {
8773 D1 time.Duration `json:",format:units"`
8774 D2 time.Duration `json:",format:nano"`
8775 }{
8776 -123456789123456789,
8777 -123456789123456789,
8778 }),
8779 }, {
8780 name: jsontest.Name("Duration/Nanos/String"),
8781 inBuf: `{"D":"12345"}`,
8782 inVal: addr(struct {
8783 D time.Duration `json:",string,format:nano"`
8784 }{1}),
8785 want: addr(struct {
8786 D time.Duration `json:",string,format:nano"`
8787 }{12345}),
8788 }, {
8789 name: jsontest.Name("Duration/Nanos/String/Invalid"),
8790 inBuf: `{"D":"+12345"}`,
8791 inVal: addr(struct {
8792 D time.Duration `json:",string,format:nano"`
8793 }{1}),
8794 want: addr(struct {
8795 D time.Duration `json:",string,format:nano"`
8796 }{1}),
8797 wantErr: EU(fmt.Errorf(`invalid duration "+12345": %w`, strconv.ErrSyntax)).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8798 }, {
8799 name: jsontest.Name("Duration/Nanos/Mismatch"),
8800 inBuf: `{"D":"34293h33m9.123456789s"}`,
8801 inVal: addr(struct {
8802 D time.Duration `json:",format:nano"`
8803 }{1}),
8804 want: addr(struct {
8805 D time.Duration `json:",format:nano"`
8806 }{1}),
8807 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8808 }, {
8809 name: jsontest.Name("Duration/Nanos"),
8810 inBuf: `{"D":1.324}`,
8811 inVal: addr(struct {
8812 D time.Duration `json:",format:nano"`
8813 }{-1}),
8814 want: addr(struct {
8815 D time.Duration `json:",format:nano"`
8816 }{1}),
8817 }, {
8818 name: jsontest.Name("Duration/String/Mismatch"),
8819 inBuf: `{"D":-123456789123456789}`,
8820 inVal: addr(struct {
8821 D time.Duration `json:",format:units"`
8822 }{1}),
8823 want: addr(struct {
8824 D time.Duration `json:",format:units"`
8825 }{1}),
8826 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('0', timeDurationType),
8827 }, {
8828 name: jsontest.Name("Duration/String/Invalid"),
8829 inBuf: `{"D":"5minkutes"}`,
8830 inVal: addr(struct {
8831 D time.Duration `json:",format:units"`
8832 }{1}),
8833 want: addr(struct {
8834 D time.Duration `json:",format:units"`
8835 }{1}),
8836 wantErr: EU(func() error {
8837 _, err := time.ParseDuration("5minkutes")
8838 return err
8839 }()).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8840 }, {
8841 name: jsontest.Name("Duration/Syntax/Invalid"),
8842 inBuf: `{"D":x}`,
8843 inVal: addr(struct {
8844 D time.Duration `json:",format:units"`
8845 }{1}),
8846 want: addr(struct {
8847 D time.Duration `json:",format:units"`
8848 }{1}),
8849 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"D":`), "/D"),
8850 }, {
8851 name: jsontest.Name("Duration/Format"),
8852 inBuf: `{
8853 "D1": "12h34m56.078090012s",
8854 "D2": "12h34m56.078090012s",
8855 "D3": 45296.078090012,
8856 "D4": "45296.078090012",
8857 "D5": 45296078.090012,
8858 "D6": "45296078.090012",
8859 "D7": 45296078090.012,
8860 "D8": "45296078090.012",
8861 "D9": 45296078090012,
8862 "D10": "45296078090012",
8863 "D11": "PT12H34M56.078090012S"
8864 }`,
8865 inVal: new(structDurationFormat),
8866 want: addr(structDurationFormat{
8867 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8868 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8869 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8870 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8871 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8872 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8873 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8874 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8875 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8876 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8877 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8878 }),
8879 }, {
8880 name: jsontest.Name("Duration/Format/Invalid"),
8881 inBuf: `{"D":"0s"}`,
8882 inVal: addr(struct {
8883 D time.Duration `json:",format:invalid"`
8884 }{1}),
8885 want: addr(struct {
8886 D time.Duration `json:",format:invalid"`
8887 }{1}),
8888 wantErr: EU(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, timeDurationType),
8889 }, {
8890
8900
8906 name: jsontest.Name("Duration/MapKey/Legacy"),
8907 opts: []Options{jsonflags.FormatDurationAsNano | 1},
8908 inBuf: `{"1000000000":""}`,
8909 inVal: new(map[time.Duration]string),
8910 want: addr(map[time.Duration]string{time.Second: ""}),
8911 }, {
8912
8919 name: jsontest.Name("Time/Zero"),
8920 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"}`,
8921 inVal: new(struct {
8922 T1 time.Time
8923 T2 time.Time `json:",format:RFC822"`
8924 T3 time.Time `json:",format:'2006-01-02'"`
8925 T4 time.Time `json:",omitzero"`
8926 T5 time.Time `json:",omitempty"`
8927 }),
8928 want: addr(struct {
8929 T1 time.Time
8930 T2 time.Time `json:",format:RFC822"`
8931 T3 time.Time `json:",format:'2006-01-02'"`
8932 T4 time.Time `json:",omitzero"`
8933 T5 time.Time `json:",omitempty"`
8934 }{
8935 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8936 mustParseTime(time.RFC822, "01 Jan 01 00:00 UTC"),
8937 mustParseTime("2006-01-02", "0001-01-01"),
8938 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8939 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8940 }),
8941 }, {
8942 name: jsontest.Name("Time/Format"),
8943 inBuf: `{
8944 "T1": "1234-01-02T03:04:05.000000006Z",
8945 "T2": "Mon Jan 2 03:04:05 1234",
8946 "T3": "Mon Jan 2 03:04:05 UTC 1234",
8947 "T4": "Mon Jan 02 03:04:05 +0000 1234",
8948 "T5": "02 Jan 34 03:04 UTC",
8949 "T6": "02 Jan 34 03:04 +0000",
8950 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
8951 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
8952 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
8953 "T10": "1234-01-02T03:04:05Z",
8954 "T11": "1234-01-02T03:04:05.000000006Z",
8955 "T12": "3:04AM",
8956 "T13": "Jan 2 03:04:05",
8957 "T14": "Jan 2 03:04:05.000",
8958 "T15": "Jan 2 03:04:05.000000",
8959 "T16": "Jan 2 03:04:05.000000006",
8960 "T17": "1234-01-02 03:04:05",
8961 "T18": "1234-01-02",
8962 "T19": "03:04:05",
8963 "T20": "1234-01-02",
8964 "T21": "\"weird\"1234",
8965 "T22": -23225777754.999999994,
8966 "T23": "-23225777754.999999994",
8967 "T24": -23225777754999.999994,
8968 "T25": "-23225777754999.999994",
8969 "T26": -23225777754999999.994,
8970 "T27": "-23225777754999999.994",
8971 "T28": -23225777754999999994,
8972 "T29": "-23225777754999999994"
8973 }`,
8974 inVal: new(structTimeFormat),
8975 want: addr(structTimeFormat{
8976 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8977 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
8978 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
8979 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
8980 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
8981 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
8982 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
8983 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
8984 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
8985 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
8986 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8987 mustParseTime(time.Kitchen, "3:04AM"),
8988 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
8989 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
8990 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
8991 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
8992 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
8993 mustParseTime(time.DateOnly, "1234-01-02"),
8994 mustParseTime(time.TimeOnly, "03:04:05"),
8995 mustParseTime("2006-01-02", "1234-01-02"),
8996 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
8997 time.Unix(-23225777755, 6).UTC(),
8998 time.Unix(-23225777755, 6).UTC(),
8999 time.Unix(-23225777755, 6).UTC(),
9000 time.Unix(-23225777755, 6).UTC(),
9001 time.Unix(-23225777755, 6).UTC(),
9002 time.Unix(-23225777755, 6).UTC(),
9003 time.Unix(-23225777755, 6).UTC(),
9004 time.Unix(-23225777755, 6).UTC(),
9005 }),
9006 }, {
9007 name: jsontest.Name("Time/Format/UnixString/InvalidNumber"),
9008 inBuf: `{
9009 "T23": -23225777754.999999994,
9010 "T25": -23225777754999.999994,
9011 "T27": -23225777754999999.994,
9012 "T29": -23225777754999999994
9013 }`,
9014 inVal: new(structTimeFormat),
9015 want: new(structTimeFormat),
9016 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T23": `, "/T23").withType('0', timeTimeType),
9017 }, {
9018 name: jsontest.Name("Time/Format/UnixString/InvalidString"),
9019 inBuf: `{
9020 "T22": "-23225777754.999999994",
9021 "T24": "-23225777754999.999994",
9022 "T26": "-23225777754999999.994",
9023 "T28": "-23225777754999999994"
9024 }`,
9025 inVal: new(structTimeFormat),
9026 want: new(structTimeFormat),
9027 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T22": `, "/T22").withType('"', timeTimeType),
9028 }, {
9029 name: jsontest.Name("Time/Format/Null"),
9030 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}`,
9031 inVal: addr(structTimeFormat{
9032 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9033 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9034 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9035 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9036 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9037 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9038 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9039 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9040 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9041 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9042 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9043 mustParseTime(time.Kitchen, "3:04AM"),
9044 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9045 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9046 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9047 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9048 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9049 mustParseTime(time.DateOnly, "1234-01-02"),
9050 mustParseTime(time.TimeOnly, "03:04:05"),
9051 mustParseTime("2006-01-02", "1234-01-02"),
9052 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9053 time.Unix(-23225777755, 6).UTC(),
9054 time.Unix(-23225777755, 6).UTC(),
9055 time.Unix(-23225777755, 6).UTC(),
9056 time.Unix(-23225777755, 6).UTC(),
9057 time.Unix(-23225777755, 6).UTC(),
9058 time.Unix(-23225777755, 6).UTC(),
9059 time.Unix(-23225777755, 6).UTC(),
9060 time.Unix(-23225777755, 6).UTC(),
9061 }),
9062 want: new(structTimeFormat),
9063 }, {
9064 name: jsontest.Name("Time/RFC3339/Mismatch"),
9065 inBuf: `{"T":1234}`,
9066 inVal: new(struct {
9067 T time.Time
9068 }),
9069 wantErr: EU(nil).withPos(`{"T":`, "/T").withType('0', timeTimeType),
9070 }, {
9071 name: jsontest.Name("Time/RFC3339/ParseError"),
9072 inBuf: `{"T":"2021-09-29T12:44:52"}`,
9073 inVal: new(struct {
9074 T time.Time
9075 }),
9076 wantErr: EU(func() error {
9077 _, err := time.Parse(time.RFC3339, "2021-09-29T12:44:52")
9078 return err
9079 }()).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9080 }, {
9081 name: jsontest.Name("Time/Format/Invalid"),
9082 inBuf: `{"T":""}`,
9083 inVal: new(struct {
9084 T time.Time `json:",format:UndefinedConstant"`
9085 }),
9086 wantErr: EU(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
9087 }, {
9088 name: jsontest.Name("Time/Format/SingleDigitHour"),
9089 inBuf: `{"T":"2000-01-01T1:12:34Z"}`,
9090 inVal: new(struct{ T time.Time }),
9091 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T1:12:34Z", "15", "1", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9092 }, {
9093 name: jsontest.Name("Time/Format/SubsecondComma"),
9094 inBuf: `{"T":"2000-01-01T00:00:00,000Z"}`,
9095 inVal: new(struct{ T time.Time }),
9096 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00,000Z", ".", ",", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9097 }, {
9098 name: jsontest.Name("Time/Format/TimezoneHourOverflow"),
9099 inBuf: `{"T":"2000-01-01T00:00:00+24:00"}`,
9100 inVal: new(struct{ T time.Time }),
9101 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),
9102 }, {
9103 name: jsontest.Name("Time/Format/TimezoneMinuteOverflow"),
9104 inBuf: `{"T":"2000-01-01T00:00:00+00:60"}`,
9105 inVal: new(struct{ T time.Time }),
9106 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),
9107 }, {
9108 name: jsontest.Name("Time/Syntax/Invalid"),
9109 inBuf: `{"T":x}`,
9110 inVal: new(struct {
9111 T time.Time
9112 }),
9113 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"T":`), "/T"),
9114 }, {
9115 name: jsontest.Name("Time/IgnoreInvalidFormat"),
9116 opts: []Options{invalidFormatOption},
9117 inBuf: `"2000-01-01T00:00:00Z"`,
9118 inVal: addr(time.Time{}),
9119 want: addr(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)),
9120 }}
9121
9122 for _, tt := range tests {
9123 t.Run(tt.name.Name, func(t *testing.T) {
9124 got := tt.inVal
9125 gotErr := Unmarshal([]byte(tt.inBuf), got, tt.opts...)
9126 if !reflect.DeepEqual(got, tt.want) && tt.want != nil {
9127 t.Errorf("%s: Unmarshal output mismatch:\ngot %v\nwant %v", tt.name.Where, got, tt.want)
9128 }
9129 if !reflect.DeepEqual(gotErr, tt.wantErr) {
9130 t.Errorf("%s: Unmarshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
9131 }
9132 })
9133 }
9134 }
9135
9136 func TestMarshalInvalidNamespace(t *testing.T) {
9137 tests := []struct {
9138 name jsontest.CaseName
9139 val any
9140 }{
9141 {jsontest.Name("Map"), map[string]string{"X": "\xde\xad\xbe\xef"}},
9142 {jsontest.Name("Struct"), struct{ X string }{"\xde\xad\xbe\xef"}},
9143 }
9144 for _, tt := range tests {
9145 t.Run(tt.name.Name, func(t *testing.T) {
9146 enc := jsontext.NewEncoder(new(bytes.Buffer))
9147 if err := MarshalEncode(enc, tt.val); err == nil {
9148 t.Fatalf("%s: MarshalEncode error is nil, want non-nil", tt.name.Where)
9149 }
9150 for _, tok := range []jsontext.Token{
9151 jsontext.Null, jsontext.String(""), jsontext.Int(0), jsontext.BeginObject, jsontext.EndObject, jsontext.BeginArray, jsontext.EndArray,
9152 } {
9153 if err := enc.WriteToken(tok); err == nil {
9154 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9155 }
9156 }
9157 for _, val := range []string{`null`, `""`, `0`, `{}`, `[]`} {
9158 if err := enc.WriteValue([]byte(val)); err == nil {
9159 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9160 }
9161 }
9162 })
9163 }
9164 }
9165
9166 func TestUnmarshalInvalidNamespace(t *testing.T) {
9167 tests := []struct {
9168 name jsontest.CaseName
9169 val any
9170 }{
9171 {jsontest.Name("Map"), addr(map[string]int{})},
9172 {jsontest.Name("Struct"), addr(struct{ X int }{})},
9173 }
9174 for _, tt := range tests {
9175 t.Run(tt.name.Name, func(t *testing.T) {
9176 dec := jsontext.NewDecoder(strings.NewReader(`{"X":""}`))
9177 if err := UnmarshalDecode(dec, tt.val); err == nil {
9178 t.Fatalf("%s: UnmarshalDecode error is nil, want non-nil", tt.name.Where)
9179 }
9180 if _, err := dec.ReadToken(); err == nil {
9181 t.Fatalf("%s: ReadToken error is nil, want non-nil", tt.name.Where)
9182 }
9183 if _, err := dec.ReadValue(); err == nil {
9184 t.Fatalf("%s: ReadValue error is nil, want non-nil", tt.name.Where)
9185 }
9186 })
9187 }
9188 }
9189
9190 func TestUnmarshalReuse(t *testing.T) {
9191 t.Run("Bytes", func(t *testing.T) {
9192 in := make([]byte, 3)
9193 want := &in[0]
9194 if err := Unmarshal([]byte(`"AQID"`), &in); err != nil {
9195 t.Fatalf("Unmarshal error: %v", err)
9196 }
9197 got := &in[0]
9198 if got != want {
9199 t.Errorf("input buffer was not reused")
9200 }
9201 })
9202 t.Run("Slices", func(t *testing.T) {
9203 in := make([]int, 3)
9204 want := &in[0]
9205 if err := Unmarshal([]byte(`[0,1,2]`), &in); err != nil {
9206 t.Fatalf("Unmarshal error: %v", err)
9207 }
9208 got := &in[0]
9209 if got != want {
9210 t.Errorf("input slice was not reused")
9211 }
9212 })
9213 t.Run("Maps", func(t *testing.T) {
9214 in := make(map[string]string)
9215 want := reflect.ValueOf(in).Pointer()
9216 if err := Unmarshal([]byte(`{"key":"value"}`), &in); err != nil {
9217 t.Fatalf("Unmarshal error: %v", err)
9218 }
9219 got := reflect.ValueOf(in).Pointer()
9220 if got != want {
9221 t.Errorf("input map was not reused")
9222 }
9223 })
9224 t.Run("Pointers", func(t *testing.T) {
9225 in := addr(addr(addr("hello")))
9226 want := **in
9227 if err := Unmarshal([]byte(`"goodbye"`), &in); err != nil {
9228 t.Fatalf("Unmarshal error: %v", err)
9229 }
9230 got := **in
9231 if got != want {
9232 t.Errorf("input pointer was not reused")
9233 }
9234 })
9235 }
9236
9237 type ReaderFunc func([]byte) (int, error)
9238
9239 func (f ReaderFunc) Read(b []byte) (int, error) { return f(b) }
9240
9241 type WriterFunc func([]byte) (int, error)
9242
9243 func (f WriterFunc) Write(b []byte) (int, error) { return f(b) }
9244
9245 func TestCoderBufferGrowth(t *testing.T) {
9246
9247
9248 checkGrowth := func(ns []int) {
9249 t.Helper()
9250 var sumBytes, sumRates, numGrows float64
9251 prev := ns[0]
9252 for i := 1; i < len(ns)-1; i++ {
9253 n := ns[i]
9254 if n != prev {
9255 sumRates += float64(n) / float64(prev)
9256 numGrows++
9257 prev = n
9258 }
9259 if n > 1<<20 {
9260 t.Fatalf("single Read/Write too large: %d", n)
9261 }
9262 sumBytes += float64(n)
9263 }
9264 if mean := sumBytes / float64(len(ns)); mean < 1<<10 {
9265 t.Fatalf("average Read/Write too small: %0.1f", mean)
9266 }
9267 switch mean := sumRates / numGrows; {
9268 case mean < 1.25:
9269 t.Fatalf("average growth rate too slow: %0.3f", mean)
9270 case mean > 2.00:
9271 t.Fatalf("average growth rate too fast: %0.3f", mean)
9272 }
9273 }
9274
9275
9276
9277 bb := struct{ *bytes.Buffer }{new(bytes.Buffer)}
9278
9279 var writeSizes []int
9280 if err := MarshalWrite(WriterFunc(func(b []byte) (int, error) {
9281 n, err := bb.Write(b)
9282 writeSizes = append(writeSizes, n)
9283 return n, err
9284 }), make([]struct{}, 1e6)); err != nil {
9285 t.Fatalf("MarshalWrite error: %v", err)
9286 }
9287 checkGrowth(writeSizes)
9288
9289 var readSizes []int
9290 if err := UnmarshalRead(ReaderFunc(func(b []byte) (int, error) {
9291 n, err := bb.Read(b)
9292 readSizes = append(readSizes, n)
9293 return n, err
9294 }), new([]struct{})); err != nil {
9295 t.Fatalf("UnmarshalRead error: %v", err)
9296 }
9297 checkGrowth(readSizes)
9298 }
9299
9300 func TestUintSet(t *testing.T) {
9301 type operation any
9302 type has struct {
9303 in uint
9304 want bool
9305 }
9306 type insert struct {
9307 in uint
9308 want bool
9309 }
9310
9311
9312 ops := []operation{
9313 has{0, false},
9314 has{63, false},
9315 has{64, false},
9316 has{1234, false},
9317 insert{3, true},
9318 has{2, false},
9319 has{3, true},
9320 has{4, false},
9321 has{63, false},
9322 insert{3, false},
9323 insert{63, true},
9324 has{63, true},
9325 insert{64, true},
9326 insert{64, false},
9327 has{64, true},
9328 insert{3264, true},
9329 has{3264, true},
9330 insert{3, false},
9331 has{3, true},
9332 }
9333
9334 var us uintSet
9335 for i, op := range ops {
9336 switch op := op.(type) {
9337 case has:
9338 if got := us.has(op.in); got != op.want {
9339 t.Fatalf("%d: uintSet.has(%v) = %v, want %v", i, op.in, got, op.want)
9340 }
9341 case insert:
9342 if got := us.insert(op.in); got != op.want {
9343 t.Fatalf("%d: uintSet.insert(%v) = %v, want %v", i, op.in, got, op.want)
9344 }
9345 default:
9346 panic(fmt.Sprintf("unknown operation: %T", op))
9347 }
9348 }
9349 }
9350
9351 func TestUnmarshalDecodeOptions(t *testing.T) {
9352 var calledFuncs int
9353 var calledOptions Options
9354 in := strings.NewReader(strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9355 dec := jsontext.NewDecoder(in,
9356 jsontext.AllowInvalidUTF8(true),
9357 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ any) error {
9358 opts := dec.Options()
9359 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9360 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9361 }
9362 calledFuncs++
9363 calledOptions = opts
9364 return SkipFunc
9365 })),
9366 )
9367
9368 if err := UnmarshalDecode(dec, new(string)); err != nil {
9369 t.Fatalf("UnmarshalDecode: %v", err)
9370 }
9371 if calledFuncs != 1 {
9372 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9373 }
9374 if err := UnmarshalDecode(dec, new(string), calledOptions); err != nil {
9375 t.Fatalf("UnmarshalDecode: %v", err)
9376 }
9377 if calledFuncs != 2 {
9378 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9379 }
9380 if err := UnmarshalDecode(dec, new(string),
9381 jsontext.AllowInvalidUTF8(false),
9382 WithUnmarshalers(nil),
9383 ); 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)); err != nil {
9390 t.Fatalf("UnmarshalDecode: %v", err)
9391 }
9392 if calledFuncs != 3 {
9393 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9394 }
9395 if err := UnmarshalDecode(dec, new(string), JoinOptions(
9396 jsontext.AllowInvalidUTF8(false),
9397 WithUnmarshalers(UnmarshalFromFunc(func(_ *jsontext.Decoder, _ any) error {
9398 opts := dec.Options()
9399 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9400 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9401 }
9402 calledFuncs = math.MaxInt
9403 return SkipFunc
9404 })),
9405 )); err != nil {
9406 t.Fatalf("UnmarshalDecode: %v", err)
9407 }
9408 if calledFuncs != math.MaxInt {
9409 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9410 }
9411
9412
9413
9414 opts := dec.Options()
9415 dec.Reset(in, jsontext.AllowInvalidUTF8(false), opts)
9416 if v, _ := GetOption(dec.Options(), jsontext.AllowInvalidUTF8); v == false {
9417 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9418 }
9419 }
9420
9421 func TestUnmarshalDecodeStream(t *testing.T) {
9422 tests := []struct {
9423 in string
9424 want []any
9425 err error
9426 }{
9427 {in: ``, err: io.EOF},
9428 {in: `{`, err: &jsontext.SyntacticError{ByteOffset: len64(`{`), Err: io.ErrUnexpectedEOF}},
9429 {in: `{"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"`), Err: io.ErrUnexpectedEOF}},
9430 {in: `{"k"`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9431 {in: `{"k":`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k":`), JSONPointer: "/k", Err: io.ErrUnexpectedEOF}},
9432 {in: `{"k",`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError(",", "after object name (expecting ':')")}},
9433 {in: `{"k"}`, err: &jsontext.SyntacticError{ByteOffset: len64(`{"k"`), JSONPointer: "/k", Err: jsonwire.NewInvalidCharacterError("}", "after object name (expecting ':')")}},
9434 {in: `[`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), Err: io.ErrUnexpectedEOF}},
9435 {in: `[0`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: io.ErrUnexpectedEOF}},
9436 {in: ` [0`, err: &jsontext.SyntacticError{ByteOffset: len64(` [0`), Err: io.ErrUnexpectedEOF}},
9437 {in: `[0.`, err: &jsontext.SyntacticError{ByteOffset: len64(`[`), JSONPointer: "/0", Err: io.ErrUnexpectedEOF}},
9438 {in: `[0. `, err: &jsontext.SyntacticError{ByteOffset: len64(`[0.`), JSONPointer: "/0", Err: jsonwire.NewInvalidCharacterError(" ", "in number (expecting digit)")}},
9439 {in: `[0,`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0,`), Err: io.ErrUnexpectedEOF}},
9440 {in: `[0:`, err: &jsontext.SyntacticError{ByteOffset: len64(`[0`), Err: jsonwire.NewInvalidCharacterError(":", "after array element (expecting ',' or ']')")}},
9441 {in: `n`, err: &jsontext.SyntacticError{ByteOffset: len64(`n`), Err: io.ErrUnexpectedEOF}},
9442 {in: `nul`, err: &jsontext.SyntacticError{ByteOffset: len64(`nul`), Err: io.ErrUnexpectedEOF}},
9443 {in: `fal `, err: &jsontext.SyntacticError{ByteOffset: len64(`fal`), Err: jsonwire.NewInvalidCharacterError(" ", "in literal false (expecting 's')")}},
9444 {in: `false`, want: []any{false}, err: io.EOF},
9445 {in: `false0.0[]null`, want: []any{false, 0.0, []any{}, nil}, err: io.EOF},
9446 }
9447 for _, tt := range tests {
9448 d := jsontext.NewDecoder(strings.NewReader(tt.in))
9449 var got []any
9450 for {
9451 var v any
9452 if err := UnmarshalDecode(d, &v); err != nil {
9453 if !reflect.DeepEqual(err, tt.err) {
9454 t.Errorf("`%s`: UnmarshalDecode error = %v, want %v", tt.in, err, tt.err)
9455 }
9456 break
9457 }
9458 got = append(got, v)
9459 }
9460 if !reflect.DeepEqual(got, tt.want) {
9461 t.Errorf("`%s`: UnmarshalDecode = %v, want %v", tt.in, got, tt.want)
9462 }
9463 }
9464 }
9465
9466
9467
9468 func BenchmarkUnmarshalDecodeOptions(b *testing.B) {
9469 var i int
9470 in := new(bytes.Buffer)
9471 dec := jsontext.NewDecoder(in)
9472 makeBench := func(opts ...Options) func(*testing.B) {
9473 return func(b *testing.B) {
9474 for range b.N {
9475 in.WriteString("0 ")
9476 }
9477 dec.Reset(in)
9478 b.ResetTimer()
9479 for range b.N {
9480 UnmarshalDecode(dec, &i, opts...)
9481 }
9482 }
9483 }
9484 b.Run("None", makeBench())
9485 b.Run("Same", makeBench(&export.Decoder(dec).Struct))
9486 b.Run("New", makeBench(DefaultOptionsV2()))
9487 }
9488
9489 func TestMarshalEncodeOptions(t *testing.T) {
9490 var calledFuncs int
9491 var calledOptions Options
9492 out := new(bytes.Buffer)
9493 enc := jsontext.NewEncoder(
9494 out,
9495 jsontext.AllowInvalidUTF8(true),
9496 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9497 opts := enc.Options()
9498 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9499 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9500 }
9501 calledFuncs++
9502 calledOptions = opts
9503 return SkipFunc
9504 })),
9505 )
9506
9507 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9508 t.Fatalf("MarshalEncode: %v", err)
9509 }
9510 if calledFuncs != 1 {
9511 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9512 }
9513 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", calledOptions); err != nil {
9514 t.Fatalf("MarshalEncode: %v", err)
9515 }
9516 if calledFuncs != 2 {
9517 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9518 }
9519 if err := MarshalEncode(enc, "\xde\xad\xbe\xef",
9520 jsontext.AllowInvalidUTF8(false),
9521 WithMarshalers(nil),
9522 ); 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"); err != nil {
9529 t.Fatalf("MarshalEncode: %v", err)
9530 }
9531 if calledFuncs != 3 {
9532 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9533 }
9534 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", JoinOptions(
9535 jsontext.AllowInvalidUTF8(false),
9536 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9537 opts := enc.Options()
9538 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9539 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9540 }
9541 calledFuncs = math.MaxInt
9542 return SkipFunc
9543 })),
9544 )); err != nil {
9545 t.Fatalf("MarshalEncode: %v", err)
9546 }
9547 if calledFuncs != math.MaxInt {
9548 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9549 }
9550 if out.String() != strings.Repeat("\"\xde\xad\ufffd\ufffd\"\n", 5) {
9551 t.Fatalf("output mismatch:\n\tgot: %s\n\twant: %s", out.String(), strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9552 }
9553
9554
9555
9556 opts := enc.Options()
9557 enc.Reset(out, jsontext.AllowInvalidUTF8(false), opts)
9558 if v, _ := GetOption(enc.Options(), jsontext.AllowInvalidUTF8); v == false {
9559 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9560 }
9561 }
9562
9563
9564
9565 func BenchmarkMarshalEncodeOptions(b *testing.B) {
9566 var i int
9567 out := new(bytes.Buffer)
9568 enc := jsontext.NewEncoder(out)
9569 makeBench := func(opts ...Options) func(*testing.B) {
9570 return func(b *testing.B) {
9571 out.Reset()
9572 enc.Reset(out)
9573 b.ResetTimer()
9574 for range b.N {
9575 MarshalEncode(enc, &i, opts...)
9576 }
9577 }
9578 }
9579 b.Run("None", makeBench())
9580 b.Run("Same", makeBench(&export.Encoder(enc).Struct))
9581 b.Run("New", makeBench(DefaultOptionsV2()))
9582 }
9583
View as plain text