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.OmitEmptyWithLegacyDefinition | 1},
1928 in: structOmitEmptyAll{},
1929 want: `{}`,
1930 }, {
1931 name: jsontest.Name("Structs/OmitEmpty/Legacy/NonEmpty"),
1932 opts: []Options{jsontext.Multiline(true), jsonflags.OmitEmptyWithLegacyDefinition | 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.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/Maps/Nil"),
3221 in: struct{ X any }{map[string]any(nil)},
3222 want: `{"X":{}}`,
3223 }, {
3224 name: jsontest.Name("Interfaces/Any/Maps/Nil/FormatNilMapAsNull"),
3225 opts: []Options{FormatNilMapAsNull(true)},
3226 in: struct{ X any }{map[string]any(nil)},
3227 want: `{"X":null}`,
3228 }, {
3229 name: jsontest.Name("Interfaces/Any/Maps/Empty"),
3230 in: struct{ X any }{map[string]any{}},
3231 want: `{"X":{}}`,
3232 }, {
3233 name: jsontest.Name("Interfaces/Any/Maps/Empty/Multiline"),
3234 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3235 in: struct{ X any }{map[string]any{}},
3236 want: "{\n\"X\": {}\n}",
3237 }, {
3238 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
3239 in: struct{ X any }{map[string]any{"fizz": "buzz"}},
3240 want: `{"X":{"fizz":"buzz"}}`,
3241 }, {
3242 name: jsontest.Name("Interfaces/Any/Maps/Deterministic"),
3243 opts: []Options{Deterministic(true)},
3244 in: struct{ X any }{map[string]any{"alpha": "", "bravo": ""}},
3245 want: `{"X":{"alpha":"","bravo":""}}`,
3246 }, {
3247 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
3248 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
3249 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3250 want: `{"X":{"�":""`,
3251 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3252 }, {
3253 name: jsontest.Name("Interfaces/Any/Maps/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
3254 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3255 in: struct{ X any }{map[string]any{"\xff": "alpha", "\xfe": "bravo"}},
3256 want: `{"X":{"�":"bravo","�":"alpha"}}`,
3257 }, {
3258 name: jsontest.Name("Interfaces/Any/Maps/RejectInvalidUTF8"),
3259 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3260 want: `{"X":{`,
3261 wantErr: newInvalidUTF8Error(len64(`{"X":{`), "/X"),
3262 }, {
3263 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+RejectDuplicateNames"),
3264 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3265 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3266 want: `{"X":{"�":""`,
3267 wantErr: newDuplicateNameError("/X", []byte(`"�"`), len64(`{"X":{"�":"",`)),
3268 }, {
3269 name: jsontest.Name("Interfaces/Any/Maps/AllowInvalidUTF8+AllowDuplicateNames"),
3270 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
3271 in: struct{ X any }{map[string]any{"\xff": "", "\xfe": ""}},
3272 want: `{"X":{"�":"","�":""}}`,
3273 }, {
3274 name: jsontest.Name("Interfaces/Any/Maps/Cyclic"),
3275 in: func() any {
3276 m := map[string]any{}
3277 m[""] = m
3278 return struct{ X any }{m}
3279 }(),
3280 want: `{"X"` + strings.Repeat(`:{""`, startDetectingCyclesAfter),
3281 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`{"":`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/", startDetectingCyclesAfter))).withType(0, T[any]()),
3282 }, {
3283 name: jsontest.Name("Interfaces/Any/Slices/Nil"),
3284 in: struct{ X any }{[]any(nil)},
3285 want: `{"X":[]}`,
3286 }, {
3287 name: jsontest.Name("Interfaces/Any/Slices/Nil/FormatNilSliceAsNull"),
3288 opts: []Options{FormatNilSliceAsNull(true)},
3289 in: struct{ X any }{[]any(nil)},
3290 want: `{"X":null}`,
3291 }, {
3292 name: jsontest.Name("Interfaces/Any/Slices/Empty"),
3293 in: struct{ X any }{[]any{}},
3294 want: `{"X":[]}`,
3295 }, {
3296 name: jsontest.Name("Interfaces/Any/Slices/Empty/Multiline"),
3297 opts: []Options{jsontext.Multiline(true), jsontext.WithIndent("")},
3298 in: struct{ X any }{[]any{}},
3299 want: "{\n\"X\": []\n}",
3300 }, {
3301 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
3302 in: struct{ X any }{[]any{"fizz", "buzz"}},
3303 want: `{"X":["fizz","buzz"]}`,
3304 }, {
3305 name: jsontest.Name("Interfaces/Any/Slices/Cyclic"),
3306 in: func() any {
3307 s := make([]any, 1)
3308 s[0] = s
3309 return struct{ X any }{s}
3310 }(),
3311 want: `{"X":` + strings.Repeat(`[`, startDetectingCyclesAfter),
3312 wantErr: EM(internal.ErrCycle).withPos(`{"X":`+strings.Repeat(`[`, startDetectingCyclesAfter), "/X"+jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter))).withType(0, T[[]any]()),
3313 }, {
3314 name: jsontest.Name("Methods/NilPointer"),
3315 in: struct{ X *allMethods }{X: (*allMethods)(nil)},
3316 want: `{"X":null}`,
3317 }, {
3318
3319 name: jsontest.Name("Methods/NilInterface"),
3320 in: struct{ X MarshalerTo }{X: (*allMethods)(nil)},
3321 want: `{"X":null}`,
3322 }, {
3323 name: jsontest.Name("Methods/AllMethods"),
3324 in: struct{ X *allMethods }{X: &allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3325 want: `{"X":"hello"}`,
3326 }, {
3327 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
3328 in: struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3329 want: `{"X":"hello"}`,
3330 }, {
3331 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
3332 in: struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3333 want: `{"X":"hello"}`,
3334 }, {
3335 name: jsontest.Name("Methods/AllMethodsExceptText"),
3336 in: struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3337 want: `{"X":"hello"}`,
3338 }, {
3339 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
3340 in: struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3341 want: `{"X":"hello"}`,
3342 }, {
3343 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
3344 in: struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "MarshalJSON", value: []byte(`"hello"`)}}},
3345 want: `{"X":"hello"}`,
3346 }, {
3347 name: jsontest.Name("Methods/OnlyMethodText"),
3348 in: struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "MarshalText", value: []byte(`hello`)}}},
3349 want: `{"X":"hello"}`,
3350 }, {
3351 name: jsontest.Name("Methods/IP"),
3352 in: net.IPv4(192, 168, 0, 100),
3353 want: `"192.168.0.100"`,
3354 }, {
3355 name: jsontest.Name("Methods/NetIP"),
3356 in: struct {
3357 Addr netip.Addr
3358 AddrPort netip.AddrPort
3359 Prefix netip.Prefix
3360 }{
3361 Addr: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
3362 AddrPort: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 1234),
3363 Prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
3364 },
3365 want: `{"Addr":"1.2.3.4","AddrPort":"1.2.3.4:1234","Prefix":"1.2.3.4/24"}`,
3366 }, {
3367
3368 name: jsontest.Name("Methods/Anonymous"),
3369 in: struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)}}},
3370 want: `{"X":"hello"}`,
3371 }, {
3372
3373 name: jsontest.Name("Methods/Addressable"),
3374 in: struct {
3375 V allMethods
3376 M map[string]allMethods
3377 I any
3378 }{
3379 V: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3380 M: map[string]allMethods{"K": {method: "MarshalJSONTo", value: []byte(`"hello"`)}},
3381 I: allMethods{method: "MarshalJSONTo", value: []byte(`"hello"`)},
3382 },
3383 want: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
3384 }, {
3385
3386 name: jsontest.Name("Methods/MapKey/JSONv2"),
3387 in: map[structMethodJSONv2]string{{"k1"}: "v1", {"k2"}: "v2"},
3388 want: `{"k1":"v1","k2":"v2"}`,
3389 canonicalize: true,
3390 }, {
3391
3392 name: jsontest.Name("Methods/MapKey/JSONv1"),
3393 in: map[structMethodJSONv1]string{{"k1"}: "v1", {"k2"}: "v2"},
3394 want: `{"k1":"v1","k2":"v2"}`,
3395 canonicalize: true,
3396 }, {
3397 name: jsontest.Name("Methods/MapKey/Text"),
3398 in: map[structMethodText]string{{"k1"}: "v1", {"k2"}: "v2"},
3399 want: `{"k1":"v1","k2":"v2"}`,
3400 canonicalize: true,
3401 }, {
3402 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
3403 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3404 return errSomeError
3405 }),
3406 wantErr: EM(errSomeError).withType(0, T[marshalJSONv2Func]()),
3407 }, {
3408 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
3409 in: marshalJSONv2Func(func(*jsontext.Encoder) error {
3410 return nil
3411 }),
3412 wantErr: EM(errNonSingularValue).withType(0, T[marshalJSONv2Func]()),
3413 }, {
3414 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
3415 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3416 enc.WriteToken(jsontext.Null)
3417 enc.WriteToken(jsontext.Null)
3418 return nil
3419 }),
3420 want: `nullnull`,
3421 wantErr: EM(errNonSingularValue).withPos(`nullnull`, "").withType(0, T[marshalJSONv2Func]()),
3422 }, {
3423 name: jsontest.Name("Methods/Invalid/JSONv2/SkipFunc"),
3424 in: marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3425 return SkipFunc
3426 }),
3427 wantErr: EM(errors.New("marshal method cannot be skipped")).withType(0, T[marshalJSONv2Func]()),
3428 }, {
3429 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
3430 in: marshalJSONv1Func(func() ([]byte, error) {
3431 return nil, errSomeError
3432 }),
3433 wantErr: EM(errSomeError).withType(0, T[marshalJSONv1Func]()),
3434 }, {
3435 name: jsontest.Name("Methods/Invalid/JSONv1/Syntax"),
3436 in: marshalJSONv1Func(func() ([]byte, error) {
3437 return []byte("invalid"), nil
3438 }),
3439 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[marshalJSONv1Func]()),
3440 }, {
3441 name: jsontest.Name("Methods/Invalid/JSONv1/SkipFunc"),
3442 in: marshalJSONv1Func(func() ([]byte, error) {
3443 return nil, SkipFunc
3444 }),
3445 wantErr: EM(errors.New("marshal method cannot be skipped")).withType(0, T[marshalJSONv1Func]()),
3446 }, {
3447 name: jsontest.Name("Methods/AppendText"),
3448 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), nil }),
3449 want: `"hello"`,
3450 }, {
3451 name: jsontest.Name("Methods/AppendText/Error"),
3452 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "hello"...), errSomeError }),
3453 wantErr: EM(errSomeError).withType(0, T[appendTextFunc]()),
3454 }, {
3455 name: jsontest.Name("Methods/AppendText/NeedEscape"),
3456 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, `"`...), nil }),
3457 want: `"\""`,
3458 }, {
3459 name: jsontest.Name("Methods/AppendText/RejectInvalidUTF8"),
3460 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3461 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[appendTextFunc]()),
3462 }, {
3463 name: jsontest.Name("Methods/AppendText/AllowInvalidUTF8"),
3464 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3465 in: appendTextFunc(func(b []byte) ([]byte, error) { return append(b, "\xde\xad\xbe\xef"...), nil }),
3466 want: "\"\xde\xad\ufffd\ufffd\"",
3467 }, {
3468 name: jsontest.Name("Methods/Invalid/Text/Error"),
3469 in: marshalTextFunc(func() ([]byte, error) {
3470 return nil, errSomeError
3471 }),
3472 wantErr: EM(errSomeError).withType(0, T[marshalTextFunc]()),
3473 }, {
3474 name: jsontest.Name("Methods/Text/RejectInvalidUTF8"),
3475 in: marshalTextFunc(func() ([]byte, error) {
3476 return []byte("\xde\xad\xbe\xef"), nil
3477 }),
3478 wantErr: EM(newInvalidUTF8Error(0, "")).withType(0, T[marshalTextFunc]()),
3479 }, {
3480 name: jsontest.Name("Methods/Text/AllowInvalidUTF8"),
3481 opts: []Options{jsontext.AllowInvalidUTF8(true)},
3482 in: marshalTextFunc(func() ([]byte, error) {
3483 return []byte("\xde\xad\xbe\xef"), nil
3484 }),
3485 want: "\"\xde\xad\ufffd\ufffd\"",
3486 }, {
3487 name: jsontest.Name("Methods/Invalid/Text/SkipFunc"),
3488 in: marshalTextFunc(func() ([]byte, error) {
3489 return nil, SkipFunc
3490 }),
3491 wantErr: EM(wrapSkipFunc(SkipFunc, "marshal method")).withType(0, T[marshalTextFunc]()),
3492 }, {
3493 name: jsontest.Name("Methods/Invalid/MapKey/JSONv2/Syntax"),
3494 in: map[any]string{
3495 addr(marshalJSONv2Func(func(enc *jsontext.Encoder) error {
3496 return enc.WriteToken(jsontext.Null)
3497 })): "invalid",
3498 },
3499 want: `{`,
3500 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv2Func]()),
3501 }, {
3502 name: jsontest.Name("Methods/Invalid/MapKey/JSONv1/Syntax"),
3503 in: map[any]string{
3504 addr(marshalJSONv1Func(func() ([]byte, error) {
3505 return []byte(`null`), nil
3506 })): "invalid",
3507 },
3508 want: `{`,
3509 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[marshalJSONv1Func]()),
3510 }, {
3511 name: jsontest.Name("Functions/Bool/V1"),
3512 opts: []Options{
3513 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3514 return []byte(`"called"`), nil
3515 })),
3516 },
3517 in: true,
3518 want: `"called"`,
3519 }, {
3520 name: jsontest.Name("Functions/Bool/Empty"),
3521 opts: []Options{WithMarshalers(nil)},
3522 in: true,
3523 want: `true`,
3524 }, {
3525 name: jsontest.Name("Functions/NamedBool/V1/NoMatch"),
3526 opts: []Options{
3527 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3528 return nil, errMustNotCall
3529 })),
3530 },
3531 in: true,
3532 want: `true`,
3533 }, {
3534 name: jsontest.Name("Functions/NamedBool/V1/Match"),
3535 opts: []Options{
3536 WithMarshalers(MarshalFunc(func(namedBool) ([]byte, error) {
3537 return []byte(`"called"`), nil
3538 })),
3539 },
3540 in: namedBool(true),
3541 want: `"called"`,
3542 }, {
3543 name: jsontest.Name("Functions/PointerBool/V1/Match"),
3544 opts: []Options{
3545 WithMarshalers(MarshalFunc(func(v *bool) ([]byte, error) {
3546 _ = *v
3547 return []byte(`"called"`), nil
3548 })),
3549 },
3550 in: true,
3551 want: `"called"`,
3552 }, {
3553 name: jsontest.Name("Functions/Bool/V2"),
3554 opts: []Options{
3555 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3556 return enc.WriteToken(jsontext.String("called"))
3557 })),
3558 },
3559 in: true,
3560 want: `"called"`,
3561 }, {
3562 name: jsontest.Name("Functions/NamedBool/V2/NoMatch"),
3563 opts: []Options{
3564 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3565 return errMustNotCall
3566 })),
3567 },
3568 in: true,
3569 want: `true`,
3570 }, {
3571 name: jsontest.Name("Functions/NamedBool/V2/Match"),
3572 opts: []Options{
3573 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v namedBool) error {
3574 return enc.WriteToken(jsontext.String("called"))
3575 })),
3576 },
3577 in: namedBool(true),
3578 want: `"called"`,
3579 }, {
3580 name: jsontest.Name("Functions/PointerBool/V2/Match"),
3581 opts: []Options{
3582 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3583 _ = *v
3584 return enc.WriteToken(jsontext.String("called"))
3585 })),
3586 },
3587 in: true,
3588 want: `"called"`,
3589 }, {
3590 name: jsontest.Name("Functions/Bool/Empty1/NoMatch"),
3591 opts: []Options{
3592 WithMarshalers(new(Marshalers)),
3593 },
3594 in: true,
3595 want: `true`,
3596 }, {
3597 name: jsontest.Name("Functions/Bool/Empty2/NoMatch"),
3598 opts: []Options{
3599 WithMarshalers(JoinMarshalers()),
3600 },
3601 in: true,
3602 want: `true`,
3603 }, {
3604 name: jsontest.Name("Functions/Bool/V1/DirectError"),
3605 opts: []Options{
3606 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3607 return nil, errSomeError
3608 })),
3609 },
3610 in: true,
3611 wantErr: EM(errSomeError).withType(0, T[bool]()),
3612 }, {
3613 name: jsontest.Name("Functions/Bool/V1/SkipError"),
3614 opts: []Options{
3615 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3616 return nil, SkipFunc
3617 })),
3618 },
3619 in: true,
3620 wantErr: EM(wrapSkipFunc(SkipFunc, "marshal function of type func(T) ([]byte, error)")).withType(0, T[bool]()),
3621 }, {
3622 name: jsontest.Name("Functions/Bool/V1/InvalidValue"),
3623 opts: []Options{
3624 WithMarshalers(MarshalFunc(func(bool) ([]byte, error) {
3625 return []byte("invalid"), nil
3626 })),
3627 },
3628 in: true,
3629 wantErr: EM(newInvalidCharacterError("i", "at start of value", 0, "")).withType(0, T[bool]()),
3630 }, {
3631 name: jsontest.Name("Functions/Bool/V2/DirectError"),
3632 opts: []Options{
3633 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3634 return errSomeError
3635 })),
3636 },
3637 in: true,
3638 wantErr: EM(errSomeError).withType(0, T[bool]()),
3639 }, {
3640 name: jsontest.Name("Functions/Bool/V2/TooFew"),
3641 opts: []Options{
3642 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3643 return nil
3644 })),
3645 },
3646 in: true,
3647 wantErr: EM(errNonSingularValue).withType(0, T[bool]()),
3648 }, {
3649 name: jsontest.Name("Functions/Bool/V2/TooMany"),
3650 opts: []Options{
3651 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3652 enc.WriteValue([]byte(`"hello"`))
3653 enc.WriteValue([]byte(`"world"`))
3654 return nil
3655 })),
3656 },
3657 in: true,
3658 want: `"hello""world"`,
3659 wantErr: EM(errNonSingularValue).withPos(`"hello""world"`, "").withType(0, T[bool]()),
3660 }, {
3661 name: jsontest.Name("Functions/Bool/V2/Skipped"),
3662 opts: []Options{
3663 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3664 return SkipFunc
3665 })),
3666 },
3667 in: true,
3668 want: `true`,
3669 }, {
3670 name: jsontest.Name("Functions/Bool/V2/ProcessBeforeSkip"),
3671 opts: []Options{
3672 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3673 enc.WriteValue([]byte(`"hello"`))
3674 return SkipFunc
3675 })),
3676 },
3677 in: true,
3678 want: `"hello"`,
3679 wantErr: EM(errSkipMutation).withPos(`"hello"`, "").withType(0, T[bool]()),
3680 }, {
3681 name: jsontest.Name("Functions/Bool/V2/WrappedSkipError"),
3682 opts: []Options{
3683 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
3684 return fmt.Errorf("wrap: %w", SkipFunc)
3685 })),
3686 },
3687 in: true,
3688 wantErr: EM(fmt.Errorf("wrap: %w", SkipFunc)).withType(0, T[bool]()),
3689 }, {
3690 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
3691 opts: []Options{
3692 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3693 return []byte(`"called"`), nil
3694 })),
3695 },
3696 in: map[nocaseString]string{"hello": "world"},
3697 want: `{"called":"world"}`,
3698 }, {
3699 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V1"),
3700 opts: []Options{
3701 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3702 _ = *v
3703 return []byte(`"called"`), nil
3704 })),
3705 },
3706 in: map[nocaseString]string{"hello": "world"},
3707 want: `{"called":"world"}`,
3708 }, {
3709 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
3710 opts: []Options{
3711 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3712 _ = *v.(*nocaseString)
3713 return []byte(`"called"`), nil
3714 })),
3715 },
3716 in: map[nocaseString]string{"hello": "world"},
3717 want: `{"called":"world"}`,
3718 }, {
3719 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1/InvalidValue"),
3720 opts: []Options{
3721 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3722 return []byte(`null`), nil
3723 })),
3724 },
3725 in: map[nocaseString]string{"hello": "world"},
3726 want: `{`,
3727 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3728 }, {
3729 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidKind"),
3730 opts: []Options{
3731 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3732 return []byte(`null`), nil
3733 })),
3734 },
3735 in: map[nocaseString]string{"hello": "world"},
3736 want: `{`,
3737 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3738 }, {
3739 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
3740 opts: []Options{
3741 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3742 return []byte(`"name"`), nil
3743 })),
3744 },
3745 in: map[string]string{"name1": "value", "name2": "value"},
3746 want: `{"name":"name"`,
3747 wantErr: EM(newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"name",`))).
3748 withPos(`{"name":"name",`, "").withType(0, T[string]()),
3749 }, {
3750 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
3751 opts: []Options{
3752 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3753 return enc.WriteValue([]byte(`"called"`))
3754 })),
3755 },
3756 in: map[nocaseString]string{"hello": "world"},
3757 want: `{"called":"world"}`,
3758 }, {
3759 name: jsontest.Name("Functions/Map/Key/PointerNoCaseString/V2"),
3760 opts: []Options{
3761 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3762 _ = *v
3763 return enc.WriteValue([]byte(`"called"`))
3764 })),
3765 },
3766 in: map[nocaseString]string{"hello": "world"},
3767 want: `{"called":"world"}`,
3768 }, {
3769 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
3770 opts: []Options{
3771 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3772 _ = *v.(*nocaseString)
3773 return enc.WriteValue([]byte(`"called"`))
3774 })),
3775 },
3776 in: map[nocaseString]string{"hello": "world"},
3777 want: `{"called":"world"}`,
3778 }, {
3779 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidToken"),
3780 opts: []Options{
3781 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3782 return enc.WriteToken(jsontext.Null)
3783 })),
3784 },
3785 in: map[nocaseString]string{"hello": "world"},
3786 want: `{`,
3787 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3788 }, {
3789 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidValue"),
3790 opts: []Options{
3791 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3792 return enc.WriteValue([]byte(`null`))
3793 })),
3794 },
3795 in: map[nocaseString]string{"hello": "world"},
3796 want: `{`,
3797 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[nocaseString]()),
3798 }, {
3799 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
3800 opts: []Options{
3801 WithMarshalers(MarshalFunc(func(v nocaseString) ([]byte, error) {
3802 return []byte(`"called"`), nil
3803 })),
3804 },
3805 in: map[string]nocaseString{"hello": "world"},
3806 want: `{"hello":"called"}`,
3807 }, {
3808 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V1"),
3809 opts: []Options{
3810 WithMarshalers(MarshalFunc(func(v *nocaseString) ([]byte, error) {
3811 _ = *v
3812 return []byte(`"called"`), nil
3813 })),
3814 },
3815 in: map[string]nocaseString{"hello": "world"},
3816 want: `{"hello":"called"}`,
3817 }, {
3818 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
3819 opts: []Options{
3820 WithMarshalers(MarshalFunc(func(v encoding.TextMarshaler) ([]byte, error) {
3821 _ = *v.(*nocaseString)
3822 return []byte(`"called"`), nil
3823 })),
3824 },
3825 in: map[string]nocaseString{"hello": "world"},
3826 want: `{"hello":"called"}`,
3827 }, {
3828 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
3829 opts: []Options{
3830 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v nocaseString) error {
3831 return enc.WriteValue([]byte(`"called"`))
3832 })),
3833 },
3834 in: map[string]nocaseString{"hello": "world"},
3835 want: `{"hello":"called"}`,
3836 }, {
3837 name: jsontest.Name("Functions/Map/Value/PointerNoCaseString/V2"),
3838 opts: []Options{
3839 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *nocaseString) error {
3840 _ = *v
3841 return enc.WriteValue([]byte(`"called"`))
3842 })),
3843 },
3844 in: map[string]nocaseString{"hello": "world"},
3845 want: `{"hello":"called"}`,
3846 }, {
3847 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
3848 opts: []Options{
3849 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v encoding.TextMarshaler) error {
3850 _ = *v.(*nocaseString)
3851 return enc.WriteValue([]byte(`"called"`))
3852 })),
3853 },
3854 in: map[string]nocaseString{"hello": "world"},
3855 want: `{"hello":"called"}`,
3856 }, {
3857 name: jsontest.Name("Funtions/Struct/Fields"),
3858 opts: []Options{
3859 WithMarshalers(JoinMarshalers(
3860 MarshalFunc(func(v bool) ([]byte, error) {
3861 return []byte(`"called1"`), nil
3862 }),
3863 MarshalFunc(func(v *string) ([]byte, error) {
3864 return []byte(`"called2"`), nil
3865 }),
3866 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3867 return enc.WriteValue([]byte(`"called3"`))
3868 }),
3869 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3870 return enc.WriteValue([]byte(`"called4"`))
3871 }),
3872 )),
3873 },
3874 in: structScalars{},
3875 want: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":0,"Float":0}`,
3876 }, {
3877 name: jsontest.Name("Functions/Struct/OmitEmpty"),
3878 opts: []Options{
3879 WithMarshalers(JoinMarshalers(
3880 MarshalFunc(func(v bool) ([]byte, error) {
3881 return []byte(`null`), nil
3882 }),
3883 MarshalFunc(func(v string) ([]byte, error) {
3884 return []byte(`"called1"`), nil
3885 }),
3886 MarshalFunc(func(v *stringMarshalNonEmpty) ([]byte, error) {
3887 return []byte(`""`), nil
3888 }),
3889 MarshalToFunc(func(enc *jsontext.Encoder, v bytesMarshalNonEmpty) error {
3890 return enc.WriteValue([]byte(`{}`))
3891 }),
3892 MarshalToFunc(func(enc *jsontext.Encoder, v *float64) error {
3893 return enc.WriteValue([]byte(`[]`))
3894 }),
3895 MarshalFunc(func(v mapMarshalNonEmpty) ([]byte, error) {
3896 return []byte(`"called2"`), nil
3897 }),
3898 MarshalFunc(func(v []string) ([]byte, error) {
3899 return []byte(`"called3"`), nil
3900 }),
3901 MarshalToFunc(func(enc *jsontext.Encoder, v *sliceMarshalNonEmpty) error {
3902 return enc.WriteValue([]byte(`"called4"`))
3903 }),
3904 )),
3905 },
3906 in: structOmitEmptyAll{},
3907 want: `{"String":"called1","MapNonEmpty":"called2","Slice":"called3","SliceNonEmpty":"called4"}`,
3908 }, {
3909 name: jsontest.Name("Functions/Struct/OmitZero"),
3910 opts: []Options{
3911 WithMarshalers(JoinMarshalers(
3912 MarshalFunc(func(v bool) ([]byte, error) {
3913 panic("should not be called")
3914 }),
3915 MarshalFunc(func(v *string) ([]byte, error) {
3916 panic("should not be called")
3917 }),
3918 MarshalToFunc(func(enc *jsontext.Encoder, v []byte) error {
3919 panic("should not be called")
3920 }),
3921 MarshalToFunc(func(enc *jsontext.Encoder, v *int64) error {
3922 panic("should not be called")
3923 }),
3924 )),
3925 },
3926 in: structOmitZeroAll{},
3927 want: `{}`,
3928 }, {
3929 name: jsontest.Name("Functions/Struct/Inlined"),
3930 opts: []Options{
3931 WithMarshalers(JoinMarshalers(
3932 MarshalFunc(func(v structInlinedL1) ([]byte, error) {
3933 panic("should not be called")
3934 }),
3935 MarshalToFunc(func(enc *jsontext.Encoder, v *StructEmbed2) error {
3936 panic("should not be called")
3937 }),
3938 )),
3939 },
3940 in: structInlined{},
3941 want: `{"D":""}`,
3942 }, {
3943 name: jsontest.Name("Functions/Slice/Elem"),
3944 opts: []Options{
3945 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3946 return []byte(`"` + strconv.FormatBool(v) + `"`), nil
3947 })),
3948 },
3949 in: []bool{true, false},
3950 want: `["true","false"]`,
3951 }, {
3952 name: jsontest.Name("Functions/Array/Elem"),
3953 opts: []Options{
3954 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3955 return enc.WriteValue([]byte(`"` + strconv.FormatBool(*v) + `"`))
3956 })),
3957 },
3958 in: [2]bool{true, false},
3959 want: `["true","false"]`,
3960 }, {
3961 name: jsontest.Name("Functions/Pointer/Nil"),
3962 opts: []Options{
3963 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3964 panic("should not be called")
3965 })),
3966 },
3967 in: struct{ X *bool }{nil},
3968 want: `{"X":null}`,
3969 }, {
3970 name: jsontest.Name("Functions/Pointer/NonNil"),
3971 opts: []Options{
3972 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *bool) error {
3973 return enc.WriteValue([]byte(`"called"`))
3974 })),
3975 },
3976 in: struct{ X *bool }{addr(false)},
3977 want: `{"X":"called"}`,
3978 }, {
3979 name: jsontest.Name("Functions/Interface/Nil"),
3980 opts: []Options{
3981 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
3982 panic("should not be called")
3983 })),
3984 },
3985 in: struct{ X fmt.Stringer }{nil},
3986 want: `{"X":null}`,
3987 }, {
3988 name: jsontest.Name("Functions/Interface/NonNil/MatchInterface"),
3989 opts: []Options{
3990 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v fmt.Stringer) error {
3991 return enc.WriteValue([]byte(`"called"`))
3992 })),
3993 },
3994 in: struct{ X fmt.Stringer }{valueStringer{}},
3995 want: `{"X":"called"}`,
3996 }, {
3997 name: jsontest.Name("Functions/Interface/NonNil/MatchConcrete"),
3998 opts: []Options{
3999 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4000 return enc.WriteValue([]byte(`"called"`))
4001 })),
4002 },
4003 in: struct{ X fmt.Stringer }{valueStringer{}},
4004 want: `{"X":"called"}`,
4005 }, {
4006 name: jsontest.Name("Functions/Interface/NonNil/MatchPointer"),
4007 opts: []Options{
4008 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4009 return enc.WriteValue([]byte(`"called"`))
4010 })),
4011 },
4012 in: struct{ X fmt.Stringer }{valueStringer{}},
4013 want: `{"X":"called"}`,
4014 }, {
4015 name: jsontest.Name("Functions/Interface/Any"),
4016 in: []any{
4017 nil,
4018 valueStringer{},
4019 (*valueStringer)(nil),
4020 addr(valueStringer{}),
4021 (**valueStringer)(nil),
4022 addr((*valueStringer)(nil)),
4023 addr(addr(valueStringer{})),
4024 pointerStringer{},
4025 (*pointerStringer)(nil),
4026 addr(pointerStringer{}),
4027 (**pointerStringer)(nil),
4028 addr((*pointerStringer)(nil)),
4029 addr(addr(pointerStringer{})),
4030 "LAST",
4031 },
4032 want: `[null,{},null,{},null,null,{},{},null,{},null,null,{},"LAST"]`,
4033 opts: []Options{
4034 WithMarshalers(func() *Marshalers {
4035 type P struct {
4036 D int
4037 N int64
4038 }
4039 type PV struct {
4040 P P
4041 V any
4042 }
4043
4044 var lastChecks []func() error
4045 checkLast := func() error {
4046 for _, fn := range lastChecks {
4047 if err := fn(); err != nil {
4048 return err
4049 }
4050 }
4051 return SkipFunc
4052 }
4053 makeValueChecker := func(name string, want []PV) func(e *jsontext.Encoder, v any) error {
4054 checkNext := func(e *jsontext.Encoder, v any) error {
4055 xe := export.Encoder(e)
4056 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4057 rv := reflect.ValueOf(v)
4058 pv := PV{p, v}
4059 switch {
4060 case len(want) == 0:
4061 return fmt.Errorf("%s: %v: got more values than expected", name, p)
4062 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
4063 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
4064 case !reflect.DeepEqual(pv, want[0]):
4065 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
4066 default:
4067 want = want[1:]
4068 return SkipFunc
4069 }
4070 }
4071 lastChecks = append(lastChecks, func() error {
4072 if len(want) > 0 {
4073 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4074 }
4075 return nil
4076 })
4077 return checkNext
4078 }
4079 makePositionChecker := func(name string, want []P) func(e *jsontext.Encoder, v any) error {
4080 checkNext := func(e *jsontext.Encoder, v any) error {
4081 xe := export.Encoder(e)
4082 p := P{len(xe.Tokens.Stack), xe.Tokens.Last.Length()}
4083 switch {
4084 case len(want) == 0:
4085 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
4086 case p != want[0]:
4087 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
4088 default:
4089 want = want[1:]
4090 return SkipFunc
4091 }
4092 }
4093 lastChecks = append(lastChecks, func() error {
4094 if len(want) > 0 {
4095 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
4096 }
4097 return nil
4098 })
4099 return checkNext
4100 }
4101
4102 wantAny := []PV{
4103 {P{0, 0}, addr([]any{
4104 nil,
4105 valueStringer{},
4106 (*valueStringer)(nil),
4107 addr(valueStringer{}),
4108 (**valueStringer)(nil),
4109 addr((*valueStringer)(nil)),
4110 addr(addr(valueStringer{})),
4111 pointerStringer{},
4112 (*pointerStringer)(nil),
4113 addr(pointerStringer{}),
4114 (**pointerStringer)(nil),
4115 addr((*pointerStringer)(nil)),
4116 addr(addr(pointerStringer{})),
4117 "LAST",
4118 })},
4119 {P{1, 0}, addr(any(nil))},
4120 {P{1, 1}, addr(any(valueStringer{}))},
4121 {P{1, 1}, addr(valueStringer{})},
4122 {P{1, 2}, addr(any((*valueStringer)(nil)))},
4123 {P{1, 2}, addr((*valueStringer)(nil))},
4124 {P{1, 3}, addr(any(addr(valueStringer{})))},
4125 {P{1, 3}, addr(addr(valueStringer{}))},
4126 {P{1, 3}, addr(valueStringer{})},
4127 {P{1, 4}, addr(any((**valueStringer)(nil)))},
4128 {P{1, 4}, addr((**valueStringer)(nil))},
4129 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
4130 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
4131 {P{1, 5}, addr((*valueStringer)(nil))},
4132 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
4133 {P{1, 6}, addr(addr(addr(valueStringer{})))},
4134 {P{1, 6}, addr(addr(valueStringer{}))},
4135 {P{1, 6}, addr(valueStringer{})},
4136 {P{1, 7}, addr(any(pointerStringer{}))},
4137 {P{1, 7}, addr(pointerStringer{})},
4138 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
4139 {P{1, 8}, addr((*pointerStringer)(nil))},
4140 {P{1, 9}, addr(any(addr(pointerStringer{})))},
4141 {P{1, 9}, addr(addr(pointerStringer{}))},
4142 {P{1, 9}, addr(pointerStringer{})},
4143 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
4144 {P{1, 10}, addr((**pointerStringer)(nil))},
4145 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
4146 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
4147 {P{1, 11}, addr((*pointerStringer)(nil))},
4148 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
4149 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
4150 {P{1, 12}, addr(addr(pointerStringer{}))},
4151 {P{1, 12}, addr(pointerStringer{})},
4152 {P{1, 13}, addr(any("LAST"))},
4153 {P{1, 13}, addr("LAST")},
4154 }
4155 checkAny := makeValueChecker("any", wantAny)
4156 anyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v any) error {
4157 return checkAny(enc, v)
4158 })
4159
4160 var wantPointerAny []PV
4161 for _, v := range wantAny {
4162 if _, ok := v.V.(*any); ok {
4163 wantPointerAny = append(wantPointerAny, v)
4164 }
4165 }
4166 checkPointerAny := makeValueChecker("*any", wantPointerAny)
4167 pointerAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *any) error {
4168 return checkPointerAny(enc, v)
4169 })
4170
4171 checkNamedAny := makeValueChecker("namedAny", wantAny)
4172 namedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v namedAny) error {
4173 return checkNamedAny(enc, v)
4174 })
4175
4176 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
4177 pointerNamedAnyMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *namedAny) error {
4178 return checkPointerNamedAny(enc, v)
4179 })
4180
4181 type stringer = fmt.Stringer
4182 var wantStringer []PV
4183 for _, v := range wantAny {
4184 if _, ok := v.V.(stringer); ok {
4185 wantStringer = append(wantStringer, v)
4186 }
4187 }
4188 checkStringer := makeValueChecker("stringer", wantStringer)
4189 stringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v stringer) error {
4190 return checkStringer(enc, v)
4191 })
4192
4193 checkPointerStringer := makeValueChecker("*stringer", nil)
4194 pointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *stringer) error {
4195 return checkPointerStringer(enc, v)
4196 })
4197
4198 wantValueStringer := []P{{1, 1}, {1, 3}, {1, 6}}
4199 checkValueValueStringer := makePositionChecker("valueStringer", wantValueStringer)
4200 valueValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v valueStringer) error {
4201 return checkValueValueStringer(enc, v)
4202 })
4203
4204 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
4205 pointerValueStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *valueStringer) error {
4206 return checkPointerValueStringer(enc, v)
4207 })
4208
4209 wantPointerStringer := []P{{1, 7}, {1, 9}, {1, 12}}
4210 checkValuePointerStringer := makePositionChecker("pointerStringer", wantPointerStringer)
4211 valuePointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v pointerStringer) error {
4212 return checkValuePointerStringer(enc, v)
4213 })
4214
4215 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
4216 pointerPointerStringerMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v *pointerStringer) error {
4217 return checkPointerPointerStringer(enc, v)
4218 })
4219
4220 lastMarshaler := MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
4221 return checkLast()
4222 })
4223
4224 return JoinMarshalers(
4225 anyMarshaler,
4226 pointerAnyMarshaler,
4227 namedAnyMarshaler,
4228 pointerNamedAnyMarshaler,
4229 stringerMarshaler,
4230 pointerStringerMarshaler,
4231 valueValueStringerMarshaler,
4232 pointerValueStringerMarshaler,
4233 valuePointerStringerMarshaler,
4234 pointerPointerStringerMarshaler,
4235 lastMarshaler,
4236 )
4237 }()),
4238 },
4239 }, {
4240 name: jsontest.Name("Functions/Precedence/V1First"),
4241 opts: []Options{
4242 WithMarshalers(JoinMarshalers(
4243 MarshalFunc(func(bool) ([]byte, error) {
4244 return []byte(`"called"`), nil
4245 }),
4246 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4247 panic("should not be called")
4248 }),
4249 )),
4250 },
4251 in: true,
4252 want: `"called"`,
4253 }, {
4254 name: jsontest.Name("Functions/Precedence/V2First"),
4255 opts: []Options{
4256 WithMarshalers(JoinMarshalers(
4257 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4258 return enc.WriteToken(jsontext.String("called"))
4259 }),
4260 MarshalFunc(func(bool) ([]byte, error) {
4261 panic("should not be called")
4262 }),
4263 )),
4264 },
4265 in: true,
4266 want: `"called"`,
4267 }, {
4268 name: jsontest.Name("Functions/Precedence/V2Skipped"),
4269 opts: []Options{
4270 WithMarshalers(JoinMarshalers(
4271 MarshalToFunc(func(enc *jsontext.Encoder, v bool) error {
4272 return SkipFunc
4273 }),
4274 MarshalFunc(func(bool) ([]byte, error) {
4275 return []byte(`"called"`), nil
4276 }),
4277 )),
4278 },
4279 in: true,
4280 want: `"called"`,
4281 }, {
4282 name: jsontest.Name("Functions/Precedence/NestedFirst"),
4283 opts: []Options{
4284 WithMarshalers(JoinMarshalers(
4285 JoinMarshalers(
4286 MarshalFunc(func(bool) ([]byte, error) {
4287 return []byte(`"called"`), nil
4288 }),
4289 ),
4290 MarshalFunc(func(bool) ([]byte, error) {
4291 panic("should not be called")
4292 }),
4293 )),
4294 },
4295 in: true,
4296 want: `"called"`,
4297 }, {
4298 name: jsontest.Name("Functions/Precedence/NestedLast"),
4299 opts: []Options{
4300 WithMarshalers(JoinMarshalers(
4301 MarshalFunc(func(bool) ([]byte, error) {
4302 return []byte(`"called"`), nil
4303 }),
4304 JoinMarshalers(
4305 MarshalFunc(func(bool) ([]byte, error) {
4306 panic("should not be called")
4307 }),
4308 ),
4309 )),
4310 },
4311 in: true,
4312 want: `"called"`,
4313 }, {
4314 name: jsontest.Name("Duration/Zero"),
4315 in: struct {
4316 D1 time.Duration `json:",format:units"`
4317 D2 time.Duration `json:",format:nano"`
4318 }{0, 0},
4319 want: `{"D1":"0s","D2":0}`,
4320 }, {
4321 name: jsontest.Name("Duration/Positive"),
4322 in: struct {
4323 D1 time.Duration `json:",format:units"`
4324 D2 time.Duration `json:",format:nano"`
4325 }{
4326 123456789123456789,
4327 123456789123456789,
4328 },
4329 want: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
4330 }, {
4331 name: jsontest.Name("Duration/Negative"),
4332 in: struct {
4333 D1 time.Duration `json:",format:units"`
4334 D2 time.Duration `json:",format:nano"`
4335 }{
4336 -123456789123456789,
4337 -123456789123456789,
4338 },
4339 want: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
4340 }, {
4341 name: jsontest.Name("Duration/Nanos/String"),
4342 in: struct {
4343 D1 time.Duration `json:",string,format:nano"`
4344 D2 time.Duration `json:",string,format:nano"`
4345 D3 time.Duration `json:",string,format:nano"`
4346 }{
4347 math.MinInt64,
4348 0,
4349 math.MaxInt64,
4350 },
4351 want: `{"D1":"-9223372036854775808","D2":"0","D3":"9223372036854775807"}`,
4352 }, {
4353 name: jsontest.Name("Duration/Format/Invalid"),
4354 in: struct {
4355 D time.Duration `json:",format:invalid"`
4356 }{},
4357 want: `{"D"`,
4358 wantErr: EM(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, T[time.Duration]()),
4359 }, {
4360
4366 name: jsontest.Name("Duration/Format"),
4367 opts: []Options{jsontext.Multiline(true)},
4368 in: structDurationFormat{
4369 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4370 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4371 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4372 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
4373 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
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 },
4381 want: `{
4382 "D1": "12h34m56.078090012s",
4383 "D2": "12h34m56.078090012s",
4384 "D3": 45296.078090012,
4385 "D4": "45296.078090012",
4386 "D5": 45296078.090012,
4387 "D6": "45296078.090012",
4388 "D7": 45296078090.012,
4389 "D8": "45296078090.012",
4390 "D9": 45296078090012,
4391 "D10": "45296078090012",
4392 "D11": "PT12H34M56.078090012S"
4393 }`,
4394 }, {
4395
4404
4409 name: jsontest.Name("Duration/MapKey/Legacy"),
4410 opts: []Options{jsonflags.FormatTimeWithLegacySemantics | 1},
4411 in: map[time.Duration]string{time.Second: ""},
4412 want: `{"1000000000":""}`,
4413 }, {
4414 name: jsontest.Name("Time/Zero"),
4415 in: struct {
4416 T1 time.Time
4417 T2 time.Time `json:",format:RFC822"`
4418 T3 time.Time `json:",format:'2006-01-02'"`
4419 T4 time.Time `json:",omitzero"`
4420 T5 time.Time `json:",omitempty"`
4421 }{
4422 time.Time{},
4423 time.Time{},
4424 time.Time{},
4425
4426
4427 time.Date(1, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC", 0)),
4428 time.Time{},
4429 },
4430 want: `{"T1":"0001-01-01T00:00:00Z","T2":"01 Jan 01 00:00 UTC","T3":"0001-01-01","T5":"0001-01-01T00:00:00Z"}`,
4431 }, {
4432 name: jsontest.Name("Time/Format"),
4433 opts: []Options{jsontext.Multiline(true)},
4434 in: structTimeFormat{
4435 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4436 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4437 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4438 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4439 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4440 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4441 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4442 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4443 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4444 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4445 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4446 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4447 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4448 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4449 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4450 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4451 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4452 time.Date(1234, 1, 2, 3, 4, 5, 6, time.UTC),
4453 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 },
4465 want: `{
4466 "T1": "1234-01-02T03:04:05.000000006Z",
4467 "T2": "Mon Jan 2 03:04:05 1234",
4468 "T3": "Mon Jan 2 03:04:05 UTC 1234",
4469 "T4": "Mon Jan 02 03:04:05 +0000 1234",
4470 "T5": "02 Jan 34 03:04 UTC",
4471 "T6": "02 Jan 34 03:04 +0000",
4472 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
4473 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
4474 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
4475 "T10": "1234-01-02T03:04:05Z",
4476 "T11": "1234-01-02T03:04:05.000000006Z",
4477 "T12": "3:04AM",
4478 "T13": "Jan 2 03:04:05",
4479 "T14": "Jan 2 03:04:05.000",
4480 "T15": "Jan 2 03:04:05.000000",
4481 "T16": "Jan 2 03:04:05.000000006",
4482 "T17": "1234-01-02 03:04:05",
4483 "T18": "1234-01-02",
4484 "T19": "03:04:05",
4485 "T20": "1234-01-02",
4486 "T21": "\"weird\"1234",
4487 "T22": -23225777754.999999994,
4488 "T23": "-23225777754.999999994",
4489 "T24": -23225777754999.999994,
4490 "T25": "-23225777754999.999994",
4491 "T26": -23225777754999999.994,
4492 "T27": "-23225777754999999.994",
4493 "T28": -23225777754999999994,
4494 "T29": "-23225777754999999994"
4495 }`,
4496 }, {
4497 name: jsontest.Name("Time/Format/Invalid"),
4498 in: struct {
4499 T time.Time `json:",format:UndefinedConstant"`
4500 }{},
4501 want: `{"T"`,
4502 wantErr: EM(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4503 }, {
4504 name: jsontest.Name("Time/Format/YearOverflow"),
4505 in: struct {
4506 T1 time.Time
4507 T2 time.Time
4508 }{
4509 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4510 time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC),
4511 },
4512 want: `{"T1":"9999-12-31T23:59:59Z","T2"`,
4513 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"9999-12-31T23:59:59Z","T2":`, "/T2").withType(0, timeTimeType),
4514 }, {
4515 name: jsontest.Name("Time/Format/YearUnderflow"),
4516 in: struct {
4517 T1 time.Time
4518 T2 time.Time
4519 }{
4520 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
4521 time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
4522 },
4523 want: `{"T1":"0000-01-01T00:00:00Z","T2"`,
4524 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T1":"0000-01-01T00:00:00Z","T2":`, "/T2").withType(0, timeTimeType),
4525 }, {
4526 name: jsontest.Name("Time/Format/YearUnderflow"),
4527 in: struct{ T time.Time }{time.Date(-998, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second)},
4528 want: `{"T"`,
4529 wantErr: EM(errors.New(`year outside of range [0,9999]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
4530 }, {
4531 name: jsontest.Name("Time/Format/ZoneExact"),
4532 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 23*60*60+59*60))},
4533 want: `{"T":"2020-01-01T00:00:00+23:59"}`,
4534 }, {
4535 name: jsontest.Name("Time/Format/ZoneHourOverflow"),
4536 in: struct{ T time.Time }{time.Date(2020, 1, 1, 0, 0, 0, 0, time.FixedZone("", 24*60*60))},
4537 want: `{"T"`,
4538 wantErr: EM(errors.New(`timezone hour outside of range [0,23]`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
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("", 123*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/IgnoreInvalidFormat"),
4546 opts: []Options{invalidFormatOption},
4547 in: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
4548 want: `"2000-01-01T00:00:00Z"`,
4549 }}
4550
4551 for _, tt := range tests {
4552 t.Run(tt.name.Name, func(t *testing.T) {
4553 var got []byte
4554 var gotErr error
4555 if tt.useWriter {
4556 bb := new(struct{ bytes.Buffer })
4557 gotErr = MarshalWrite(bb, tt.in, tt.opts...)
4558 got = bb.Bytes()
4559 } else {
4560 got, gotErr = Marshal(tt.in, tt.opts...)
4561 }
4562 if tt.canonicalize {
4563 (*jsontext.Value)(&got).Canonicalize()
4564 }
4565 if string(got) != tt.want {
4566 t.Errorf("%s: Marshal output mismatch:\ngot %s\nwant %s", tt.name.Where, got, tt.want)
4567 }
4568 if !reflect.DeepEqual(gotErr, tt.wantErr) {
4569 t.Errorf("%s: Marshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
4570 }
4571 })
4572 }
4573 }
4574
4575 func TestUnmarshal(t *testing.T) {
4576 tests := []struct {
4577 name jsontest.CaseName
4578 opts []Options
4579 inBuf string
4580 inVal any
4581 want any
4582 wantErr error
4583 }{{
4584 name: jsontest.Name("Nil"),
4585 inBuf: `null`,
4586 wantErr: EU(internal.ErrNonNilReference),
4587 }, {
4588 name: jsontest.Name("NilPointer"),
4589 inBuf: `null`,
4590 inVal: (*string)(nil),
4591 want: (*string)(nil),
4592 wantErr: EU(internal.ErrNonNilReference).withType(0, T[*string]()),
4593 }, {
4594 name: jsontest.Name("NonPointer"),
4595 inBuf: `null`,
4596 inVal: "unchanged",
4597 want: "unchanged",
4598 wantErr: EU(internal.ErrNonNilReference).withType(0, T[string]()),
4599 }, {
4600 name: jsontest.Name("Bools/TrailingJunk"),
4601 inBuf: `falsetrue`,
4602 inVal: addr(true),
4603 want: addr(false),
4604 wantErr: newInvalidCharacterError("t", "after top-level value", len64(`false`), ""),
4605 }, {
4606 name: jsontest.Name("Bools/Null"),
4607 inBuf: `null`,
4608 inVal: addr(true),
4609 want: addr(false),
4610 }, {
4611 name: jsontest.Name("Bools"),
4612 inBuf: `[null,false,true]`,
4613 inVal: new([]bool),
4614 want: addr([]bool{false, false, true}),
4615 }, {
4616 name: jsontest.Name("Bools/Named"),
4617 inBuf: `[null,false,true]`,
4618 inVal: new([]namedBool),
4619 want: addr([]namedBool{false, false, true}),
4620 }, {
4621 name: jsontest.Name("Bools/Invalid/StringifiedFalse"),
4622 opts: []Options{StringifyNumbers(true)},
4623 inBuf: `"false"`,
4624 inVal: addr(true),
4625 want: addr(true),
4626 wantErr: EU(nil).withType('"', boolType),
4627 }, {
4628 name: jsontest.Name("Bools/Invalid/StringifiedTrue"),
4629 opts: []Options{StringifyNumbers(true)},
4630 inBuf: `"true"`,
4631 inVal: addr(true),
4632 want: addr(true),
4633 wantErr: EU(nil).withType('"', boolType),
4634 }, {
4635 name: jsontest.Name("Bools/StringifiedBool/True"),
4636 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4637 inBuf: `"true"`,
4638 inVal: addr(false),
4639 want: addr(true),
4640 }, {
4641 name: jsontest.Name("Bools/StringifiedBool/False"),
4642 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4643 inBuf: `"false"`,
4644 inVal: addr(true),
4645 want: addr(false),
4646 }, {
4647 name: jsontest.Name("Bools/StringifiedBool/InvalidWhitespace"),
4648 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4649 inBuf: `"false "`,
4650 inVal: addr(true),
4651 want: addr(true),
4652 wantErr: EU(strconv.ErrSyntax).withVal(`"false "`).withType('"', boolType),
4653 }, {
4654 name: jsontest.Name("Bools/StringifiedBool/InvalidBool"),
4655 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4656 inBuf: `false`,
4657 inVal: addr(true),
4658 want: addr(true),
4659 wantErr: EU(nil).withType('f', boolType),
4660 }, {
4661 name: jsontest.Name("Bools/Invalid/Number"),
4662 inBuf: `0`,
4663 inVal: addr(true),
4664 want: addr(true),
4665 wantErr: EU(nil).withType('0', boolType),
4666 }, {
4667 name: jsontest.Name("Bools/Invalid/String"),
4668 inBuf: `""`,
4669 inVal: addr(true),
4670 want: addr(true),
4671 wantErr: EU(nil).withType('"', boolType),
4672 }, {
4673 name: jsontest.Name("Bools/Invalid/Object"),
4674 inBuf: `{}`,
4675 inVal: addr(true),
4676 want: addr(true),
4677 wantErr: EU(nil).withType('{', boolType),
4678 }, {
4679 name: jsontest.Name("Bools/Invalid/Array"),
4680 inBuf: `[]`,
4681 inVal: addr(true),
4682 want: addr(true),
4683 wantErr: EU(nil).withType('[', boolType),
4684 }, {
4685 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
4686 opts: []Options{invalidFormatOption},
4687 inBuf: `false`,
4688 inVal: addr(true),
4689 want: addr(false),
4690 }, {
4691 name: jsontest.Name("Strings/Null"),
4692 inBuf: `null`,
4693 inVal: addr("something"),
4694 want: addr(""),
4695 }, {
4696 name: jsontest.Name("Strings"),
4697 inBuf: `[null,"","hello","世界"]`,
4698 inVal: new([]string),
4699 want: addr([]string{"", "", "hello", "世界"}),
4700 }, {
4701 name: jsontest.Name("Strings/Escaped"),
4702 inBuf: `[null,"","\u0068\u0065\u006c\u006c\u006f","\u4e16\u754c"]`,
4703 inVal: new([]string),
4704 want: addr([]string{"", "", "hello", "世界"}),
4705 }, {
4706 name: jsontest.Name("Strings/Named"),
4707 inBuf: `[null,"","hello","世界"]`,
4708 inVal: new([]namedString),
4709 want: addr([]namedString{"", "", "hello", "世界"}),
4710 }, {
4711 name: jsontest.Name("Strings/Invalid/False"),
4712 inBuf: `false`,
4713 inVal: addr("nochange"),
4714 want: addr("nochange"),
4715 wantErr: EU(nil).withType('f', stringType),
4716 }, {
4717 name: jsontest.Name("Strings/Invalid/True"),
4718 inBuf: `true`,
4719 inVal: addr("nochange"),
4720 want: addr("nochange"),
4721 wantErr: EU(nil).withType('t', stringType),
4722 }, {
4723 name: jsontest.Name("Strings/Invalid/Object"),
4724 inBuf: `{}`,
4725 inVal: addr("nochange"),
4726 want: addr("nochange"),
4727 wantErr: EU(nil).withType('{', stringType),
4728 }, {
4729 name: jsontest.Name("Strings/Invalid/Array"),
4730 inBuf: `[]`,
4731 inVal: addr("nochange"),
4732 want: addr("nochange"),
4733 wantErr: EU(nil).withType('[', stringType),
4734 }, {
4735 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
4736 opts: []Options{invalidFormatOption},
4737 inBuf: `"hello"`,
4738 inVal: addr("goodbye"),
4739 want: addr("hello"),
4740 }, {
4741 name: jsontest.Name("Strings/StringifiedString"),
4742 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4743 inBuf: `"\"foo\""`,
4744 inVal: new(string),
4745 want: addr("foo"),
4746 }, {
4747 name: jsontest.Name("Strings/StringifiedString/InvalidWhitespace"),
4748 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4749 inBuf: `"\"foo\" "`,
4750 inVal: new(string),
4751 want: new(string),
4752 wantErr: EU(newInvalidCharacterError(" ", "after string value", 0, "")).withType('"', stringType),
4753 }, {
4754 name: jsontest.Name("Strings/StringifiedString/InvalidString"),
4755 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
4756 inBuf: `""`,
4757 inVal: new(string),
4758 want: new(string),
4759 wantErr: EU(&jsontext.SyntacticError{Err: io.ErrUnexpectedEOF}).withType('"', stringType),
4760 }, {
4761 name: jsontest.Name("Bytes/Null"),
4762 inBuf: `null`,
4763 inVal: addr([]byte("something")),
4764 want: addr([]byte(nil)),
4765 }, {
4766 name: jsontest.Name("Bytes"),
4767 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4768 inVal: new([][]byte),
4769 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4770 }, {
4771 name: jsontest.Name("Bytes/Large"),
4772 inBuf: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
4773 inVal: new([]byte),
4774 want: addr([]byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on.")),
4775 }, {
4776 name: jsontest.Name("Bytes/Reuse"),
4777 inBuf: `"AQID"`,
4778 inVal: addr([]byte("changed")),
4779 want: addr([]byte{1, 2, 3}),
4780 }, {
4781 name: jsontest.Name("Bytes/Escaped"),
4782 inBuf: `[null,"","\u0041\u0051\u003d\u003d","\u0041\u0051\u0049\u003d","\u0041\u0051\u0049\u0044"]`,
4783 inVal: new([][]byte),
4784 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4785 }, {
4786 name: jsontest.Name("Bytes/Named"),
4787 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4788 inVal: new([]namedBytes),
4789 want: addr([]namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4790 }, {
4791 name: jsontest.Name("Bytes/NotStringified"),
4792 opts: []Options{StringifyNumbers(true)},
4793 inBuf: `[null,"","AQ==","AQI=","AQID"]`,
4794 inVal: new([][]byte),
4795 want: addr([][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4796 }, {
4797
4798
4799 name: jsontest.Name("Bytes/Invariant"),
4800 inBuf: `[null,[],[1],[1,2],[1,2,3]]`,
4801 inVal: new([][]namedByte),
4802 want: addr([][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}}),
4803 }, {
4804
4805
4806 name: jsontest.Name("Bytes/ByteArray"),
4807 inBuf: `"aGVsbG8="`,
4808 inVal: new([5]byte),
4809 want: addr([5]byte{'h', 'e', 'l', 'l', 'o'}),
4810 }, {
4811 name: jsontest.Name("Bytes/ByteArray0/Valid"),
4812 inBuf: `""`,
4813 inVal: new([0]byte),
4814 want: addr([0]byte{}),
4815 }, {
4816 name: jsontest.Name("Bytes/ByteArray0/Invalid"),
4817 inBuf: `"A"`,
4818 inVal: new([0]byte),
4819 want: addr([0]byte{}),
4820 wantErr: EU(func() error {
4821 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("A"))
4822 return err
4823 }()).withType('"', T[[0]byte]()),
4824 }, {
4825 name: jsontest.Name("Bytes/ByteArray0/Overflow"),
4826 inBuf: `"AA=="`,
4827 inVal: new([0]byte),
4828 want: addr([0]byte{}),
4829 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 0")).withType('"', T[[0]byte]()),
4830 }, {
4831 name: jsontest.Name("Bytes/ByteArray1/Valid"),
4832 inBuf: `"AQ=="`,
4833 inVal: new([1]byte),
4834 want: addr([1]byte{1}),
4835 }, {
4836 name: jsontest.Name("Bytes/ByteArray1/Invalid"),
4837 inBuf: `"$$=="`,
4838 inVal: new([1]byte),
4839 want: addr([1]byte{}),
4840 wantErr: EU(func() error {
4841 _, err := base64.StdEncoding.Decode(make([]byte, 1), []byte("$$=="))
4842 return err
4843 }()).withType('"', T[[1]byte]()),
4844 }, {
4845 name: jsontest.Name("Bytes/ByteArray1/Underflow"),
4846 inBuf: `""`,
4847 inVal: new([1]byte),
4848 want: addr([1]byte{}),
4849 wantErr: EU(errors.New("decoded length of 0 mismatches array length of 1")).withType('"', T[[1]byte]()),
4850 }, {
4851 name: jsontest.Name("Bytes/ByteArray1/Overflow"),
4852 inBuf: `"AQI="`,
4853 inVal: new([1]byte),
4854 want: addr([1]byte{1}),
4855 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 1")).withType('"', T[[1]byte]()),
4856 }, {
4857 name: jsontest.Name("Bytes/ByteArray2/Valid"),
4858 inBuf: `"AQI="`,
4859 inVal: new([2]byte),
4860 want: addr([2]byte{1, 2}),
4861 }, {
4862 name: jsontest.Name("Bytes/ByteArray2/Invalid"),
4863 inBuf: `"$$$="`,
4864 inVal: new([2]byte),
4865 want: addr([2]byte{}),
4866 wantErr: EU(func() error {
4867 _, err := base64.StdEncoding.Decode(make([]byte, 2), []byte("$$$="))
4868 return err
4869 }()).withType('"', T[[2]byte]()),
4870 }, {
4871 name: jsontest.Name("Bytes/ByteArray2/Underflow"),
4872 inBuf: `"AQ=="`,
4873 inVal: new([2]byte),
4874 want: addr([2]byte{1, 0}),
4875 wantErr: EU(errors.New("decoded length of 1 mismatches array length of 2")).withType('"', T[[2]byte]()),
4876 }, {
4877 name: jsontest.Name("Bytes/ByteArray2/Underflow/Allowed"),
4878 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4879 inBuf: `"AQ=="`,
4880 inVal: new([2]byte),
4881 want: addr([2]byte{1, 0}),
4882 }, {
4883 name: jsontest.Name("Bytes/ByteArray2/Overflow"),
4884 inBuf: `"AQID"`,
4885 inVal: new([2]byte),
4886 want: addr([2]byte{1, 2}),
4887 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 2")).withType('"', T[[2]byte]()),
4888 }, {
4889 name: jsontest.Name("Bytes/ByteArray2/Overflow/Allowed"),
4890 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
4891 inBuf: `"AQID"`,
4892 inVal: new([2]byte),
4893 want: addr([2]byte{1, 2}),
4894 }, {
4895 name: jsontest.Name("Bytes/ByteArray3/Valid"),
4896 inBuf: `"AQID"`,
4897 inVal: new([3]byte),
4898 want: addr([3]byte{1, 2, 3}),
4899 }, {
4900 name: jsontest.Name("Bytes/ByteArray3/Invalid"),
4901 inBuf: `"$$$$"`,
4902 inVal: new([3]byte),
4903 want: addr([3]byte{}),
4904 wantErr: EU(func() error {
4905 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("$$$$"))
4906 return err
4907 }()).withType('"', T[[3]byte]()),
4908 }, {
4909 name: jsontest.Name("Bytes/ByteArray3/Underflow"),
4910 inBuf: `"AQI="`,
4911 inVal: addr([3]byte{0xff, 0xff, 0xff}),
4912 want: addr([3]byte{1, 2, 0}),
4913 wantErr: EU(errors.New("decoded length of 2 mismatches array length of 3")).withType('"', T[[3]byte]()),
4914 }, {
4915 name: jsontest.Name("Bytes/ByteArray3/Overflow"),
4916 inBuf: `"AQIDAQ=="`,
4917 inVal: new([3]byte),
4918 want: addr([3]byte{1, 2, 3}),
4919 wantErr: EU(errors.New("decoded length of 4 mismatches array length of 3")).withType('"', T[[3]byte]()),
4920 }, {
4921 name: jsontest.Name("Bytes/ByteArray4/Valid"),
4922 inBuf: `"AQIDBA=="`,
4923 inVal: new([4]byte),
4924 want: addr([4]byte{1, 2, 3, 4}),
4925 }, {
4926 name: jsontest.Name("Bytes/ByteArray4/Invalid"),
4927 inBuf: `"$$$$$$=="`,
4928 inVal: new([4]byte),
4929 want: addr([4]byte{}),
4930 wantErr: EU(func() error {
4931 _, err := base64.StdEncoding.Decode(make([]byte, 4), []byte("$$$$$$=="))
4932 return err
4933 }()).withType('"', T[[4]byte]()),
4934 }, {
4935 name: jsontest.Name("Bytes/ByteArray4/Underflow"),
4936 inBuf: `"AQID"`,
4937 inVal: new([4]byte),
4938 want: addr([4]byte{1, 2, 3, 0}),
4939 wantErr: EU(errors.New("decoded length of 3 mismatches array length of 4")).withType('"', T[[4]byte]()),
4940 }, {
4941 name: jsontest.Name("Bytes/ByteArray4/Overflow"),
4942 inBuf: `"AQIDBAU="`,
4943 inVal: new([4]byte),
4944 want: addr([4]byte{1, 2, 3, 4}),
4945 wantErr: EU(errors.New("decoded length of 5 mismatches array length of 4")).withType('"', T[[4]byte]()),
4946 }, {
4947
4948
4949 name: jsontest.Name("Bytes/NamedByteArray"),
4950 inBuf: `[104,101,108,108,111]`,
4951 inVal: new([5]namedByte),
4952 want: addr([5]namedByte{'h', 'e', 'l', 'l', 'o'}),
4953 }, {
4954 name: jsontest.Name("Bytes/Valid/Denormalized"),
4955 inBuf: `"AR=="`,
4956 inVal: new([]byte),
4957 want: addr([]byte{1}),
4958 }, {
4959 name: jsontest.Name("Bytes/Invalid/Unpadded1"),
4960 inBuf: `"AQ="`,
4961 inVal: addr([]byte("nochange")),
4962 want: addr([]byte("nochange")),
4963 wantErr: EU(func() error {
4964 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ="))
4965 return err
4966 }()).withType('"', bytesType),
4967 }, {
4968 name: jsontest.Name("Bytes/Invalid/Unpadded2"),
4969 inBuf: `"AQ"`,
4970 inVal: addr([]byte("nochange")),
4971 want: addr([]byte("nochange")),
4972 wantErr: EU(func() error {
4973 _, err := base64.StdEncoding.Decode(make([]byte, 0), []byte("AQ"))
4974 return err
4975 }()).withType('"', bytesType),
4976 }, {
4977 name: jsontest.Name("Bytes/Invalid/Character"),
4978 inBuf: `"@@@@"`,
4979 inVal: addr([]byte("nochange")),
4980 want: addr([]byte("nochange")),
4981 wantErr: EU(func() error {
4982 _, err := base64.StdEncoding.Decode(make([]byte, 3), []byte("@@@@"))
4983 return err
4984 }()).withType('"', bytesType),
4985 }, {
4986 name: jsontest.Name("Bytes/Invalid/Bool"),
4987 inBuf: `true`,
4988 inVal: addr([]byte("nochange")),
4989 want: addr([]byte("nochange")),
4990 wantErr: EU(nil).withType('t', bytesType),
4991 }, {
4992 name: jsontest.Name("Bytes/Invalid/Number"),
4993 inBuf: `0`,
4994 inVal: addr([]byte("nochange")),
4995 want: addr([]byte("nochange")),
4996 wantErr: EU(nil).withType('0', bytesType),
4997 }, {
4998 name: jsontest.Name("Bytes/Invalid/Object"),
4999 inBuf: `{}`,
5000 inVal: addr([]byte("nochange")),
5001 want: addr([]byte("nochange")),
5002 wantErr: EU(nil).withType('{', bytesType),
5003 }, {
5004 name: jsontest.Name("Bytes/Invalid/Array"),
5005 inBuf: `[]`,
5006 inVal: addr([]byte("nochange")),
5007 want: addr([]byte("nochange")),
5008 wantErr: EU(nil).withType('[', bytesType),
5009 }, {
5010 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
5011 opts: []Options{invalidFormatOption},
5012 inBuf: `"aGVsbG8="`,
5013 inVal: new([]byte),
5014 want: addr([]byte("hello")),
5015 }, {
5016 name: jsontest.Name("Ints/Null"),
5017 inBuf: `null`,
5018 inVal: addr(int(1)),
5019 want: addr(int(0)),
5020 }, {
5021 name: jsontest.Name("Ints/Int"),
5022 inBuf: `1`,
5023 inVal: addr(int(0)),
5024 want: addr(int(1)),
5025 }, {
5026 name: jsontest.Name("Ints/Int8/MinOverflow"),
5027 inBuf: `-129`,
5028 inVal: addr(int8(-1)),
5029 want: addr(int8(-1)),
5030 wantErr: EU(strconv.ErrRange).withVal(`-129`).withType('0', T[int8]()),
5031 }, {
5032 name: jsontest.Name("Ints/Int8/Min"),
5033 inBuf: `-128`,
5034 inVal: addr(int8(0)),
5035 want: addr(int8(-128)),
5036 }, {
5037 name: jsontest.Name("Ints/Int8/Max"),
5038 inBuf: `127`,
5039 inVal: addr(int8(0)),
5040 want: addr(int8(127)),
5041 }, {
5042 name: jsontest.Name("Ints/Int8/MaxOverflow"),
5043 inBuf: `128`,
5044 inVal: addr(int8(-1)),
5045 want: addr(int8(-1)),
5046 wantErr: EU(strconv.ErrRange).withVal(`128`).withType('0', T[int8]()),
5047 }, {
5048 name: jsontest.Name("Ints/Int16/MinOverflow"),
5049 inBuf: `-32769`,
5050 inVal: addr(int16(-1)),
5051 want: addr(int16(-1)),
5052 wantErr: EU(strconv.ErrRange).withVal(`-32769`).withType('0', T[int16]()),
5053 }, {
5054 name: jsontest.Name("Ints/Int16/Min"),
5055 inBuf: `-32768`,
5056 inVal: addr(int16(0)),
5057 want: addr(int16(-32768)),
5058 }, {
5059 name: jsontest.Name("Ints/Int16/Max"),
5060 inBuf: `32767`,
5061 inVal: addr(int16(0)),
5062 want: addr(int16(32767)),
5063 }, {
5064 name: jsontest.Name("Ints/Int16/MaxOverflow"),
5065 inBuf: `32768`,
5066 inVal: addr(int16(-1)),
5067 want: addr(int16(-1)),
5068 wantErr: EU(strconv.ErrRange).withVal(`32768`).withType('0', T[int16]()),
5069 }, {
5070 name: jsontest.Name("Ints/Int32/MinOverflow"),
5071 inBuf: `-2147483649`,
5072 inVal: addr(int32(-1)),
5073 want: addr(int32(-1)),
5074 wantErr: EU(strconv.ErrRange).withVal(`-2147483649`).withType('0', T[int32]()),
5075 }, {
5076 name: jsontest.Name("Ints/Int32/Min"),
5077 inBuf: `-2147483648`,
5078 inVal: addr(int32(0)),
5079 want: addr(int32(-2147483648)),
5080 }, {
5081 name: jsontest.Name("Ints/Int32/Max"),
5082 inBuf: `2147483647`,
5083 inVal: addr(int32(0)),
5084 want: addr(int32(2147483647)),
5085 }, {
5086 name: jsontest.Name("Ints/Int32/MaxOverflow"),
5087 inBuf: `2147483648`,
5088 inVal: addr(int32(-1)),
5089 want: addr(int32(-1)),
5090 wantErr: EU(strconv.ErrRange).withVal(`2147483648`).withType('0', T[int32]()),
5091 }, {
5092 name: jsontest.Name("Ints/Int64/MinOverflow"),
5093 inBuf: `-9223372036854775809`,
5094 inVal: addr(int64(-1)),
5095 want: addr(int64(-1)),
5096 wantErr: EU(strconv.ErrRange).withVal(`-9223372036854775809`).withType('0', T[int64]()),
5097 }, {
5098 name: jsontest.Name("Ints/Int64/Min"),
5099 inBuf: `-9223372036854775808`,
5100 inVal: addr(int64(0)),
5101 want: addr(int64(-9223372036854775808)),
5102 }, {
5103 name: jsontest.Name("Ints/Int64/Max"),
5104 inBuf: `9223372036854775807`,
5105 inVal: addr(int64(0)),
5106 want: addr(int64(9223372036854775807)),
5107 }, {
5108 name: jsontest.Name("Ints/Int64/MaxOverflow"),
5109 inBuf: `9223372036854775808`,
5110 inVal: addr(int64(-1)),
5111 want: addr(int64(-1)),
5112 wantErr: EU(strconv.ErrRange).withVal(`9223372036854775808`).withType('0', T[int64]()),
5113 }, {
5114 name: jsontest.Name("Ints/Named"),
5115 inBuf: `-6464`,
5116 inVal: addr(namedInt64(0)),
5117 want: addr(namedInt64(-6464)),
5118 }, {
5119 name: jsontest.Name("Ints/Stringified"),
5120 opts: []Options{StringifyNumbers(true)},
5121 inBuf: `"-6464"`,
5122 inVal: new(int),
5123 want: addr(int(-6464)),
5124 }, {
5125 name: jsontest.Name("Ints/Stringified/Invalid"),
5126 opts: []Options{StringifyNumbers(true)},
5127 inBuf: `-6464`,
5128 inVal: new(int),
5129 want: new(int),
5130 wantErr: EU(nil).withType('0', T[int]()),
5131 }, {
5132 name: jsontest.Name("Ints/Stringified/LeadingZero"),
5133 opts: []Options{StringifyNumbers(true)},
5134 inBuf: `"00"`,
5135 inVal: addr(int(-1)),
5136 want: addr(int(-1)),
5137 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[int]()),
5138 }, {
5139 name: jsontest.Name("Ints/Escaped"),
5140 opts: []Options{StringifyNumbers(true)},
5141 inBuf: `"\u002d\u0036\u0034\u0036\u0034"`,
5142 inVal: new(int),
5143 want: addr(int(-6464)),
5144 }, {
5145 name: jsontest.Name("Ints/Valid/NegativeZero"),
5146 inBuf: `-0`,
5147 inVal: addr(int(1)),
5148 want: addr(int(0)),
5149 }, {
5150 name: jsontest.Name("Ints/Invalid/Fraction"),
5151 inBuf: `1.0`,
5152 inVal: addr(int(-1)),
5153 want: addr(int(-1)),
5154 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[int]()),
5155 }, {
5156 name: jsontest.Name("Ints/Invalid/Exponent"),
5157 inBuf: `1e0`,
5158 inVal: addr(int(-1)),
5159 want: addr(int(-1)),
5160 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[int]()),
5161 }, {
5162 name: jsontest.Name("Ints/Invalid/StringifiedFraction"),
5163 opts: []Options{StringifyNumbers(true)},
5164 inBuf: `"1.0"`,
5165 inVal: addr(int(-1)),
5166 want: addr(int(-1)),
5167 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[int]()),
5168 }, {
5169 name: jsontest.Name("Ints/Invalid/StringifiedExponent"),
5170 opts: []Options{StringifyNumbers(true)},
5171 inBuf: `"1e0"`,
5172 inVal: addr(int(-1)),
5173 want: addr(int(-1)),
5174 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[int]()),
5175 }, {
5176 name: jsontest.Name("Ints/Invalid/Overflow"),
5177 inBuf: `100000000000000000000000000000`,
5178 inVal: addr(int(-1)),
5179 want: addr(int(-1)),
5180 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[int]()),
5181 }, {
5182 name: jsontest.Name("Ints/Invalid/OverflowSyntax"),
5183 opts: []Options{StringifyNumbers(true)},
5184 inBuf: `"100000000000000000000000000000x"`,
5185 inVal: addr(int(-1)),
5186 want: addr(int(-1)),
5187 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[int]()),
5188 }, {
5189 name: jsontest.Name("Ints/Invalid/Whitespace"),
5190 opts: []Options{StringifyNumbers(true)},
5191 inBuf: `"0 "`,
5192 inVal: addr(int(-1)),
5193 want: addr(int(-1)),
5194 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[int]()),
5195 }, {
5196 name: jsontest.Name("Ints/Invalid/Bool"),
5197 inBuf: `true`,
5198 inVal: addr(int(-1)),
5199 want: addr(int(-1)),
5200 wantErr: EU(nil).withType('t', T[int]()),
5201 }, {
5202 name: jsontest.Name("Ints/Invalid/String"),
5203 inBuf: `"0"`,
5204 inVal: addr(int(-1)),
5205 want: addr(int(-1)),
5206 wantErr: EU(nil).withType('"', T[int]()),
5207 }, {
5208 name: jsontest.Name("Ints/Invalid/Object"),
5209 inBuf: `{}`,
5210 inVal: addr(int(-1)),
5211 want: addr(int(-1)),
5212 wantErr: EU(nil).withType('{', T[int]()),
5213 }, {
5214 name: jsontest.Name("Ints/Invalid/Array"),
5215 inBuf: `[]`,
5216 inVal: addr(int(-1)),
5217 want: addr(int(-1)),
5218 wantErr: EU(nil).withType('[', T[int]()),
5219 }, {
5220 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
5221 opts: []Options{invalidFormatOption},
5222 inBuf: `1`,
5223 inVal: addr(int(0)),
5224 want: addr(int(1)),
5225 }, {
5226 name: jsontest.Name("Uints/Null"),
5227 inBuf: `null`,
5228 inVal: addr(uint(1)),
5229 want: addr(uint(0)),
5230 }, {
5231 name: jsontest.Name("Uints/Uint"),
5232 inBuf: `1`,
5233 inVal: addr(uint(0)),
5234 want: addr(uint(1)),
5235 }, {
5236 name: jsontest.Name("Uints/Uint8/Min"),
5237 inBuf: `0`,
5238 inVal: addr(uint8(1)),
5239 want: addr(uint8(0)),
5240 }, {
5241 name: jsontest.Name("Uints/Uint8/Max"),
5242 inBuf: `255`,
5243 inVal: addr(uint8(0)),
5244 want: addr(uint8(255)),
5245 }, {
5246 name: jsontest.Name("Uints/Uint8/MaxOverflow"),
5247 inBuf: `256`,
5248 inVal: addr(uint8(1)),
5249 want: addr(uint8(1)),
5250 wantErr: EU(strconv.ErrRange).withVal(`256`).withType('0', T[uint8]()),
5251 }, {
5252 name: jsontest.Name("Uints/Uint16/Min"),
5253 inBuf: `0`,
5254 inVal: addr(uint16(1)),
5255 want: addr(uint16(0)),
5256 }, {
5257 name: jsontest.Name("Uints/Uint16/Max"),
5258 inBuf: `65535`,
5259 inVal: addr(uint16(0)),
5260 want: addr(uint16(65535)),
5261 }, {
5262 name: jsontest.Name("Uints/Uint16/MaxOverflow"),
5263 inBuf: `65536`,
5264 inVal: addr(uint16(1)),
5265 want: addr(uint16(1)),
5266 wantErr: EU(strconv.ErrRange).withVal(`65536`).withType('0', T[uint16]()),
5267 }, {
5268 name: jsontest.Name("Uints/Uint32/Min"),
5269 inBuf: `0`,
5270 inVal: addr(uint32(1)),
5271 want: addr(uint32(0)),
5272 }, {
5273 name: jsontest.Name("Uints/Uint32/Max"),
5274 inBuf: `4294967295`,
5275 inVal: addr(uint32(0)),
5276 want: addr(uint32(4294967295)),
5277 }, {
5278 name: jsontest.Name("Uints/Uint32/MaxOverflow"),
5279 inBuf: `4294967296`,
5280 inVal: addr(uint32(1)),
5281 want: addr(uint32(1)),
5282 wantErr: EU(strconv.ErrRange).withVal(`4294967296`).withType('0', T[uint32]()),
5283 }, {
5284 name: jsontest.Name("Uints/Uint64/Min"),
5285 inBuf: `0`,
5286 inVal: addr(uint64(1)),
5287 want: addr(uint64(0)),
5288 }, {
5289 name: jsontest.Name("Uints/Uint64/Max"),
5290 inBuf: `18446744073709551615`,
5291 inVal: addr(uint64(0)),
5292 want: addr(uint64(18446744073709551615)),
5293 }, {
5294 name: jsontest.Name("Uints/Uint64/MaxOverflow"),
5295 inBuf: `18446744073709551616`,
5296 inVal: addr(uint64(1)),
5297 want: addr(uint64(1)),
5298 wantErr: EU(strconv.ErrRange).withVal(`18446744073709551616`).withType('0', T[uint64]()),
5299 }, {
5300 name: jsontest.Name("Uints/Uintptr"),
5301 inBuf: `1`,
5302 inVal: addr(uintptr(0)),
5303 want: addr(uintptr(1)),
5304 }, {
5305 name: jsontest.Name("Uints/Named"),
5306 inBuf: `6464`,
5307 inVal: addr(namedUint64(0)),
5308 want: addr(namedUint64(6464)),
5309 }, {
5310 name: jsontest.Name("Uints/Stringified"),
5311 opts: []Options{StringifyNumbers(true)},
5312 inBuf: `"6464"`,
5313 inVal: new(uint),
5314 want: addr(uint(6464)),
5315 }, {
5316 name: jsontest.Name("Uints/Stringified/Invalid"),
5317 opts: []Options{StringifyNumbers(true)},
5318 inBuf: `6464`,
5319 inVal: new(uint),
5320 want: new(uint),
5321 wantErr: EU(nil).withType('0', T[uint]()),
5322 }, {
5323 name: jsontest.Name("Uints/Stringified/LeadingZero"),
5324 opts: []Options{StringifyNumbers(true)},
5325 inBuf: `"00"`,
5326 inVal: addr(uint(1)),
5327 want: addr(uint(1)),
5328 wantErr: EU(strconv.ErrSyntax).withVal(`"00"`).withType('"', T[uint]()),
5329 }, {
5330 name: jsontest.Name("Uints/Escaped"),
5331 opts: []Options{StringifyNumbers(true)},
5332 inBuf: `"\u0036\u0034\u0036\u0034"`,
5333 inVal: new(uint),
5334 want: addr(uint(6464)),
5335 }, {
5336 name: jsontest.Name("Uints/Invalid/NegativeOne"),
5337 inBuf: `-1`,
5338 inVal: addr(uint(1)),
5339 want: addr(uint(1)),
5340 wantErr: EU(strconv.ErrSyntax).withVal(`-1`).withType('0', T[uint]()),
5341 }, {
5342 name: jsontest.Name("Uints/Invalid/NegativeZero"),
5343 inBuf: `-0`,
5344 inVal: addr(uint(1)),
5345 want: addr(uint(1)),
5346 wantErr: EU(strconv.ErrSyntax).withVal(`-0`).withType('0', T[uint]()),
5347 }, {
5348 name: jsontest.Name("Uints/Invalid/Fraction"),
5349 inBuf: `1.0`,
5350 inVal: addr(uint(10)),
5351 want: addr(uint(10)),
5352 wantErr: EU(strconv.ErrSyntax).withVal(`1.0`).withType('0', T[uint]()),
5353 }, {
5354 name: jsontest.Name("Uints/Invalid/Exponent"),
5355 inBuf: `1e0`,
5356 inVal: addr(uint(10)),
5357 want: addr(uint(10)),
5358 wantErr: EU(strconv.ErrSyntax).withVal(`1e0`).withType('0', T[uint]()),
5359 }, {
5360 name: jsontest.Name("Uints/Invalid/StringifiedFraction"),
5361 opts: []Options{StringifyNumbers(true)},
5362 inBuf: `"1.0"`,
5363 inVal: addr(uint(10)),
5364 want: addr(uint(10)),
5365 wantErr: EU(strconv.ErrSyntax).withVal(`"1.0"`).withType('"', T[uint]()),
5366 }, {
5367 name: jsontest.Name("Uints/Invalid/StringifiedExponent"),
5368 opts: []Options{StringifyNumbers(true)},
5369 inBuf: `"1e0"`,
5370 inVal: addr(uint(10)),
5371 want: addr(uint(10)),
5372 wantErr: EU(strconv.ErrSyntax).withVal(`"1e0"`).withType('"', T[uint]()),
5373 }, {
5374 name: jsontest.Name("Uints/Invalid/Overflow"),
5375 inBuf: `100000000000000000000000000000`,
5376 inVal: addr(uint(1)),
5377 want: addr(uint(1)),
5378 wantErr: EU(strconv.ErrRange).withVal(`100000000000000000000000000000`).withType('0', T[uint]()),
5379 }, {
5380 name: jsontest.Name("Uints/Invalid/OverflowSyntax"),
5381 opts: []Options{StringifyNumbers(true)},
5382 inBuf: `"100000000000000000000000000000x"`,
5383 inVal: addr(uint(1)),
5384 want: addr(uint(1)),
5385 wantErr: EU(strconv.ErrSyntax).withVal(`"100000000000000000000000000000x"`).withType('"', T[uint]()),
5386 }, {
5387 name: jsontest.Name("Uints/Invalid/Whitespace"),
5388 opts: []Options{StringifyNumbers(true)},
5389 inBuf: `"0 "`,
5390 inVal: addr(uint(1)),
5391 want: addr(uint(1)),
5392 wantErr: EU(strconv.ErrSyntax).withVal(`"0 "`).withType('"', T[uint]()),
5393 }, {
5394 name: jsontest.Name("Uints/Invalid/Bool"),
5395 inBuf: `true`,
5396 inVal: addr(uint(1)),
5397 want: addr(uint(1)),
5398 wantErr: EU(nil).withType('t', T[uint]()),
5399 }, {
5400 name: jsontest.Name("Uints/Invalid/String"),
5401 inBuf: `"0"`,
5402 inVal: addr(uint(1)),
5403 want: addr(uint(1)),
5404 wantErr: EU(nil).withType('"', T[uint]()),
5405 }, {
5406 name: jsontest.Name("Uints/Invalid/Object"),
5407 inBuf: `{}`,
5408 inVal: addr(uint(1)),
5409 want: addr(uint(1)),
5410 wantErr: EU(nil).withType('{', T[uint]()),
5411 }, {
5412 name: jsontest.Name("Uints/Invalid/Array"),
5413 inBuf: `[]`,
5414 inVal: addr(uint(1)),
5415 want: addr(uint(1)),
5416 wantErr: EU(nil).withType('[', T[uint]()),
5417 }, {
5418 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
5419 opts: []Options{invalidFormatOption},
5420 inBuf: `1`,
5421 inVal: addr(uint(0)),
5422 want: addr(uint(1)),
5423 }, {
5424 name: jsontest.Name("Floats/Null"),
5425 inBuf: `null`,
5426 inVal: addr(float64(64.64)),
5427 want: addr(float64(0)),
5428 }, {
5429 name: jsontest.Name("Floats/Float32/Pi"),
5430 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5431 inVal: addr(float32(32.32)),
5432 want: addr(float32(math.Pi)),
5433 }, {
5434 name: jsontest.Name("Floats/Float32/Underflow"),
5435 inBuf: `1e-1000`,
5436 inVal: addr(float32(32.32)),
5437 want: addr(float32(0)),
5438 }, {
5439 name: jsontest.Name("Floats/Float32/Overflow"),
5440 inBuf: `-1e1000`,
5441 inVal: addr(float32(32.32)),
5442 want: addr(float32(-math.MaxFloat32)),
5443 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float32]()),
5444 }, {
5445 name: jsontest.Name("Floats/Float64/Pi"),
5446 inBuf: `3.14159265358979323846264338327950288419716939937510582097494459`,
5447 inVal: addr(float64(64.64)),
5448 want: addr(float64(math.Pi)),
5449 }, {
5450 name: jsontest.Name("Floats/Float64/Underflow"),
5451 inBuf: `1e-1000`,
5452 inVal: addr(float64(64.64)),
5453 want: addr(float64(0)),
5454 }, {
5455 name: jsontest.Name("Floats/Float64/Overflow"),
5456 inBuf: `-1e1000`,
5457 inVal: addr(float64(64.64)),
5458 want: addr(float64(-math.MaxFloat64)),
5459 wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float64]()),
5460 }, {
5461 name: jsontest.Name("Floats/Any/Overflow"),
5462 inBuf: `1e1000`,
5463 inVal: new(any),
5464 want: addr(any(float64(math.MaxFloat64))),
5465 wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float64]()),
5466 }, {
5467 name: jsontest.Name("Floats/Named"),
5468 inBuf: `64.64`,
5469 inVal: addr(namedFloat64(0)),
5470 want: addr(namedFloat64(64.64)),
5471 }, {
5472 name: jsontest.Name("Floats/Stringified"),
5473 opts: []Options{StringifyNumbers(true)},
5474 inBuf: `"64.64"`,
5475 inVal: new(float64),
5476 want: addr(float64(64.64)),
5477 }, {
5478 name: jsontest.Name("Floats/Stringified/Invalid"),
5479 opts: []Options{StringifyNumbers(true)},
5480 inBuf: `64.64`,
5481 inVal: new(float64),
5482 want: new(float64),
5483 wantErr: EU(nil).withType('0', T[float64]()),
5484 }, {
5485 name: jsontest.Name("Floats/Escaped"),
5486 opts: []Options{StringifyNumbers(true)},
5487 inBuf: `"\u0036\u0034\u002e\u0036\u0034"`,
5488 inVal: new(float64),
5489 want: addr(float64(64.64)),
5490 }, {
5491 name: jsontest.Name("Floats/Invalid/NaN"),
5492 opts: []Options{StringifyNumbers(true)},
5493 inBuf: `"NaN"`,
5494 inVal: addr(float64(64.64)),
5495 want: addr(float64(64.64)),
5496 wantErr: EU(strconv.ErrSyntax).withVal(`"NaN"`).withType('"', float64Type),
5497 }, {
5498 name: jsontest.Name("Floats/Invalid/Infinity"),
5499 opts: []Options{StringifyNumbers(true)},
5500 inBuf: `"Infinity"`,
5501 inVal: addr(float64(64.64)),
5502 want: addr(float64(64.64)),
5503 wantErr: EU(strconv.ErrSyntax).withVal(`"Infinity"`).withType('"', float64Type),
5504 }, {
5505 name: jsontest.Name("Floats/Invalid/Whitespace"),
5506 opts: []Options{StringifyNumbers(true)},
5507 inBuf: `"1 "`,
5508 inVal: addr(float64(64.64)),
5509 want: addr(float64(64.64)),
5510 wantErr: EU(strconv.ErrSyntax).withVal(`"1 "`).withType('"', float64Type),
5511 }, {
5512 name: jsontest.Name("Floats/Invalid/GoSyntax"),
5513 opts: []Options{StringifyNumbers(true)},
5514 inBuf: `"1p-2"`,
5515 inVal: addr(float64(64.64)),
5516 want: addr(float64(64.64)),
5517 wantErr: EU(strconv.ErrSyntax).withVal(`"1p-2"`).withType('"', float64Type),
5518 }, {
5519 name: jsontest.Name("Floats/Invalid/Bool"),
5520 inBuf: `true`,
5521 inVal: addr(float64(64.64)),
5522 want: addr(float64(64.64)),
5523 wantErr: EU(nil).withType('t', float64Type),
5524 }, {
5525 name: jsontest.Name("Floats/Invalid/String"),
5526 inBuf: `"0"`,
5527 inVal: addr(float64(64.64)),
5528 want: addr(float64(64.64)),
5529 wantErr: EU(nil).withType('"', float64Type),
5530 }, {
5531 name: jsontest.Name("Floats/Invalid/Object"),
5532 inBuf: `{}`,
5533 inVal: addr(float64(64.64)),
5534 want: addr(float64(64.64)),
5535 wantErr: EU(nil).withType('{', float64Type),
5536 }, {
5537 name: jsontest.Name("Floats/Invalid/Array"),
5538 inBuf: `[]`,
5539 inVal: addr(float64(64.64)),
5540 want: addr(float64(64.64)),
5541 wantErr: EU(nil).withType('[', float64Type),
5542 }, {
5543 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
5544 opts: []Options{invalidFormatOption},
5545 inBuf: `1`,
5546 inVal: addr(float64(0)),
5547 want: addr(float64(1)),
5548 }, {
5549 name: jsontest.Name("Maps/Null"),
5550 inBuf: `null`,
5551 inVal: addr(map[string]string{"key": "value"}),
5552 want: new(map[string]string),
5553 }, {
5554 name: jsontest.Name("Maps/InvalidKey/Bool"),
5555 inBuf: `{"true":"false"}`,
5556 inVal: new(map[bool]bool),
5557 want: addr(make(map[bool]bool)),
5558 wantErr: EU(nil).withPos(`{`, "/true").withType('"', boolType),
5559 }, {
5560 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
5561 inBuf: `{"true":"false"}`,
5562 inVal: new(map[namedBool]bool),
5563 want: addr(make(map[namedBool]bool)),
5564 wantErr: EU(nil).withPos(`{`, "/true").withType('"', T[namedBool]()),
5565 }, {
5566 name: jsontest.Name("Maps/InvalidKey/Array"),
5567 inBuf: `{"key":"value"}`,
5568 inVal: new(map[[1]string]string),
5569 want: addr(make(map[[1]string]string)),
5570 wantErr: EU(nil).withPos(`{`, "/key").withType('"', T[[1]string]()),
5571 }, {
5572 name: jsontest.Name("Maps/InvalidKey/Channel"),
5573 inBuf: `{"key":"value"}`,
5574 inVal: new(map[chan string]string),
5575 want: addr(make(map[chan string]string)),
5576 wantErr: EU(nil).withPos(`{`, "").withType(0, T[chan string]()),
5577 }, {
5578 name: jsontest.Name("Maps/ValidKey/Int"),
5579 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5580 inVal: new(map[int]int),
5581 want: addr(map[int]int{0: 0, -1: 1, 2: 2, -3: 3}),
5582 }, {
5583 name: jsontest.Name("Maps/ValidKey/NamedInt"),
5584 inBuf: `{"0":0,"-1":1,"2":2,"-3":3}`,
5585 inVal: new(map[namedInt64]int),
5586 want: addr(map[namedInt64]int{0: 0, -1: 1, 2: 2, -3: 3}),
5587 }, {
5588 name: jsontest.Name("Maps/ValidKey/Uint"),
5589 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5590 inVal: new(map[uint]uint),
5591 want: addr(map[uint]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5592 }, {
5593 name: jsontest.Name("Maps/ValidKey/NamedUint"),
5594 inBuf: `{"0":0,"1":1,"2":2,"3":3}`,
5595 inVal: new(map[namedUint64]uint),
5596 want: addr(map[namedUint64]uint{0: 0, 1: 1, 2: 2, 3: 3}),
5597 }, {
5598 name: jsontest.Name("Maps/ValidKey/Float"),
5599 inBuf: `{"1.234":1.234,"12.34":12.34,"123.4":123.4}`,
5600 inVal: new(map[float64]float64),
5601 want: addr(map[float64]float64{1.234: 1.234, 12.34: 12.34, 123.4: 123.4}),
5602 }, {
5603 name: jsontest.Name("Maps/DuplicateName/Int"),
5604 inBuf: `{"0":1,"-0":-1}`,
5605 inVal: new(map[int]int),
5606 want: addr(map[int]int{0: 1}),
5607 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5608 }, {
5609 name: jsontest.Name("Maps/DuplicateName/Int/MergeWithLegacySemantics"),
5610 opts: []Options{jsonflags.MergeWithLegacySemantics | 1},
5611 inBuf: `{"0":1,"-0":-1}`,
5612 inVal: new(map[int]int),
5613 want: addr(map[int]int{0: 1}),
5614 wantErr: newDuplicateNameError("", []byte(`"-0"`), len64(`{"0":1,`)),
5615 }, {
5616 name: jsontest.Name("Maps/DuplicateName/Int/AllowDuplicateNames"),
5617 opts: []Options{jsontext.AllowDuplicateNames(true)},
5618 inBuf: `{"0":1,"-0":-1}`,
5619 inVal: new(map[int]int),
5620 want: addr(map[int]int{0: -1}),
5621 }, {
5622 name: jsontest.Name("Maps/DuplicateName/Int/OverwriteExisting"),
5623 inBuf: `{"-0":-1}`,
5624 inVal: addr(map[int]int{0: 1}),
5625 want: addr(map[int]int{0: -1}),
5626 }, {
5627 name: jsontest.Name("Maps/DuplicateName/Float"),
5628 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5629 inVal: new(map[float64]string),
5630 want: addr(map[float64]string{1: "1.0"}),
5631 wantErr: newDuplicateNameError("", []byte(`"1"`), len64(`{"1.0":"1.0",`)),
5632 }, {
5633 name: jsontest.Name("Maps/DuplicateName/Float/AllowDuplicateNames"),
5634 opts: []Options{jsontext.AllowDuplicateNames(true)},
5635 inBuf: `{"1.0":"1.0","1":"1","1e0":"1e0"}`,
5636 inVal: new(map[float64]string),
5637 want: addr(map[float64]string{1: "1e0"}),
5638 }, {
5639 name: jsontest.Name("Maps/DuplicateName/Float/OverwriteExisting"),
5640 inBuf: `{"1.0":"1.0"}`,
5641 inVal: addr(map[float64]string{1: "1"}),
5642 want: addr(map[float64]string{1: "1.0"}),
5643 }, {
5644 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
5645 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5646 inVal: new(map[nocaseString]string),
5647 want: addr(map[nocaseString]string{"hello": "hello"}),
5648 wantErr: newDuplicateNameError("", []byte(`"HELLO"`), len64(`{"hello":"hello",`)),
5649 }, {
5650 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
5651 opts: []Options{jsontext.AllowDuplicateNames(true)},
5652 inBuf: `{"hello":"hello","HELLO":"HELLO"}`,
5653 inVal: new(map[nocaseString]string),
5654 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5655 }, {
5656 name: jsontest.Name("Maps/DuplicateName/NoCaseString/OverwriteExisting"),
5657 opts: []Options{jsontext.AllowDuplicateNames(true)},
5658 inBuf: `{"HELLO":"HELLO"}`,
5659 inVal: addr(map[nocaseString]string{"hello": "hello"}),
5660 want: addr(map[nocaseString]string{"hello": "HELLO"}),
5661 }, {
5662 name: jsontest.Name("Maps/ValidKey/Interface"),
5663 inBuf: `{"false":"false","true":"true","string":"string","0":"0","[]":"[]","{}":"{}"}`,
5664 inVal: new(map[any]string),
5665 want: addr(map[any]string{
5666 "false": "false",
5667 "true": "true",
5668 "string": "string",
5669 "0": "0",
5670 "[]": "[]",
5671 "{}": "{}",
5672 }),
5673 }, {
5674 name: jsontest.Name("Maps/InvalidValue/Channel"),
5675 inBuf: `{"key":"value"}`,
5676 inVal: new(map[string]chan string),
5677 want: addr(map[string]chan string{
5678 "key": nil,
5679 }),
5680 wantErr: EU(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
5681 }, {
5682 name: jsontest.Name("Maps/RecursiveMap"),
5683 inBuf: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
5684 inVal: new(recursiveMap),
5685 want: addr(recursiveMap{
5686 "fizz": {
5687 "foo": {},
5688 "bar": {},
5689 },
5690 "buzz": {},
5691 }),
5692 }, {
5693
5694
5695
5696 name: jsontest.Name("Maps/Merge"),
5697 opts: []Options{jsontext.AllowDuplicateNames(true)},
5698 inBuf: `{"k1":{"k2":"v2"},"k2":{"k1":"v1"},"k2":{"k2":"v2"}}`,
5699 inVal: addr(map[string]map[string]string{
5700 "k1": {"k1": "v1"},
5701 }),
5702 want: addr(map[string]map[string]string{
5703 "k1": {"k1": "v1", "k2": "v2"},
5704 "k2": {"k1": "v1", "k2": "v2"},
5705 }),
5706 }, {
5707 name: jsontest.Name("Maps/Invalid/Bool"),
5708 inBuf: `true`,
5709 inVal: addr(map[string]string{"key": "value"}),
5710 want: addr(map[string]string{"key": "value"}),
5711 wantErr: EU(nil).withType('t', T[map[string]string]()),
5712 }, {
5713 name: jsontest.Name("Maps/Invalid/String"),
5714 inBuf: `""`,
5715 inVal: addr(map[string]string{"key": "value"}),
5716 want: addr(map[string]string{"key": "value"}),
5717 wantErr: EU(nil).withType('"', T[map[string]string]()),
5718 }, {
5719 name: jsontest.Name("Maps/Invalid/Number"),
5720 inBuf: `0`,
5721 inVal: addr(map[string]string{"key": "value"}),
5722 want: addr(map[string]string{"key": "value"}),
5723 wantErr: EU(nil).withType('0', T[map[string]string]()),
5724 }, {
5725 name: jsontest.Name("Maps/Invalid/Array"),
5726 inBuf: `[]`,
5727 inVal: addr(map[string]string{"key": "value"}),
5728 want: addr(map[string]string{"key": "value"}),
5729 wantErr: EU(nil).withType('[', T[map[string]string]()),
5730 }, {
5731 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
5732 opts: []Options{invalidFormatOption},
5733 inBuf: `{"hello":"goodbye"}`,
5734 inVal: addr(map[string]string{}),
5735 want: addr(map[string]string{"hello": "goodbye"}),
5736 }, {
5737 name: jsontest.Name("Structs/Null"),
5738 inBuf: `null`,
5739 inVal: addr(structAll{String: "something"}),
5740 want: addr(structAll{}),
5741 }, {
5742 name: jsontest.Name("Structs/Empty"),
5743 inBuf: `{}`,
5744 inVal: addr(structAll{
5745 String: "hello",
5746 Map: map[string]string{},
5747 Slice: []string{},
5748 }),
5749 want: addr(structAll{
5750 String: "hello",
5751 Map: map[string]string{},
5752 Slice: []string{},
5753 }),
5754 }, {
5755 name: jsontest.Name("Structs/Normal"),
5756 inBuf: `{
5757 "Bool": true,
5758 "String": "hello",
5759 "Bytes": "AQID",
5760 "Int": -64,
5761 "Uint": 64,
5762 "Float": 3.14159,
5763 "Map": {"key": "value"},
5764 "StructScalars": {
5765 "Bool": true,
5766 "String": "hello",
5767 "Bytes": "AQID",
5768 "Int": -64,
5769 "Uint": 64,
5770 "Float": 3.14159
5771 },
5772 "StructMaps": {
5773 "MapBool": {"": true},
5774 "MapString": {"": "hello"},
5775 "MapBytes": {"": "AQID"},
5776 "MapInt": {"": -64},
5777 "MapUint": {"": 64},
5778 "MapFloat": {"": 3.14159}
5779 },
5780 "StructSlices": {
5781 "SliceBool": [true],
5782 "SliceString": ["hello"],
5783 "SliceBytes": ["AQID"],
5784 "SliceInt": [-64],
5785 "SliceUint": [64],
5786 "SliceFloat": [3.14159]
5787 },
5788 "Slice": ["fizz","buzz"],
5789 "Array": ["goodbye"],
5790 "Pointer": {},
5791 "Interface": null
5792 }`,
5793 inVal: new(structAll),
5794 want: addr(structAll{
5795 Bool: true,
5796 String: "hello",
5797 Bytes: []byte{1, 2, 3},
5798 Int: -64,
5799 Uint: +64,
5800 Float: 3.14159,
5801 Map: map[string]string{"key": "value"},
5802 StructScalars: structScalars{
5803 Bool: true,
5804 String: "hello",
5805 Bytes: []byte{1, 2, 3},
5806 Int: -64,
5807 Uint: +64,
5808 Float: 3.14159,
5809 },
5810 StructMaps: structMaps{
5811 MapBool: map[string]bool{"": true},
5812 MapString: map[string]string{"": "hello"},
5813 MapBytes: map[string][]byte{"": {1, 2, 3}},
5814 MapInt: map[string]int64{"": -64},
5815 MapUint: map[string]uint64{"": +64},
5816 MapFloat: map[string]float64{"": 3.14159},
5817 },
5818 StructSlices: structSlices{
5819 SliceBool: []bool{true},
5820 SliceString: []string{"hello"},
5821 SliceBytes: [][]byte{{1, 2, 3}},
5822 SliceInt: []int64{-64},
5823 SliceUint: []uint64{+64},
5824 SliceFloat: []float64{3.14159},
5825 },
5826 Slice: []string{"fizz", "buzz"},
5827 Array: [1]string{"goodbye"},
5828 Pointer: new(structAll),
5829 }),
5830 }, {
5831 name: jsontest.Name("Structs/Merge"),
5832 inBuf: `{
5833 "Bool": false,
5834 "String": "goodbye",
5835 "Int": -64,
5836 "Float": 3.14159,
5837 "Map": {"k2": "v2"},
5838 "StructScalars": {
5839 "Bool": true,
5840 "String": "hello",
5841 "Bytes": "AQID",
5842 "Int": -64
5843 },
5844 "StructMaps": {
5845 "MapBool": {"": true},
5846 "MapString": {"": "hello"},
5847 "MapBytes": {"": "AQID"},
5848 "MapInt": {"": -64},
5849 "MapUint": {"": 64},
5850 "MapFloat": {"": 3.14159}
5851 },
5852 "StructSlices": {
5853 "SliceString": ["hello"],
5854 "SliceBytes": ["AQID"],
5855 "SliceInt": [-64],
5856 "SliceUint": [64]
5857 },
5858 "Slice": ["fizz","buzz"],
5859 "Array": ["goodbye"],
5860 "Pointer": {},
5861 "Interface": {"k2":"v2"}
5862 }`,
5863 inVal: addr(structAll{
5864 Bool: true,
5865 String: "hello",
5866 Bytes: []byte{1, 2, 3},
5867 Uint: +64,
5868 Float: math.NaN(),
5869 Map: map[string]string{"k1": "v1"},
5870 StructScalars: structScalars{
5871 String: "hello",
5872 Bytes: make([]byte, 2, 4),
5873 Uint: +64,
5874 Float: 3.14159,
5875 },
5876 StructMaps: structMaps{
5877 MapBool: map[string]bool{"": false},
5878 MapBytes: map[string][]byte{"": {}},
5879 MapInt: map[string]int64{"": 123},
5880 MapFloat: map[string]float64{"": math.Inf(+1)},
5881 },
5882 StructSlices: structSlices{
5883 SliceBool: []bool{true},
5884 SliceBytes: [][]byte{nil, nil},
5885 SliceInt: []int64{-123},
5886 SliceUint: []uint64{+123},
5887 SliceFloat: []float64{3.14159},
5888 },
5889 Slice: []string{"buzz", "fizz", "gizz"},
5890 Array: [1]string{"hello"},
5891 Pointer: new(structAll),
5892 Interface: map[string]string{"k1": "v1"},
5893 }),
5894 want: addr(structAll{
5895 Bool: false,
5896 String: "goodbye",
5897 Bytes: []byte{1, 2, 3},
5898 Int: -64,
5899 Uint: +64,
5900 Float: 3.14159,
5901 Map: map[string]string{"k1": "v1", "k2": "v2"},
5902 StructScalars: structScalars{
5903 Bool: true,
5904 String: "hello",
5905 Bytes: []byte{1, 2, 3},
5906 Int: -64,
5907 Uint: +64,
5908 Float: 3.14159,
5909 },
5910 StructMaps: structMaps{
5911 MapBool: map[string]bool{"": true},
5912 MapString: map[string]string{"": "hello"},
5913 MapBytes: map[string][]byte{"": {1, 2, 3}},
5914 MapInt: map[string]int64{"": -64},
5915 MapUint: map[string]uint64{"": +64},
5916 MapFloat: map[string]float64{"": 3.14159},
5917 },
5918 StructSlices: structSlices{
5919 SliceBool: []bool{true},
5920 SliceString: []string{"hello"},
5921 SliceBytes: [][]byte{{1, 2, 3}},
5922 SliceInt: []int64{-64},
5923 SliceUint: []uint64{+64},
5924 SliceFloat: []float64{3.14159},
5925 },
5926 Slice: []string{"fizz", "buzz"},
5927 Array: [1]string{"goodbye"},
5928 Pointer: new(structAll),
5929 Interface: map[string]string{"k1": "v1", "k2": "v2"},
5930 }),
5931 }, {
5932 name: jsontest.Name("Structs/Stringified/Normal"),
5933 inBuf: `{
5934 "Bool": true,
5935 "String": "hello",
5936 "Bytes": "AQID",
5937 "Int": "-64",
5938 "Uint": "64",
5939 "Float": "3.14159",
5940 "Map": {"key": "value"},
5941 "StructScalars": {
5942 "Bool": true,
5943 "String": "hello",
5944 "Bytes": "AQID",
5945 "Int": "-64",
5946 "Uint": "64",
5947 "Float": "3.14159"
5948 },
5949 "StructMaps": {
5950 "MapBool": {"": true},
5951 "MapString": {"": "hello"},
5952 "MapBytes": {"": "AQID"},
5953 "MapInt": {"": "-64"},
5954 "MapUint": {"": "64"},
5955 "MapFloat": {"": "3.14159"}
5956 },
5957 "StructSlices": {
5958 "SliceBool": [true],
5959 "SliceString": ["hello"],
5960 "SliceBytes": ["AQID"],
5961 "SliceInt": ["-64"],
5962 "SliceUint": ["64"],
5963 "SliceFloat": ["3.14159"]
5964 },
5965 "Slice": ["fizz","buzz"],
5966 "Array": ["goodbye"],
5967 "Pointer": {},
5968 "Interface": null
5969 }`,
5970 inVal: new(structStringifiedAll),
5971 want: addr(structStringifiedAll{
5972 Bool: true,
5973 String: "hello",
5974 Bytes: []byte{1, 2, 3},
5975 Int: -64,
5976 Uint: +64,
5977 Float: 3.14159,
5978 Map: map[string]string{"key": "value"},
5979 StructScalars: structScalars{
5980 Bool: true,
5981 String: "hello",
5982 Bytes: []byte{1, 2, 3},
5983 Int: -64,
5984 Uint: +64,
5985 Float: 3.14159,
5986 },
5987 StructMaps: structMaps{
5988 MapBool: map[string]bool{"": true},
5989 MapString: map[string]string{"": "hello"},
5990 MapBytes: map[string][]byte{"": {1, 2, 3}},
5991 MapInt: map[string]int64{"": -64},
5992 MapUint: map[string]uint64{"": +64},
5993 MapFloat: map[string]float64{"": 3.14159},
5994 },
5995 StructSlices: structSlices{
5996 SliceBool: []bool{true},
5997 SliceString: []string{"hello"},
5998 SliceBytes: [][]byte{{1, 2, 3}},
5999 SliceInt: []int64{-64},
6000 SliceUint: []uint64{+64},
6001 SliceFloat: []float64{3.14159},
6002 },
6003 Slice: []string{"fizz", "buzz"},
6004 Array: [1]string{"goodbye"},
6005 Pointer: new(structStringifiedAll),
6006 }),
6007 }, {
6008 name: jsontest.Name("Structs/Stringified/String"),
6009 inBuf: `{
6010 "Bool": true,
6011 "String": "hello",
6012 "Bytes": "AQID",
6013 "Int": "-64",
6014 "Uint": "64",
6015 "Float": "3.14159",
6016 "Map": {"key": "value"},
6017 "StructScalars": {
6018 "Bool": true,
6019 "String": "hello",
6020 "Bytes": "AQID",
6021 "Int": "-64",
6022 "Uint": "64",
6023 "Float": "3.14159"
6024 },
6025 "StructMaps": {
6026 "MapBool": {"": true},
6027 "MapString": {"": "hello"},
6028 "MapBytes": {"": "AQID"},
6029 "MapInt": {"": "-64"},
6030 "MapUint": {"": "64"},
6031 "MapFloat": {"": "3.14159"}
6032 },
6033 "StructSlices": {
6034 "SliceBool": [true],
6035 "SliceString": ["hello"],
6036 "SliceBytes": ["AQID"],
6037 "SliceInt": ["-64"],
6038 "SliceUint": ["64"],
6039 "SliceFloat": ["3.14159"]
6040 },
6041 "Slice": ["fizz","buzz"],
6042 "Array": ["goodbye"],
6043 "Pointer": {},
6044 "Interface": null
6045 }`,
6046 inVal: new(structStringifiedAll),
6047 want: addr(structStringifiedAll{
6048 Bool: true,
6049 String: "hello",
6050 Bytes: []byte{1, 2, 3},
6051 Int: -64,
6052 Uint: +64,
6053 Float: 3.14159,
6054 Map: map[string]string{"key": "value"},
6055 StructScalars: structScalars{
6056 Bool: true,
6057 String: "hello",
6058 Bytes: []byte{1, 2, 3},
6059 Int: -64,
6060 Uint: +64,
6061 Float: 3.14159,
6062 },
6063 StructMaps: structMaps{
6064 MapBool: map[string]bool{"": true},
6065 MapString: map[string]string{"": "hello"},
6066 MapBytes: map[string][]byte{"": {1, 2, 3}},
6067 MapInt: map[string]int64{"": -64},
6068 MapUint: map[string]uint64{"": +64},
6069 MapFloat: map[string]float64{"": 3.14159},
6070 },
6071 StructSlices: structSlices{
6072 SliceBool: []bool{true},
6073 SliceString: []string{"hello"},
6074 SliceBytes: [][]byte{{1, 2, 3}},
6075 SliceInt: []int64{-64},
6076 SliceUint: []uint64{+64},
6077 SliceFloat: []float64{3.14159},
6078 },
6079 Slice: []string{"fizz", "buzz"},
6080 Array: [1]string{"goodbye"},
6081 Pointer: new(structStringifiedAll),
6082 }),
6083 }, {
6084 name: jsontest.Name("Structs/Stringified/InvalidEmpty"),
6085 inBuf: `{"Int":""}`,
6086 inVal: new(structStringifiedAll),
6087 want: new(structStringifiedAll),
6088 wantErr: EU(strconv.ErrSyntax).withVal(`""`).withPos(`{"Int":`, "/Int").withType('"', T[int64]()),
6089 }, {
6090 name: jsontest.Name("Structs/LegacyStringified"),
6091 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6092 inBuf: `{
6093 "Bool": "true",
6094 "String": "\"hello\"",
6095 "Bytes": "AQID",
6096 "Int": "-64",
6097 "Uint": "64",
6098 "Float": "3.14159",
6099 "Map": {"key": "value"},
6100 "StructScalars": {
6101 "Bool": true,
6102 "String": "hello",
6103 "Bytes": "AQID",
6104 "Int": -64,
6105 "Uint": 64,
6106 "Float": 3.14159
6107 },
6108 "StructMaps": {
6109 "MapBool": {"": true},
6110 "MapString": {"": "hello"},
6111 "MapBytes": {"": "AQID"},
6112 "MapInt": {"": -64},
6113 "MapUint": {"": 64},
6114 "MapFloat": {"": 3.14159}
6115 },
6116 "StructSlices": {
6117 "SliceBool": [true],
6118 "SliceString": ["hello"],
6119 "SliceBytes": ["AQID"],
6120 "SliceInt": [-64],
6121 "SliceUint": [64],
6122 "SliceFloat": [3.14159]
6123 },
6124 "Slice": ["fizz", "buzz"],
6125 "Array": ["goodbye"]
6126 }`,
6127 inVal: new(structStringifiedAll),
6128 want: addr(structStringifiedAll{
6129 Bool: true,
6130 String: "hello",
6131 Bytes: []byte{1, 2, 3},
6132 Int: -64,
6133 Uint: +64,
6134 Float: 3.14159,
6135 Map: map[string]string{"key": "value"},
6136 StructScalars: structScalars{
6137 Bool: true,
6138 String: "hello",
6139 Bytes: []byte{1, 2, 3},
6140 Int: -64,
6141 Uint: +64,
6142 Float: 3.14159,
6143 },
6144 StructMaps: structMaps{
6145 MapBool: map[string]bool{"": true},
6146 MapString: map[string]string{"": "hello"},
6147 MapBytes: map[string][]byte{"": {1, 2, 3}},
6148 MapInt: map[string]int64{"": -64},
6149 MapUint: map[string]uint64{"": +64},
6150 MapFloat: map[string]float64{"": 3.14159},
6151 },
6152 StructSlices: structSlices{
6153 SliceBool: []bool{true},
6154 SliceString: []string{"hello"},
6155 SliceBytes: [][]byte{{1, 2, 3}},
6156 SliceInt: []int64{-64},
6157 SliceUint: []uint64{+64},
6158 SliceFloat: []float64{3.14159},
6159 },
6160 Slice: []string{"fizz", "buzz"},
6161 Array: [1]string{"goodbye"},
6162 }),
6163 }, {
6164 name: jsontest.Name("Structs/LegacyStringified/InvalidBool"),
6165 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6166 inBuf: `{"Bool": true}`,
6167 inVal: new(structStringifiedAll),
6168 wantErr: EU(nil).withPos(`{"Bool": `, "/Bool").withType('t', T[bool]()),
6169 }, {
6170 name: jsontest.Name("Structs/LegacyStringified/InvalidString"),
6171 opts: []Options{jsonflags.StringifyWithLegacySemantics | 1},
6172 inBuf: `{"String": "string"}`,
6173 inVal: new(structStringifiedAll),
6174 wantErr: EU(newInvalidCharacterError("s", "at start of string (expecting '\"')", 0, "")).
6175 withPos(`{"String": `, "/String").withType('"', T[string]()),
6176 }, {
6177 name: jsontest.Name("Structs/Format/Bytes"),
6178 inBuf: `{
6179 "Base16": "0123456789abcdef",
6180 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
6181 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
6182 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
6183 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
6184 "Array": [1, 2, 3, 4]
6185 }`,
6186 inVal: new(structFormatBytes),
6187 want: addr(structFormatBytes{
6188 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
6189 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6190 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
6191 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߿"),
6192 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߿"),
6193 Array: []byte{1, 2, 3, 4},
6194 }),
6195 }, {
6196 name: jsontest.Name("Structs/Format/ArrayBytes"),
6197 inBuf: `{
6198 "Base16": "01020304",
6199 "Base32": "AEBAGBA=",
6200 "Base32Hex": "0410610=",
6201 "Base64": "AQIDBA==",
6202 "Base64URL": "AQIDBA==",
6203 "Array": [1, 2, 3, 4],
6204 "Default": "AQIDBA=="
6205 }`,
6206 inVal: new(structFormatArrayBytes),
6207 want: addr(structFormatArrayBytes{
6208 Base16: [4]byte{1, 2, 3, 4},
6209 Base32: [4]byte{1, 2, 3, 4},
6210 Base32Hex: [4]byte{1, 2, 3, 4},
6211 Base64: [4]byte{1, 2, 3, 4},
6212 Base64URL: [4]byte{1, 2, 3, 4},
6213 Array: [4]byte{1, 2, 3, 4},
6214 Default: [4]byte{1, 2, 3, 4},
6215 }),
6216 }, {
6217 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
6218 opts: []Options{jsonflags.FormatBytesWithLegacySemantics | 1},
6219 inBuf: `{
6220 "Base16": "01020304",
6221 "Base32": "AEBAGBA=",
6222 "Base32Hex": "0410610=",
6223 "Base64": "AQIDBA==",
6224 "Base64URL": "AQIDBA==",
6225 "Array": [1, 2, 3, 4],
6226 "Default": [1, 2, 3, 4]
6227 }`,
6228 inVal: new(structFormatArrayBytes),
6229 want: addr(structFormatArrayBytes{
6230 Base16: [4]byte{1, 2, 3, 4},
6231 Base32: [4]byte{1, 2, 3, 4},
6232 Base32Hex: [4]byte{1, 2, 3, 4},
6233 Base64: [4]byte{1, 2, 3, 4},
6234 Base64URL: [4]byte{1, 2, 3, 4},
6235 Array: [4]byte{1, 2, 3, 4},
6236 Default: [4]byte{1, 2, 3, 4},
6237 }),
6238 }, {
6239 name: jsontest.Name("Structs/Format/Bytes/Array"),
6240 opts: []Options{
6241 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *byte) error {
6242 if string(b) == "true" {
6243 *v = 1
6244 } else {
6245 *v = 0
6246 }
6247 return nil
6248 })),
6249 },
6250 inBuf: `{"Array":[false,true,false,true,false,true]}`,
6251 inVal: new(struct {
6252 Array []byte `json:",format:array"`
6253 }),
6254 want: addr(struct {
6255 Array []byte `json:",format:array"`
6256 }{
6257 Array: []byte{0, 1, 0, 1, 0, 1},
6258 }),
6259 }, {
6260 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/WrongKind"),
6261 inBuf: `{"Base16": [1,2,3,4]}`,
6262 inVal: new(structFormatBytes),
6263 wantErr: EU(nil).withPos(`{"Base16": `, "/Base16").withType('[', T[[]byte]()),
6264 }, {
6265 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/AllPadding"),
6266 inBuf: `{"Base16": "===="}`,
6267 inVal: new(structFormatBytes),
6268 wantErr: EU(func() error {
6269 _, err := hex.Decode(make([]byte, 2), []byte("====="))
6270 return err
6271 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6272 }, {
6273 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/EvenPadding"),
6274 inBuf: `{"Base16": "0123456789abcdef="}`,
6275 inVal: new(structFormatBytes),
6276 wantErr: EU(func() error {
6277 _, err := hex.Decode(make([]byte, 8), []byte("0123456789abcdef="))
6278 return err
6279 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6280 }, {
6281 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/OddPadding"),
6282 inBuf: `{"Base16": "0123456789abcdef0="}`,
6283 inVal: new(structFormatBytes),
6284 wantErr: EU(func() error {
6285 _, err := hex.Decode(make([]byte, 9), []byte("0123456789abcdef0="))
6286 return err
6287 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6288 }, {
6289 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/LineFeed"),
6290 inBuf: `{"Base16": "aa\naa"}`,
6291 inVal: new(structFormatBytes),
6292 wantErr: EU(func() error {
6293 _, err := hex.Decode(make([]byte, 9), []byte("aa\naa"))
6294 return err
6295 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6296 }, {
6297 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/CarriageReturn"),
6298 inBuf: `{"Base16": "aa\raa"}`,
6299 inVal: new(structFormatBytes),
6300 wantErr: EU(func() error {
6301 _, err := hex.Decode(make([]byte, 9), []byte("aa\raa"))
6302 return err
6303 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6304 }, {
6305 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base16/NonAlphabet/Space"),
6306 inBuf: `{"Base16": "aa aa"}`,
6307 inVal: new(structFormatBytes),
6308 wantErr: EU(func() error {
6309 _, err := hex.Decode(make([]byte, 9), []byte("aa aa"))
6310 return err
6311 }()).withPos(`{"Base16": `, "/Base16").withType('"', T[[]byte]()),
6312 }, {
6313 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Padding"),
6314 inBuf: `[
6315 {"Base32": "NA======"},
6316 {"Base32": "NBSQ===="},
6317 {"Base32": "NBSWY==="},
6318 {"Base32": "NBSWY3A="},
6319 {"Base32": "NBSWY3DP"}
6320 ]`,
6321 inVal: new([]structFormatBytes),
6322 want: addr([]structFormatBytes{
6323 {Base32: []byte("h")},
6324 {Base32: []byte("he")},
6325 {Base32: []byte("hel")},
6326 {Base32: []byte("hell")},
6327 {Base32: []byte("hello")},
6328 }),
6329 }, {
6330 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/Invalid/NoPadding"),
6331 inBuf: `[
6332 {"Base32": "NA"},
6333 {"Base32": "NBSQ"},
6334 {"Base32": "NBSWY"},
6335 {"Base32": "NBSWY3A"},
6336 {"Base32": "NBSWY3DP"}
6337 ]`,
6338 inVal: new([]structFormatBytes),
6339 wantErr: EU(func() error {
6340 _, err := base32.StdEncoding.Decode(make([]byte, 1), []byte("NA"))
6341 return err
6342 }()).withPos(`[`+"\n\t\t\t\t"+`{"Base32": `, "/0/Base32").withType('"', T[[]byte]()),
6343 }, {
6344 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/WrongAlphabet"),
6345 inBuf: `{"Base32": "0123456789ABCDEFGHIJKLMNOPQRSTUV"}`,
6346 inVal: new(structFormatBytes),
6347 wantErr: EU(func() error {
6348 _, err := base32.StdEncoding.Decode(make([]byte, 20), []byte("0123456789ABCDEFGHIJKLMNOPQRSTUV"))
6349 return err
6350 }()).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6351 }, {
6352 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32Hex/WrongAlphabet"),
6353 inBuf: `{"Base32Hex": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"}`,
6354 inVal: new(structFormatBytes),
6355 wantErr: EU(func() error {
6356 _, err := base32.HexEncoding.Decode(make([]byte, 20), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"))
6357 return err
6358 }()).withPos(`{"Base32Hex": `, "/Base32Hex").withType('"', T[[]byte]()),
6359 }, {
6360 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/LineFeed"),
6361 inBuf: `{"Base32": "AAAA\nAAAA"}`,
6362 inVal: new(structFormatBytes),
6363 wantErr: EU(errors.New("illegal character '\\n' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6364 }, {
6365 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/CarriageReturn"),
6366 inBuf: `{"Base32": "AAAA\rAAAA"}`,
6367 inVal: new(structFormatBytes),
6368 wantErr: EU(errors.New("illegal character '\\r' at offset 4")).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6369 }, {
6370 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base32/NonAlphabet/Space"),
6371 inBuf: `{"Base32": "AAAA AAAA"}`,
6372 inVal: new(structFormatBytes),
6373 wantErr: EU(base32.CorruptInputError(4)).withPos(`{"Base32": `, "/Base32").withType('"', T[[]byte]()),
6374 }, {
6375 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/WrongAlphabet"),
6376 inBuf: `{"Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"}`,
6377 inVal: new(structFormatBytes),
6378 wantErr: EU(func() error {
6379 _, err := base64.StdEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"))
6380 return err
6381 }()).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6382 }, {
6383 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64URL/WrongAlphabet"),
6384 inBuf: `{"Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}`,
6385 inVal: new(structFormatBytes),
6386 wantErr: EU(func() error {
6387 _, err := base64.URLEncoding.Decode(make([]byte, 48), []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
6388 return err
6389 }()).withPos(`{"Base64URL": `, "/Base64URL").withType('"', T[[]byte]()),
6390 }, {
6391 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/LineFeed"),
6392 inBuf: `{"Base64": "aa=\n="}`,
6393 inVal: new(structFormatBytes),
6394 wantErr: EU(errors.New("illegal character '\\n' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6395 }, {
6396 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/CarriageReturn"),
6397 inBuf: `{"Base64": "aa=\r="}`,
6398 inVal: new(structFormatBytes),
6399 wantErr: EU(errors.New("illegal character '\\r' at offset 3")).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6400 }, {
6401 name: jsontest.Name("Structs/Format/Bytes/Base64/NonAlphabet/Ignored"),
6402 opts: []Options{jsonflags.FormatBytesWithLegacySemantics | 1},
6403 inBuf: `{"Base64": "aa=\r\n="}`,
6404 inVal: new(structFormatBytes),
6405 want: &structFormatBytes{Base64: []byte{105}},
6406 }, {
6407 name: jsontest.Name("Structs/Format/Bytes/Invalid/Base64/NonAlphabet/Space"),
6408 inBuf: `{"Base64": "aa= ="}`,
6409 inVal: new(structFormatBytes),
6410 wantErr: EU(base64.CorruptInputError(2)).withPos(`{"Base64": `, "/Base64").withType('"', T[[]byte]()),
6411 }, {
6412 name: jsontest.Name("Structs/Format/Floats"),
6413 inBuf: `[
6414 {"NonFinite": 3.141592653589793, "PointerNonFinite": 3.141592653589793},
6415 {"NonFinite": "-Infinity", "PointerNonFinite": "-Infinity"},
6416 {"NonFinite": "Infinity", "PointerNonFinite": "Infinity"}
6417 ]`,
6418 inVal: new([]structFormatFloats),
6419 want: addr([]structFormatFloats{
6420 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
6421 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
6422 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
6423 }),
6424 }, {
6425 name: jsontest.Name("Structs/Format/Floats/NaN"),
6426 inBuf: `{"NonFinite": "NaN"}`,
6427 inVal: new(structFormatFloats),
6428
6429 }, {
6430 name: jsontest.Name("Structs/Format/Floats/Invalid/NaN"),
6431 inBuf: `{"NonFinite": "nan"}`,
6432 inVal: new(structFormatFloats),
6433 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6434 }, {
6435 name: jsontest.Name("Structs/Format/Floats/Invalid/PositiveInfinity"),
6436 inBuf: `{"NonFinite": "+Infinity"}`,
6437 inVal: new(structFormatFloats),
6438 wantErr: EU(nil).withPos(`{"NonFinite": `, "/NonFinite").withType('"', T[float64]()),
6439 }, {
6440 name: jsontest.Name("Structs/Format/Floats/Invalid/NegativeInfinitySpace"),
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/Maps"),
6446 inBuf: `[
6447 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6448 {"EmitNull": {}, "PointerEmitNull": {}, "EmitEmpty": {}, "PointerEmitEmpty": {}, "EmitDefault": {}, "PointerEmitDefault": {}},
6449 {"EmitNull": {"k": "v"}, "PointerEmitNull": {"k": "v"}, "EmitEmpty": {"k": "v"}, "PointerEmitEmpty": {"k": "v"}, "EmitDefault": {"k": "v"}, "PointerEmitDefault": {"k": "v"}}
6450 ]`,
6451 inVal: new([]structFormatMaps),
6452 want: addr([]structFormatMaps{{
6453 EmitNull: map[string]string(nil), PointerEmitNull: (*map[string]string)(nil),
6454 EmitEmpty: map[string]string(nil), PointerEmitEmpty: (*map[string]string)(nil),
6455 EmitDefault: map[string]string(nil), PointerEmitDefault: (*map[string]string)(nil),
6456 }, {
6457 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
6458 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
6459 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
6460 }, {
6461 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
6462 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
6463 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
6464 }}),
6465 }, {
6466 name: jsontest.Name("Structs/Format/Slices"),
6467 inBuf: `[
6468 {"EmitNull": null, "PointerEmitNull": null, "EmitEmpty": null, "PointerEmitEmpty": null, "EmitDefault": null, "PointerEmitDefault": null},
6469 {"EmitNull": [], "PointerEmitNull": [], "EmitEmpty": [], "PointerEmitEmpty": [], "EmitDefault": [], "PointerEmitDefault": []},
6470 {"EmitNull": ["v"], "PointerEmitNull": ["v"], "EmitEmpty": ["v"], "PointerEmitEmpty": ["v"], "EmitDefault": ["v"], "PointerEmitDefault": ["v"]}
6471 ]`,
6472 inVal: new([]structFormatSlices),
6473 want: addr([]structFormatSlices{{
6474 EmitNull: []string(nil), PointerEmitNull: (*[]string)(nil),
6475 EmitEmpty: []string(nil), PointerEmitEmpty: (*[]string)(nil),
6476 EmitDefault: []string(nil), PointerEmitDefault: (*[]string)(nil),
6477 }, {
6478 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
6479 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
6480 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
6481 }, {
6482 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
6483 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
6484 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
6485 }}),
6486 }, {
6487 name: jsontest.Name("Structs/Format/Invalid/Bool"),
6488 inBuf: `{"Bool":true}`,
6489 inVal: new(structFormatInvalid),
6490 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, T[bool]()),
6491 }, {
6492 name: jsontest.Name("Structs/Format/Invalid/String"),
6493 inBuf: `{"String": "string"}`,
6494 inVal: new(structFormatInvalid),
6495 wantErr: EU(errInvalidFormatFlag).withPos(`{"String": `, "/String").withType(0, T[string]()),
6496 }, {
6497 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
6498 inBuf: `{"Bytes": "bytes"}`,
6499 inVal: new(structFormatInvalid),
6500 wantErr: EU(errInvalidFormatFlag).withPos(`{"Bytes": `, "/Bytes").withType(0, T[[]byte]()),
6501 }, {
6502 name: jsontest.Name("Structs/Format/Invalid/Int"),
6503 inBuf: `{"Int": 1}`,
6504 inVal: new(structFormatInvalid),
6505 wantErr: EU(errInvalidFormatFlag).withPos(`{"Int": `, "/Int").withType(0, T[int64]()),
6506 }, {
6507 name: jsontest.Name("Structs/Format/Invalid/Uint"),
6508 inBuf: `{"Uint": 1}`,
6509 inVal: new(structFormatInvalid),
6510 wantErr: EU(errInvalidFormatFlag).withPos(`{"Uint": `, "/Uint").withType(0, T[uint64]()),
6511 }, {
6512 name: jsontest.Name("Structs/Format/Invalid/Float"),
6513 inBuf: `{"Float" : 1}`,
6514 inVal: new(structFormatInvalid),
6515 wantErr: EU(errInvalidFormatFlag).withPos(`{"Float" : `, "/Float").withType(0, T[float64]()),
6516 }, {
6517 name: jsontest.Name("Structs/Format/Invalid/Map"),
6518 inBuf: `{"Map":{}}`,
6519 inVal: new(structFormatInvalid),
6520 wantErr: EU(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
6521 }, {
6522 name: jsontest.Name("Structs/Format/Invalid/Struct"),
6523 inBuf: `{"Struct": {}}`,
6524 inVal: new(structFormatInvalid),
6525 wantErr: EU(errInvalidFormatFlag).withPos(`{"Struct": `, "/Struct").withType(0, T[structAll]()),
6526 }, {
6527 name: jsontest.Name("Structs/Format/Invalid/Slice"),
6528 inBuf: `{"Slice": {}}`,
6529 inVal: new(structFormatInvalid),
6530 wantErr: EU(errInvalidFormatFlag).withPos(`{"Slice": `, "/Slice").withType(0, T[[]string]()),
6531 }, {
6532 name: jsontest.Name("Structs/Format/Invalid/Array"),
6533 inBuf: `{"Array": []}`,
6534 inVal: new(structFormatInvalid),
6535 wantErr: EU(errInvalidFormatFlag).withPos(`{"Array": `, "/Array").withType(0, T[[1]string]()),
6536 }, {
6537 name: jsontest.Name("Structs/Format/Invalid/Interface"),
6538 inBuf: `{"Interface": "anything"}`,
6539 inVal: new(structFormatInvalid),
6540 wantErr: EU(errInvalidFormatFlag).withPos(`{"Interface": `, "/Interface").withType(0, T[any]()),
6541 }, {
6542 name: jsontest.Name("Structs/Inline/Zero"),
6543 inBuf: `{"D":""}`,
6544 inVal: new(structInlined),
6545 want: new(structInlined),
6546 }, {
6547 name: jsontest.Name("Structs/Inline/Alloc"),
6548 inBuf: `{"E":"","F":"","G":"","A":"","B":"","D":""}`,
6549 inVal: new(structInlined),
6550 want: addr(structInlined{
6551 X: structInlinedL1{
6552 X: &structInlinedL2{},
6553 StructEmbed1: StructEmbed1{},
6554 },
6555 StructEmbed2: &StructEmbed2{},
6556 }),
6557 }, {
6558 name: jsontest.Name("Structs/Inline/NonZero"),
6559 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6560 inVal: new(structInlined),
6561 want: addr(structInlined{
6562 X: structInlinedL1{
6563 X: &structInlinedL2{A: "A1", B: "B1" },
6564 StructEmbed1: StructEmbed1{ D: "D2" },
6565 },
6566 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6567 }),
6568 }, {
6569 name: jsontest.Name("Structs/Inline/Merge"),
6570 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
6571 inVal: addr(structInlined{
6572 X: structInlinedL1{
6573 X: &structInlinedL2{B: "##", C: "C1"},
6574 StructEmbed1: StructEmbed1{C: "C2", E: "E2"},
6575 },
6576 StructEmbed2: &StructEmbed2{E: "##", G: "G3"},
6577 }),
6578 want: addr(structInlined{
6579 X: structInlinedL1{
6580 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
6581 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
6582 },
6583 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
6584 }),
6585 }, {
6586 name: jsontest.Name("Structs/InlinedFallback/TextValue/Noop"),
6587 inBuf: `{"A":1,"B":2}`,
6588 inVal: new(structInlineTextValue),
6589 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(nil), B: 2}),
6590 }, {
6591 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Nil"),
6592 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6593 inVal: new(structInlineTextValue),
6594 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6595 }, {
6596 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Empty"),
6597 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6598 inVal: addr(structInlineTextValue{X: jsontext.Value{}}),
6599 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6600 }, {
6601 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Whitespace"),
6602 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6603 inVal: addr(structInlineTextValue{X: jsontext.Value("\n\r\t ")}),
6604 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("")}),
6605 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6606 }, {
6607 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/Null"),
6608 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6609 inVal: addr(structInlineTextValue{X: jsontext.Value("null")}),
6610 want: addr(structInlineTextValue{A: 1, X: jsontext.Value("null")}),
6611 wantErr: EU(errRawInlinedNotObject).withPos(`{"A":1,`, "/fizz").withType('"', T[jsontext.Value]()),
6612 }, {
6613 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN1/ObjectN0"),
6614 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6615 inVal: addr(structInlineTextValue{X: jsontext.Value(` { } `)}),
6616 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` {"fizz":"buzz"}`), B: 2}),
6617 }, {
6618 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeN2/ObjectN1"),
6619 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6620 inVal: addr(structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)}),
6621 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(` { "fizz" : "buzz","fizz":"buzz","foo":[ 1 , 2 , 3 ]}`), B: 2}),
6622 }, {
6623 name: jsontest.Name("Structs/InlinedFallback/TextValue/Merge/EndObject"),
6624 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6625 inVal: addr(structInlineTextValue{X: jsontext.Value(` } `)}),
6626
6627
6628 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`,"fizz":"buzz"}`), B: 2}),
6629 }, {
6630 name: jsontest.Name("Structs/InlinedFallback/TextValue/MergeInvalidValue"),
6631 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6632 inVal: new(structInlineTextValue),
6633 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":`)}),
6634 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6635 }, {
6636 name: jsontest.Name("Structs/InlinedFallback/TextValue/CaseSensitive"),
6637 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6638 inVal: new(structInlineTextValue),
6639 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","a":3}`), B: 2}),
6640 }, {
6641 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
6642 opts: []Options{jsontext.AllowDuplicateNames(false)},
6643 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6644 inVal: new(structInlineTextValue),
6645 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`), B: 2}),
6646 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6647 }, {
6648 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
6649 opts: []Options{jsontext.AllowDuplicateNames(true)},
6650 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6651 inVal: new(structInlineTextValue),
6652 want: addr(structInlineTextValue{A: 1, X: jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`), B: 2}),
6653 }, {
6654 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Noop"),
6655 inBuf: `{}`,
6656 inVal: new(structInlinePointerInlineTextValue),
6657 want: new(structInlinePointerInlineTextValue),
6658 }, {
6659 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Alloc"),
6660 inBuf: `{"A":1,"fizz":"buzz"}`,
6661 inVal: new(structInlinePointerInlineTextValue),
6662 want: addr(structInlinePointerInlineTextValue{
6663 X: &struct {
6664 A int
6665 X jsontext.Value `json:",inline"`
6666 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6667 }),
6668 }, {
6669 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Merge"),
6670 inBuf: `{"fizz":"buzz"}`,
6671 inVal: addr(structInlinePointerInlineTextValue{
6672 X: &struct {
6673 A int
6674 X jsontext.Value `json:",inline"`
6675 }{A: 1},
6676 }),
6677 want: addr(structInlinePointerInlineTextValue{
6678 X: &struct {
6679 A int
6680 X jsontext.Value `json:",inline"`
6681 }{A: 1, X: jsontext.Value(`{"fizz":"buzz"}`)},
6682 }),
6683 }, {
6684 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Noop"),
6685 inBuf: `{"A":1,"B":2}`,
6686 inVal: new(structInlinePointerTextValue),
6687 want: addr(structInlinePointerTextValue{A: 1, X: nil, B: 2}),
6688 }, {
6689 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Alloc"),
6690 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6691 inVal: new(structInlinePointerTextValue),
6692 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz"}`)), B: 2}),
6693 }, {
6694 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Merge"),
6695 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6696 inVal: addr(structInlinePointerTextValue{X: addr(jsontext.Value(`{"fizz":"buzz"}`))}),
6697 want: addr(structInlinePointerTextValue{A: 1, X: addr(jsontext.Value(`{"fizz":"buzz","fizz":"buzz"}`)), B: 2}),
6698 }, {
6699 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
6700 inBuf: `{"fizz":"buzz"}`,
6701 inVal: new(structInlineInlinePointerTextValue),
6702 want: addr(structInlineInlinePointerTextValue{
6703 X: struct {
6704 X *jsontext.Value `json:",inline"`
6705 }{X: addr(jsontext.Value(`{"fizz":"buzz"}`))},
6706 }),
6707 }, {
6708 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Noop"),
6709 inBuf: `{"A":1,"B":2}`,
6710 inVal: new(structInlineMapStringAny),
6711 want: addr(structInlineMapStringAny{A: 1, X: nil, B: 2}),
6712 }, {
6713 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Nil"),
6714 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6715 inVal: new(structInlineMapStringAny),
6716 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6717 }, {
6718 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/Empty"),
6719 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6720 inVal: addr(structInlineMapStringAny{X: jsonObject{}}),
6721 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6722 }, {
6723 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN1/ObjectN1"),
6724 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6725 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": jsonObject{
6726 "alpha": "bravo",
6727 "charlie": "delta",
6728 }}}),
6729 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{
6730 "alpha": "bravo",
6731 "charlie": "DELTA",
6732 "echo": "foxtrot",
6733 }}, B: 2}),
6734 }, {
6735 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeN2/ObjectN1"),
6736 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6737 inVal: addr(structInlineMapStringAny{X: jsonObject{"fizz": "wuzz"}}),
6738 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6739 }, {
6740 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue"),
6741 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6742 inVal: new(structInlineMapStringAny),
6743 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": nil}}),
6744 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6745 }, {
6746 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MergeInvalidValue/Existing"),
6747 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6748 inVal: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6749 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": true}}),
6750 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6751 }, {
6752 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/CaseSensitive"),
6753 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6754 inVal: new(structInlineMapStringAny),
6755 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz", "a": 3.0}, B: 2}),
6756 }, {
6757 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectDuplicateNames"),
6758 opts: []Options{jsontext.AllowDuplicateNames(false)},
6759 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6760 inVal: new(structInlineMapStringAny),
6761 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": "buzz"}, B: 2}),
6762 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6763 }, {
6764 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowDuplicateNames"),
6765 opts: []Options{jsontext.AllowDuplicateNames(true)},
6766 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
6767 inVal: new(structInlineMapStringAny),
6768 want: addr(structInlineMapStringAny{A: 1, X: jsonObject{"fizz": jsonObject{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
6769 }, {
6770 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Noop"),
6771 inBuf: `{}`,
6772 inVal: new(structInlinePointerInlineMapStringAny),
6773 want: new(structInlinePointerInlineMapStringAny),
6774 }, {
6775 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Alloc"),
6776 inBuf: `{"A":1,"fizz":"buzz"}`,
6777 inVal: new(structInlinePointerInlineMapStringAny),
6778 want: addr(structInlinePointerInlineMapStringAny{
6779 X: &struct {
6780 A int
6781 X jsonObject `json:",inline"`
6782 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6783 }),
6784 }, {
6785 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Merge"),
6786 inBuf: `{"fizz":"buzz"}`,
6787 inVal: addr(structInlinePointerInlineMapStringAny{
6788 X: &struct {
6789 A int
6790 X jsonObject `json:",inline"`
6791 }{A: 1},
6792 }),
6793 want: addr(structInlinePointerInlineMapStringAny{
6794 X: &struct {
6795 A int
6796 X jsonObject `json:",inline"`
6797 }{A: 1, X: jsonObject{"fizz": "buzz"}},
6798 }),
6799 }, {
6800 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6801 opts: []Options{
6802 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
6803 var err error
6804 *v, err = strconv.ParseFloat(string(bytes.Trim(b, `"`)), 64)
6805 return err
6806 })),
6807 },
6808 inBuf: `{"D":"1.1","E":"2.2","F":"3.3"}`,
6809 inVal: new(structInlineMapStringAny),
6810 want: addr(structInlineMapStringAny{X: jsonObject{"D": 1.1, "E": 2.2, "F": 3.3}}),
6811 }, {
6812 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Noop"),
6813 inBuf: `{"A":1,"B":2}`,
6814 inVal: new(structInlinePointerMapStringAny),
6815 want: addr(structInlinePointerMapStringAny{A: 1, X: nil, B: 2}),
6816 }, {
6817 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Alloc"),
6818 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6819 inVal: new(structInlinePointerMapStringAny),
6820 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "buzz"}), B: 2}),
6821 }, {
6822 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Merge"),
6823 inBuf: `{"A":1,"fizz":"wuzz","B":2}`,
6824 inVal: addr(structInlinePointerMapStringAny{X: addr(jsonObject{"fizz": "buzz"})}),
6825 want: addr(structInlinePointerMapStringAny{A: 1, X: addr(jsonObject{"fizz": "wuzz"}), B: 2}),
6826 }, {
6827 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
6828 inBuf: `{"fizz":"buzz"}`,
6829 inVal: new(structInlineInlinePointerMapStringAny),
6830 want: addr(structInlineInlinePointerMapStringAny{
6831 X: struct {
6832 X *jsonObject `json:",inline"`
6833 }{X: addr(jsonObject{"fizz": "buzz"})},
6834 }),
6835 }, {
6836 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
6837 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6838 inVal: new(structInlineMapStringInt),
6839 want: addr(structInlineMapStringInt{
6840 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6841 }),
6842 }, {
6843 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Null"),
6844 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6845 inVal: new(structInlineMapStringInt),
6846 want: addr(structInlineMapStringInt{
6847 X: map[string]int{"zero": 0, "one": 0, "two": 2},
6848 }),
6849 }, {
6850 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Invalid"),
6851 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6852 inVal: new(structInlineMapStringInt),
6853 want: addr(structInlineMapStringInt{
6854 X: map[string]int{"zero": 0, "one": 0},
6855 }),
6856 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6857 }, {
6858 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
6859 opts: []Options{StringifyNumbers(true)},
6860 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6861 inVal: new(structInlineMapStringInt),
6862 want: addr(structInlineMapStringInt{
6863 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6864 }),
6865 }, {
6866 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/UnmarshalFunc"),
6867 opts: []Options{
6868 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6869 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6870 if err != nil {
6871 return err
6872 }
6873 *v = int(i)
6874 return nil
6875 })),
6876 },
6877 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6878 inVal: new(structInlineMapStringInt),
6879 want: addr(structInlineMapStringInt{
6880 X: map[string]int{"zero": 0, "one": 1, "two": 2},
6881 }),
6882 }, {
6883 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
6884 inBuf: `{"zero": 0, "one": 1, "two": 2}`,
6885 inVal: new(structInlineMapNamedStringInt),
6886 want: addr(structInlineMapNamedStringInt{
6887 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6888 }),
6889 }, {
6890 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Null"),
6891 inBuf: `{"zero": 0, "one": null, "two": 2}`,
6892 inVal: new(structInlineMapNamedStringInt),
6893 want: addr(structInlineMapNamedStringInt{
6894 X: map[namedString]int{"zero": 0, "one": 0, "two": 2},
6895 }),
6896 }, {
6897 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Invalid"),
6898 inBuf: `{"zero": 0, "one": {}, "two": 2}`,
6899 inVal: new(structInlineMapNamedStringInt),
6900 want: addr(structInlineMapNamedStringInt{
6901 X: map[namedString]int{"zero": 0, "one": 0},
6902 }),
6903 wantErr: EU(nil).withPos(`{"zero": 0, "one": `, "/one").withType('{', T[int]()),
6904 }, {
6905 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/StringifiedNumbers"),
6906 opts: []Options{StringifyNumbers(true)},
6907 inBuf: `{"zero": "0", "one": 1, "two": "2"}`,
6908 inVal: new(structInlineMapNamedStringInt),
6909 want: addr(structInlineMapNamedStringInt{
6910 X: map[namedString]int{"zero": 0, "one": 0},
6911 }),
6912 wantErr: EU(nil).withPos(`{"zero": "0", "one": `, "/one").withType('0', T[int]()),
6913 }, {
6914 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/UnmarshalFunc"),
6915 opts: []Options{
6916 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *int) error {
6917 i, err := strconv.ParseInt(string(bytes.Trim(b, `"`)), 10, 64)
6918 if err != nil {
6919 return err
6920 }
6921 *v = int(i)
6922 return nil
6923 })),
6924 },
6925 inBuf: `{"zero": "0", "one": "1", "two": "2"}`,
6926 inVal: new(structInlineMapNamedStringInt),
6927 want: addr(structInlineMapNamedStringInt{
6928 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
6929 }),
6930 }, {
6931 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Noop"),
6932 inBuf: `{"A":1,"B":2}`,
6933 inVal: new(structInlineMapNamedStringAny),
6934 want: addr(structInlineMapNamedStringAny{A: 1, X: nil, B: 2}),
6935 }, {
6936 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Nil"),
6937 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6938 inVal: new(structInlineMapNamedStringAny),
6939 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6940 }, {
6941 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/Empty"),
6942 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6943 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{}}),
6944 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6945 }, {
6946 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN1/ObjectN1"),
6947 inBuf: `{"A":1,"fizz":{"charlie":"DELTA","echo":"foxtrot"},"B":2}`,
6948 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": jsonObject{
6949 "alpha": "bravo",
6950 "charlie": "delta",
6951 }}}),
6952 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": jsonObject{
6953 "alpha": "bravo",
6954 "charlie": "DELTA",
6955 "echo": "foxtrot",
6956 }}, B: 2}),
6957 }, {
6958 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeN2/ObjectN1"),
6959 inBuf: `{"A":1,"fizz":"buzz","B":2,"foo": [ 1 , 2 , 3 ]}`,
6960 inVal: addr(structInlineMapNamedStringAny{X: map[namedString]any{"fizz": "wuzz"}}),
6961 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "foo": jsonArray{1.0, 2.0, 3.0}}, B: 2}),
6962 }, {
6963 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue"),
6964 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6965 inVal: new(structInlineMapNamedStringAny),
6966 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": nil}}),
6967 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6968 }, {
6969 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MergeInvalidValue/Existing"),
6970 inBuf: `{"A":1,"fizz":nil,"B":2}`,
6971 inVal: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
6972 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": true}}),
6973 wantErr: newInvalidCharacterError("i", "in literal null (expecting 'u')", len64(`{"A":1,"fizz":n`), "/fizz"),
6974 }, {
6975 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/CaseSensitive"),
6976 inBuf: `{"A":1,"fizz":"buzz","B":2,"a":3}`,
6977 inVal: new(structInlineMapNamedStringAny),
6978 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz", "a": 3.0}, B: 2}),
6979 }, {
6980 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectDuplicateNames"),
6981 opts: []Options{jsontext.AllowDuplicateNames(false)},
6982 inBuf: `{"A":1,"fizz":"buzz","B":2,"fizz":"buzz"}`,
6983 inVal: new(structInlineMapNamedStringAny),
6984 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": "buzz"}, B: 2}),
6985 wantErr: newDuplicateNameError("", []byte(`"fizz"`), len64(`{"A":1,"fizz":"buzz","B":2,`)),
6986 }, {
6987 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowDuplicateNames"),
6988 opts: []Options{jsontext.AllowDuplicateNames(true)},
6989 inBuf: `{"A":1,"fizz":{"one":1,"two":-2},"B":2,"fizz":{"two":2,"three":3}}`,
6990 inVal: new(structInlineMapNamedStringAny),
6991 want: addr(structInlineMapNamedStringAny{A: 1, X: map[namedString]any{"fizz": map[string]any{"one": 1.0, "two": 2.0, "three": 3.0}}, B: 2}),
6992 }, {
6993 name: jsontest.Name("Structs/InlinedFallback/RejectUnknownMembers"),
6994 opts: []Options{RejectUnknownMembers(true)},
6995 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
6996 inVal: new(structInlineTextValue),
6997
6998 want: addr(structInlineTextValue{
6999 A: 1,
7000 X: jsontext.Value(`{"fizz":"buzz"}`),
7001 B: 2,
7002 }),
7003 }, {
7004 name: jsontest.Name("Structs/UnknownFallback/RejectUnknownMembers"),
7005 opts: []Options{RejectUnknownMembers(true)},
7006 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7007 inVal: new(structUnknownTextValue),
7008 want: addr(structUnknownTextValue{A: 1}),
7009 wantErr: EU(ErrUnknownName).withPos(`{"A":1,`, "/fizz").withType('"', T[structUnknownTextValue]()),
7010 }, {
7011 name: jsontest.Name("Structs/UnknownFallback"),
7012 inBuf: `{"A":1,"fizz":"buzz","B":2}`,
7013 inVal: new(structUnknownTextValue),
7014 want: addr(structUnknownTextValue{
7015 A: 1,
7016 X: jsontext.Value(`{"fizz":"buzz"}`),
7017 B: 2,
7018 }),
7019 }, {
7020 name: jsontest.Name("Structs/UnknownIgnored"),
7021 opts: []Options{RejectUnknownMembers(false)},
7022 inBuf: `{"unknown":"fizzbuzz"}`,
7023 inVal: new(structAll),
7024 want: new(structAll),
7025 }, {
7026 name: jsontest.Name("Structs/RejectUnknownMembers"),
7027 opts: []Options{RejectUnknownMembers(true)},
7028 inBuf: `{"unknown":"fizzbuzz"}`,
7029 inVal: new(structAll),
7030 want: new(structAll),
7031 wantErr: EU(ErrUnknownName).withPos(`{`, "/unknown").withType('"', T[structAll]()),
7032 }, {
7033 name: jsontest.Name("Structs/UnexportedIgnored"),
7034 inBuf: `{"ignored":"unused"}`,
7035 inVal: new(structUnexportedIgnored),
7036 want: new(structUnexportedIgnored),
7037 }, {
7038 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
7039 inBuf: `{"namedString":"unused"}`,
7040 inVal: new(structIgnoredUnexportedEmbedded),
7041 want: new(structIgnoredUnexportedEmbedded),
7042 }, {
7043 name: jsontest.Name("Structs/WeirdNames"),
7044 inBuf: `{"":"empty",",":"comma","\"":"quote"}`,
7045 inVal: new(structWeirdNames),
7046 want: addr(structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"}),
7047 }, {
7048 name: jsontest.Name("Structs/NoCase/Exact"),
7049 inBuf: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
7050 inVal: new(structNoCase),
7051 want: addr(structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"}),
7052 }, {
7053 name: jsontest.Name("Structs/NoCase/CaseInsensitiveDefault"),
7054 inBuf: `{"aa_a":"aa_a"}`,
7055 inVal: new(structNoCase),
7056 want: addr(structNoCase{AaA: "aa_a"}),
7057 }, {
7058 name: jsontest.Name("Structs/NoCase/MatchCaseSensitiveDelimiter"),
7059 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
7060 inBuf: `{"aa_a":"aa_a"}`,
7061 inVal: new(structNoCase),
7062 want: addr(structNoCase{}),
7063 }, {
7064 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
7065 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
7066 inBuf: `{"aa_a":"aa_a"}`,
7067 inVal: new(structNoCase),
7068 want: addr(structNoCase{AA_A: "aa_a"}),
7069 }, {
7070 name: jsontest.Name("Structs/NoCase/Merge/AllowDuplicateNames"),
7071 opts: []Options{jsontext.AllowDuplicateNames(true)},
7072 inBuf: `{"AaA":"AaA","aaa":"aaa","aAa":"aAa"}`,
7073 inVal: new(structNoCase),
7074 want: addr(structNoCase{AaA: "aAa"}),
7075 }, {
7076 name: jsontest.Name("Structs/NoCase/Merge/RejectDuplicateNames"),
7077 opts: []Options{jsontext.AllowDuplicateNames(false)},
7078 inBuf: `{"AaA":"AaA","aaa":"aaa"}`,
7079 inVal: new(structNoCase),
7080 want: addr(structNoCase{AaA: "AaA"}),
7081 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AaA":"AaA",`)),
7082 }, {
7083 name: jsontest.Name("Structs/CaseSensitive"),
7084 inBuf: `{"BOOL": true, "STRING": "hello", "BYTES": "AQID", "INT": -64, "UINT": 64, "FLOAT": 3.14159}`,
7085 inVal: new(structScalars),
7086 want: addr(structScalars{}),
7087 }, {
7088 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactDifferent"),
7089 inBuf: `{"AAA":"AAA","AaA":"AaA","AAa":"AAa","Aaa":"Aaa"}`,
7090 inVal: addr(structNoCaseInlineTextValue{}),
7091 want: addr(structNoCaseInlineTextValue{AAA: "AAA", AaA: "AaA", AAa: "AAa", Aaa: "Aaa"}),
7092 }, {
7093 name: jsontest.Name("Structs/DuplicateName/NoCase/ExactConflict"),
7094 inBuf: `{"AAA":"AAA","AAA":"AAA"}`,
7095 inVal: addr(structNoCaseInlineTextValue{}),
7096 want: addr(structNoCaseInlineTextValue{AAA: "AAA"}),
7097 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"AAA",`)),
7098 }, {
7099 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteExact"),
7100 inBuf: `{"AAA":"after"}`,
7101 inVal: addr(structNoCaseInlineTextValue{AAA: "before"}),
7102 want: addr(structNoCaseInlineTextValue{AAA: "after"}),
7103 }, {
7104 name: jsontest.Name("Structs/DuplicateName/NoCase/NoCaseConflict"),
7105 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7106 inVal: addr(structNoCaseInlineTextValue{}),
7107 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7108 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7109 }, {
7110 name: jsontest.Name("Structs/DuplicateName/NoCase/OverwriteNoCase"),
7111 inBuf: `{"aaa":"aaa","aaA":"aaA"}`,
7112 inVal: addr(structNoCaseInlineTextValue{}),
7113 want: addr(structNoCaseInlineTextValue{AaA: "aaa"}),
7114 wantErr: newDuplicateNameError("", []byte(`"aaA"`), len64(`{"aaa":"aaa",`)),
7115 }, {
7116 name: jsontest.Name("Structs/DuplicateName/Inline/Unknown"),
7117 inBuf: `{"unknown":""}`,
7118 inVal: addr(structNoCaseInlineTextValue{}),
7119 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7120 }, {
7121 name: jsontest.Name("Structs/DuplicateName/Inline/UnknownMerge"),
7122 inBuf: `{"unknown":""}`,
7123 inVal: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":""}`)}),
7124 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"unknown":"","unknown":""}`)}),
7125 }, {
7126 name: jsontest.Name("Structs/DuplicateName/Inline/NoCaseOkay"),
7127 inBuf: `{"b":"","B":""}`,
7128 inVal: addr(structNoCaseInlineTextValue{}),
7129 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":"","B":""}`)}),
7130 }, {
7131 name: jsontest.Name("Structs/DuplicateName/Inline/ExactConflict"),
7132 inBuf: `{"b":"","b":""}`,
7133 inVal: addr(structNoCaseInlineTextValue{}),
7134 want: addr(structNoCaseInlineTextValue{X: jsontext.Value(`{"b":""}`)}),
7135 wantErr: newDuplicateNameError("", []byte(`"b"`), len64(`{"b":"",`)),
7136 }, {
7137 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7138 inBuf: ``,
7139 inVal: addr(structAll{}),
7140 want: addr(structAll{}),
7141 wantErr: io.ErrUnexpectedEOF,
7142 }, {
7143 name: jsontest.Name("Structs/Invalid/NestedErrUnexpectedEOF"),
7144 inBuf: `{"Pointer":`,
7145 inVal: addr(structAll{}),
7146 want: addr(structAll{Pointer: new(structAll)}),
7147 wantErr: &jsontext.SyntacticError{ByteOffset: len64(`{"Pointer":`), JSONPointer: "/Pointer", Err: io.ErrUnexpectedEOF},
7148 }, {
7149 name: jsontest.Name("Structs/Invalid/Conflicting"),
7150 inBuf: `{}`,
7151 inVal: addr(structConflicting{}),
7152 want: addr(structConflicting{}),
7153 wantErr: EU(errors.New(`Go struct fields A and B conflict over JSON object name "conflict"`)).withType('{', T[structConflicting]()),
7154 }, {
7155 name: jsontest.Name("Structs/Invalid/NoneExported"),
7156 inBuf: ` {}`,
7157 inVal: addr(structNoneExported{}),
7158 want: addr(structNoneExported{}),
7159 wantErr: EU(errNoExportedFields).withPos(` `, "").withType('{', T[structNoneExported]()),
7160 }, {
7161 name: jsontest.Name("Structs/Invalid/MalformedTag"),
7162 inBuf: `{}`,
7163 inVal: addr(structMalformedTag{}),
7164 want: addr(structMalformedTag{}),
7165 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]()),
7166 }, {
7167 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
7168 inBuf: `{}`,
7169 inVal: addr(structUnexportedTag{}),
7170 want: addr(structUnexportedTag{}),
7171 wantErr: EU(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType('{', T[structUnexportedTag]()),
7172 }, {
7173 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
7174 inBuf: `{"NamedString":"hello"}`,
7175 inVal: addr(structExportedEmbedded{}),
7176 want: addr(structExportedEmbedded{}),
7177 wantErr: EU(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structExportedEmbedded]()),
7178 }, {
7179 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
7180 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
7181 inBuf: `{"NamedString":"hello"}`,
7182 inVal: addr(structExportedEmbedded{}),
7183 want: addr(structExportedEmbedded{"hello"}),
7184 }, {
7185 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
7186 inBuf: `{"name":"hello"}`,
7187 inVal: addr(structExportedEmbeddedTag{}),
7188 want: addr(structExportedEmbeddedTag{"hello"}),
7189 }, {
7190 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
7191 inBuf: `{}`,
7192 inVal: addr(structUnexportedEmbedded{}),
7193 want: addr(structUnexportedEmbedded{}),
7194 wantErr: EU(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structUnexportedEmbedded]()),
7195 }, {
7196 name: jsontest.Name("Structs/UnexportedEmbeddedStruct"),
7197 inBuf: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7198 inVal: addr(structUnexportedEmbeddedStruct{}),
7199 want: addr(structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7200 }, {
7201 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7202 inBuf: `{"Bool":true,"FizzBuzz":5}`,
7203 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7204 wantErr: EU(errNilField).withPos(`{"Bool":`, "/Bool").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7205 }, {
7206 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7207 inBuf: `{"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7208 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7209 wantErr: EU(errNilField).withPos(`{"FizzBuzz":5,"Addr":`, "/Addr").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7210 }, {
7211 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7212 inBuf: `{"Bool":true,"FizzBuzz":10,"Addr":"192.168.0.1"}`,
7213 inVal: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Int: 5}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{127, 0, 0, 1})}}),
7214 want: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true, Int: 5}, 10, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7215 }, {
7216 name: jsontest.Name("Structs/Unknown"),
7217 inBuf: `{
7218 "object0": {},
7219 "object1": {"key1": "value"},
7220 "object2": {"key1": "value", "key2": "value"},
7221 "objects": {"":{"":{"":{}}}},
7222 "array0": [],
7223 "array1": ["value1"],
7224 "array2": ["value1", "value2"],
7225 "array": [[[]]],
7226 "scalars": [null, false, true, "string", 12.345]
7227 }`,
7228 inVal: addr(struct{}{}),
7229 want: addr(struct{}{}),
7230 }, {
7231 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
7232 opts: []Options{invalidFormatOption},
7233 inBuf: `{"Field":"Value"}`,
7234 inVal: addr(struct{ Field string }{}),
7235 want: addr(struct{ Field string }{"Value"}),
7236 }, {
7237 name: jsontest.Name("Slices/Null"),
7238 inBuf: `null`,
7239 inVal: addr([]string{"something"}),
7240 want: addr([]string(nil)),
7241 }, {
7242 name: jsontest.Name("Slices/Bool"),
7243 inBuf: `[true,false]`,
7244 inVal: new([]bool),
7245 want: addr([]bool{true, false}),
7246 }, {
7247 name: jsontest.Name("Slices/String"),
7248 inBuf: `["hello","goodbye"]`,
7249 inVal: new([]string),
7250 want: addr([]string{"hello", "goodbye"}),
7251 }, {
7252 name: jsontest.Name("Slices/Bytes"),
7253 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7254 inVal: new([][]byte),
7255 want: addr([][]byte{[]byte("hello"), []byte("goodbye")}),
7256 }, {
7257 name: jsontest.Name("Slices/Int"),
7258 inBuf: `[-2,-1,0,1,2]`,
7259 inVal: new([]int),
7260 want: addr([]int{-2, -1, 0, 1, 2}),
7261 }, {
7262 name: jsontest.Name("Slices/Uint"),
7263 inBuf: `[0,1,2,3,4]`,
7264 inVal: new([]uint),
7265 want: addr([]uint{0, 1, 2, 3, 4}),
7266 }, {
7267 name: jsontest.Name("Slices/Float"),
7268 inBuf: `[3.14159,12.34]`,
7269 inVal: new([]float64),
7270 want: addr([]float64{3.14159, 12.34}),
7271 }, {
7272
7273
7274
7275 name: jsontest.Name("Slices/Merge"),
7276 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7277 inVal: addr([]map[string]string{{"k1": "v1"}, {"k2": "v2"}}[:1]),
7278 want: addr([]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7279 }, {
7280 name: jsontest.Name("Slices/Invalid/Channel"),
7281 inBuf: `["hello"]`,
7282 inVal: new([]chan string),
7283 want: addr([]chan string{nil}),
7284 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7285 }, {
7286 name: jsontest.Name("Slices/RecursiveSlice"),
7287 inBuf: `[[],[],[[]],[[],[]]]`,
7288 inVal: new(recursiveSlice),
7289 want: addr(recursiveSlice{
7290 {},
7291 {},
7292 {{}},
7293 {{}, {}},
7294 }),
7295 }, {
7296 name: jsontest.Name("Slices/Invalid/Bool"),
7297 inBuf: `true`,
7298 inVal: addr([]string{"nochange"}),
7299 want: addr([]string{"nochange"}),
7300 wantErr: EU(nil).withType('t', T[[]string]()),
7301 }, {
7302 name: jsontest.Name("Slices/Invalid/String"),
7303 inBuf: `""`,
7304 inVal: addr([]string{"nochange"}),
7305 want: addr([]string{"nochange"}),
7306 wantErr: EU(nil).withType('"', T[[]string]()),
7307 }, {
7308 name: jsontest.Name("Slices/Invalid/Number"),
7309 inBuf: `0`,
7310 inVal: addr([]string{"nochange"}),
7311 want: addr([]string{"nochange"}),
7312 wantErr: EU(nil).withType('0', T[[]string]()),
7313 }, {
7314 name: jsontest.Name("Slices/Invalid/Object"),
7315 inBuf: `{}`,
7316 inVal: addr([]string{"nochange"}),
7317 want: addr([]string{"nochange"}),
7318 wantErr: EU(nil).withType('{', T[[]string]()),
7319 }, {
7320 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
7321 opts: []Options{invalidFormatOption},
7322 inBuf: `[false,true]`,
7323 inVal: addr([]bool{true, false}),
7324 want: addr([]bool{false, true}),
7325 }, {
7326 name: jsontest.Name("Arrays/Null"),
7327 inBuf: `null`,
7328 inVal: addr([1]string{"something"}),
7329 want: addr([1]string{}),
7330 }, {
7331 name: jsontest.Name("Arrays/Bool"),
7332 inBuf: `[true,false]`,
7333 inVal: new([2]bool),
7334 want: addr([2]bool{true, false}),
7335 }, {
7336 name: jsontest.Name("Arrays/String"),
7337 inBuf: `["hello","goodbye"]`,
7338 inVal: new([2]string),
7339 want: addr([2]string{"hello", "goodbye"}),
7340 }, {
7341 name: jsontest.Name("Arrays/Bytes"),
7342 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7343 inVal: new([2][]byte),
7344 want: addr([2][]byte{[]byte("hello"), []byte("goodbye")}),
7345 }, {
7346 name: jsontest.Name("Arrays/Int"),
7347 inBuf: `[-2,-1,0,1,2]`,
7348 inVal: new([5]int),
7349 want: addr([5]int{-2, -1, 0, 1, 2}),
7350 }, {
7351 name: jsontest.Name("Arrays/Uint"),
7352 inBuf: `[0,1,2,3,4]`,
7353 inVal: new([5]uint),
7354 want: addr([5]uint{0, 1, 2, 3, 4}),
7355 }, {
7356 name: jsontest.Name("Arrays/Float"),
7357 inBuf: `[3.14159,12.34]`,
7358 inVal: new([2]float64),
7359 want: addr([2]float64{3.14159, 12.34}),
7360 }, {
7361
7362
7363 name: jsontest.Name("Arrays/Merge"),
7364 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7365 inVal: addr([2]map[string]string{{"k1": "v1"}, {"k2": "v2"}}),
7366 want: addr([2]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7367 }, {
7368 name: jsontest.Name("Arrays/Invalid/Channel"),
7369 inBuf: `["hello"]`,
7370 inVal: new([1]chan string),
7371 want: new([1]chan string),
7372 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7373 }, {
7374 name: jsontest.Name("Arrays/Invalid/Underflow"),
7375 inBuf: `{"F":[ ]}`,
7376 inVal: new(struct{ F [1]string }),
7377 want: addr(struct{ F [1]string }{}),
7378 wantErr: EU(errArrayUnderflow).withPos(`{"F":[ `, "/F").withType(']', T[[1]string]()),
7379 }, {
7380 name: jsontest.Name("Arrays/Invalid/Underflow/UnmarshalArrayFromAnyLength"),
7381 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7382 inBuf: `[-1,-2]`,
7383 inVal: addr([4]int{1, 2, 3, 4}),
7384 want: addr([4]int{-1, -2, 0, 0}),
7385 }, {
7386 name: jsontest.Name("Arrays/Invalid/Overflow"),
7387 inBuf: `["1","2"]`,
7388 inVal: new([1]string),
7389 want: addr([1]string{"1"}),
7390 wantErr: EU(errArrayOverflow).withPos(`["1","2"`, "").withType(']', T[[1]string]()),
7391 }, {
7392 name: jsontest.Name("Arrays/Invalid/Overflow/UnmarshalArrayFromAnyLength"),
7393 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7394 inBuf: `[-1,-2,-3,-4,-5,-6]`,
7395 inVal: addr([4]int{1, 2, 3, 4}),
7396 want: addr([4]int{-1, -2, -3, -4}),
7397 }, {
7398 name: jsontest.Name("Arrays/Invalid/Bool"),
7399 inBuf: `true`,
7400 inVal: addr([1]string{"nochange"}),
7401 want: addr([1]string{"nochange"}),
7402 wantErr: EU(nil).withType('t', T[[1]string]()),
7403 }, {
7404 name: jsontest.Name("Arrays/Invalid/String"),
7405 inBuf: `""`,
7406 inVal: addr([1]string{"nochange"}),
7407 want: addr([1]string{"nochange"}),
7408 wantErr: EU(nil).withType('"', T[[1]string]()),
7409 }, {
7410 name: jsontest.Name("Arrays/Invalid/Number"),
7411 inBuf: `0`,
7412 inVal: addr([1]string{"nochange"}),
7413 want: addr([1]string{"nochange"}),
7414 wantErr: EU(nil).withType('0', T[[1]string]()),
7415 }, {
7416 name: jsontest.Name("Arrays/Invalid/Object"),
7417 inBuf: `{}`,
7418 inVal: addr([1]string{"nochange"}),
7419 want: addr([1]string{"nochange"}),
7420 wantErr: EU(nil).withType('{', T[[1]string]()),
7421 }, {
7422 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
7423 opts: []Options{invalidFormatOption},
7424 inBuf: `[false,true]`,
7425 inVal: addr([2]bool{true, false}),
7426 want: addr([2]bool{false, true}),
7427 }, {
7428 name: jsontest.Name("Pointers/NullL0"),
7429 inBuf: `null`,
7430 inVal: new(*string),
7431 want: addr((*string)(nil)),
7432 }, {
7433 name: jsontest.Name("Pointers/NullL1"),
7434 inBuf: `null`,
7435 inVal: addr(new(*string)),
7436 want: addr((**string)(nil)),
7437 }, {
7438 name: jsontest.Name("Pointers/Bool"),
7439 inBuf: `true`,
7440 inVal: addr(new(bool)),
7441 want: addr(addr(true)),
7442 }, {
7443 name: jsontest.Name("Pointers/String"),
7444 inBuf: `"hello"`,
7445 inVal: addr(new(string)),
7446 want: addr(addr("hello")),
7447 }, {
7448 name: jsontest.Name("Pointers/Bytes"),
7449 inBuf: `"aGVsbG8="`,
7450 inVal: addr(new([]byte)),
7451 want: addr(addr([]byte("hello"))),
7452 }, {
7453 name: jsontest.Name("Pointers/Int"),
7454 inBuf: `-123`,
7455 inVal: addr(new(int)),
7456 want: addr(addr(int(-123))),
7457 }, {
7458 name: jsontest.Name("Pointers/Uint"),
7459 inBuf: `123`,
7460 inVal: addr(new(int)),
7461 want: addr(addr(int(123))),
7462 }, {
7463 name: jsontest.Name("Pointers/Float"),
7464 inBuf: `123.456`,
7465 inVal: addr(new(float64)),
7466 want: addr(addr(float64(123.456))),
7467 }, {
7468 name: jsontest.Name("Pointers/Allocate"),
7469 inBuf: `"hello"`,
7470 inVal: addr((*string)(nil)),
7471 want: addr(addr("hello")),
7472 }, {
7473 name: jsontest.Name("Points/IgnoreInvalidFormat"),
7474 opts: []Options{invalidFormatOption},
7475 inBuf: `true`,
7476 inVal: addr(new(bool)),
7477 want: addr(addr(true)),
7478 }, {
7479 name: jsontest.Name("Interfaces/Empty/Null"),
7480 inBuf: `null`,
7481 inVal: new(any),
7482 want: new(any),
7483 }, {
7484 name: jsontest.Name("Interfaces/NonEmpty/Null"),
7485 inBuf: `null`,
7486 inVal: new(io.Reader),
7487 want: new(io.Reader),
7488 }, {
7489 name: jsontest.Name("Interfaces/NonEmpty/Invalid"),
7490 inBuf: `"hello"`,
7491 inVal: new(io.Reader),
7492 want: new(io.Reader),
7493 wantErr: EU(errNilInterface).withType(0, T[io.Reader]()),
7494 }, {
7495 name: jsontest.Name("Interfaces/Empty/False"),
7496 inBuf: `false`,
7497 inVal: new(any),
7498 want: func() any {
7499 var vi any = false
7500 return &vi
7501 }(),
7502 }, {
7503 name: jsontest.Name("Interfaces/Empty/True"),
7504 inBuf: `true`,
7505 inVal: new(any),
7506 want: func() any {
7507 var vi any = true
7508 return &vi
7509 }(),
7510 }, {
7511 name: jsontest.Name("Interfaces/Empty/String"),
7512 inBuf: `"string"`,
7513 inVal: new(any),
7514 want: func() any {
7515 var vi any = "string"
7516 return &vi
7517 }(),
7518 }, {
7519 name: jsontest.Name("Interfaces/Empty/Number"),
7520 inBuf: `3.14159`,
7521 inVal: new(any),
7522 want: func() any {
7523 var vi any = 3.14159
7524 return &vi
7525 }(),
7526 }, {
7527 name: jsontest.Name("Interfaces/Empty/Object"),
7528 inBuf: `{"k":"v"}`,
7529 inVal: new(any),
7530 want: func() any {
7531 var vi any = map[string]any{"k": "v"}
7532 return &vi
7533 }(),
7534 }, {
7535 name: jsontest.Name("Interfaces/Empty/Array"),
7536 inBuf: `["v"]`,
7537 inVal: new(any),
7538 want: func() any {
7539 var vi any = []any{"v"}
7540 return &vi
7541 }(),
7542 }, {
7543 name: jsontest.Name("Interfaces/NamedAny/String"),
7544 inBuf: `"string"`,
7545 inVal: new(namedAny),
7546 want: func() namedAny {
7547 var vi namedAny = "string"
7548 return &vi
7549 }(),
7550 }, {
7551 name: jsontest.Name("Interfaces/Invalid"),
7552 inBuf: `]`,
7553 inVal: new(any),
7554 want: new(any),
7555 wantErr: newInvalidCharacterError("]", "at start of value", 0, ""),
7556 }, {
7557
7558
7559
7560
7561 name: jsontest.Name("Interfaces/Merge/Map"),
7562 inBuf: `{"k2":"v2"}`,
7563 inVal: func() any {
7564 var vi any = map[string]string{"k1": "v1"}
7565 return &vi
7566 }(),
7567 want: func() any {
7568 var vi any = map[string]string{"k1": "v1", "k2": "v2"}
7569 return &vi
7570 }(),
7571 }, {
7572 name: jsontest.Name("Interfaces/Merge/Struct"),
7573 inBuf: `{"Array":["goodbye"]}`,
7574 inVal: func() any {
7575 var vi any = structAll{String: "hello"}
7576 return &vi
7577 }(),
7578 want: func() any {
7579 var vi any = structAll{String: "hello", Array: [1]string{"goodbye"}}
7580 return &vi
7581 }(),
7582 }, {
7583 name: jsontest.Name("Interfaces/Merge/NamedInt"),
7584 inBuf: `64`,
7585 inVal: func() any {
7586 var vi any = namedInt64(-64)
7587 return &vi
7588 }(),
7589 want: func() any {
7590 var vi any = namedInt64(+64)
7591 return &vi
7592 }(),
7593 }, {
7594 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
7595 opts: []Options{invalidFormatOption},
7596 inBuf: `true`,
7597 inVal: new(any),
7598 want: func() any {
7599 var vi any = true
7600 return &vi
7601 }(),
7602 }, {
7603 name: jsontest.Name("Interfaces/Any"),
7604 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7605 inVal: new(struct{ X any }),
7606 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7607 }, {
7608 name: jsontest.Name("Interfaces/Any/Named"),
7609 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7610 inVal: new(struct{ X namedAny }),
7611 want: addr(struct{ X namedAny }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7612 }, {
7613 name: jsontest.Name("Interfaces/Any/Stringified"),
7614 opts: []Options{StringifyNumbers(true)},
7615 inBuf: `{"X":"0"}`,
7616 inVal: new(struct{ X any }),
7617 want: addr(struct{ X any }{"0"}),
7618 }, {
7619 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Any"),
7620 opts: []Options{
7621 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
7622 *v = "called"
7623 return nil
7624 })),
7625 },
7626 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7627 inVal: new(struct{ X any }),
7628 want: addr(struct{ X any }{"called"}),
7629 }, {
7630 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Bool"),
7631 opts: []Options{
7632 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *bool) error {
7633 *v = string(b) != "true"
7634 return nil
7635 })),
7636 },
7637 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7638 inVal: new(struct{ X any }),
7639 want: addr(struct{ X any }{[]any{nil, true, false, "", 0.0, map[string]any{}, []any{}}}),
7640 }, {
7641 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/String"),
7642 opts: []Options{
7643 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7644 *v = "called"
7645 return nil
7646 })),
7647 },
7648 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7649 inVal: new(struct{ X any }),
7650 want: addr(struct{ X any }{[]any{nil, false, true, "called", 0.0, map[string]any{}, []any{}}}),
7651 }, {
7652 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Float64"),
7653 opts: []Options{
7654 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *float64) error {
7655 *v = 3.14159
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, "", 3.14159, map[string]any{}, []any{}}}),
7662 }, {
7663 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/MapStringAny"),
7664 opts: []Options{
7665 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *map[string]any) error {
7666 *v = map[string]any{"called": nil}
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, "", 0.0, map[string]any{"called": nil}, []any{}}}),
7673 }, {
7674 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/SliceAny"),
7675 opts: []Options{
7676 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *[]any) error {
7677 *v = []any{"called"}
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{"called"}}),
7684 }, {
7685 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
7686 inBuf: `{"X":{"fizz":"buzz"}}`,
7687 inVal: new(struct{ X any }),
7688 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7689 }, {
7690 name: jsontest.Name("Interfaces/Any/Maps/RejectDuplicateNames"),
7691 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7692 inVal: new(struct{ X any }),
7693 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7694 wantErr: newDuplicateNameError("/X", []byte(`"fizz"`), len64(`{"X":{"fizz":"buzz",`)),
7695 }, {
7696 name: jsontest.Name("Interfaces/Any/Maps/AllowDuplicateNames"),
7697 opts: []Options{jsontext.AllowDuplicateNames(true)},
7698 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7699 inVal: new(struct{ X any }),
7700 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7701 wantErr: EU(nil).withPos(`{"X":{"fizz":"buzz","fizz":`, "/X/fizz").withType('t', T[string]()),
7702 }, {
7703 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
7704 inBuf: `{"X":["fizz","buzz"]}`,
7705 inVal: new(struct{ X any }),
7706 want: addr(struct{ X any }{[]any{"fizz", "buzz"}}),
7707 }, {
7708 name: jsontest.Name("Methods/NilPointer/Null"),
7709 inBuf: `{"X":null}`,
7710 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7711 want: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7712 }, {
7713 name: jsontest.Name("Methods/NilPointer/Value"),
7714 inBuf: `{"X":"value"}`,
7715 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7716 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7717 }, {
7718 name: jsontest.Name("Methods/NilInterface/Null"),
7719 inBuf: `{"X":null}`,
7720 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7721 want: addr(struct{ X MarshalerTo }{X: nil}),
7722 }, {
7723 name: jsontest.Name("Methods/NilInterface/Value"),
7724 inBuf: `{"X":"value"}`,
7725 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7726 want: addr(struct{ X MarshalerTo }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7727 }, {
7728 name: jsontest.Name("Methods/AllMethods"),
7729 inBuf: `{"X":"hello"}`,
7730 inVal: new(struct{ X *allMethods }),
7731 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}),
7732 }, {
7733 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
7734 inBuf: `{"X":"hello"}`,
7735 inVal: new(struct{ X *allMethodsExceptJSONv2 }),
7736 want: addr(struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7737 }, {
7738 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
7739 inBuf: `{"X":"hello"}`,
7740 inVal: new(struct{ X *allMethodsExceptJSONv1 }),
7741 want: addr(struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7742 }, {
7743 name: jsontest.Name("Methods/AllMethodsExceptText"),
7744 inBuf: `{"X":"hello"}`,
7745 inVal: new(struct{ X *allMethodsExceptText }),
7746 want: addr(struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7747 }, {
7748 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
7749 inBuf: `{"X":"hello"}`,
7750 inVal: new(struct{ X *onlyMethodJSONv2 }),
7751 want: addr(struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7752 }, {
7753 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
7754 inBuf: `{"X":"hello"}`,
7755 inVal: new(struct{ X *onlyMethodJSONv1 }),
7756 want: addr(struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7757 }, {
7758 name: jsontest.Name("Methods/OnlyMethodText"),
7759 inBuf: `{"X":"hello"}`,
7760 inVal: new(struct{ X *onlyMethodText }),
7761 want: addr(struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "UnmarshalText", value: []byte(`hello`)}}}),
7762 }, {
7763 name: jsontest.Name("Methods/Text/Null"),
7764 inBuf: `{"X":null}`,
7765 inVal: addr(struct{ X unmarshalTextFunc }{unmarshalTextFunc(func(b []byte) error {
7766 return errMustNotCall
7767 })}),
7768 want: addr(struct{ X unmarshalTextFunc }{nil}),
7769 }, {
7770 name: jsontest.Name("Methods/IP"),
7771 inBuf: `"192.168.0.100"`,
7772 inVal: new(net.IP),
7773 want: addr(net.IPv4(192, 168, 0, 100)),
7774 }, {
7775
7776 name: jsontest.Name("Methods/Anonymous"),
7777 inBuf: `{"X":"hello"}`,
7778 inVal: new(struct{ X struct{ allMethods } }),
7779 want: addr(struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7780 }, {
7781
7782 name: jsontest.Name("Methods/Addressable"),
7783 inBuf: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
7784 inVal: addr(struct {
7785 V allMethods
7786 M map[string]allMethods
7787 I any
7788 }{
7789 I: allMethods{},
7790 }),
7791 want: addr(struct {
7792 V allMethods
7793 M map[string]allMethods
7794 I any
7795 }{
7796 V: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7797 M: map[string]allMethods{"K": {method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}},
7798 I: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7799 }),
7800 }, {
7801
7802 name: jsontest.Name("Methods/MapKey/JSONv2"),
7803 inBuf: `{"k1":"v1b","k2":"v2"}`,
7804 inVal: addr(map[structMethodJSONv2]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7805 want: addr(map[structMethodJSONv2]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7806 }, {
7807
7808 name: jsontest.Name("Methods/MapKey/JSONv1"),
7809 inBuf: `{"k1":"v1b","k2":"v2"}`,
7810 inVal: addr(map[structMethodJSONv1]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7811 want: addr(map[structMethodJSONv1]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7812 }, {
7813 name: jsontest.Name("Methods/MapKey/Text"),
7814 inBuf: `{"k1":"v1b","k2":"v2"}`,
7815 inVal: addr(map[structMethodText]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7816 want: addr(map[structMethodText]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7817 }, {
7818 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
7819 inBuf: `{}`,
7820 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7821 return errSomeError
7822 })),
7823 wantErr: EU(errSomeError).withType(0, T[unmarshalJSONv2Func]()),
7824 }, {
7825 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
7826 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7827 return nil
7828 })),
7829 wantErr: EU(errNonSingularValue).withType(0, T[unmarshalJSONv2Func]()),
7830 }, {
7831 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
7832 inBuf: `{}{}`,
7833 inVal: addr(unmarshalJSONv2Func(func(dec *jsontext.Decoder) error {
7834 dec.ReadValue()
7835 dec.ReadValue()
7836 return nil
7837 })),
7838 wantErr: EU(errNonSingularValue).withPos(`{}`, "").withType(0, T[unmarshalJSONv2Func]()),
7839 }, {
7840 name: jsontest.Name("Methods/Invalid/JSONv2/SkipFunc"),
7841 inBuf: `{}`,
7842 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7843 return SkipFunc
7844 })),
7845 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType(0, T[unmarshalJSONv2Func]()),
7846 }, {
7847 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
7848 inBuf: `{}`,
7849 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7850 return errSomeError
7851 })),
7852 wantErr: EU(errSomeError).withType('{', T[unmarshalJSONv1Func]()),
7853 }, {
7854 name: jsontest.Name("Methods/Invalid/JSONv1/SkipFunc"),
7855 inBuf: `{}`,
7856 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7857 return SkipFunc
7858 })),
7859 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType('{', T[unmarshalJSONv1Func]()),
7860 }, {
7861 name: jsontest.Name("Methods/Invalid/Text/Error"),
7862 inBuf: `"value"`,
7863 inVal: addr(unmarshalTextFunc(func([]byte) error {
7864 return errSomeError
7865 })),
7866 wantErr: EU(errSomeError).withType('"', T[unmarshalTextFunc]()),
7867 }, {
7868 name: jsontest.Name("Methods/Invalid/Text/Syntax"),
7869 inBuf: `{}`,
7870 inVal: addr(unmarshalTextFunc(func([]byte) error {
7871 panic("should not be called")
7872 })),
7873 wantErr: EU(errNonStringValue).withType('{', T[unmarshalTextFunc]()),
7874 }, {
7875 name: jsontest.Name("Methods/Invalid/Text/SkipFunc"),
7876 inBuf: `"value"`,
7877 inVal: addr(unmarshalTextFunc(func([]byte) error {
7878 return SkipFunc
7879 })),
7880 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType('"', T[unmarshalTextFunc]()),
7881 }, {
7882 name: jsontest.Name("Functions/String/V1"),
7883 opts: []Options{
7884 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7885 if string(b) != `""` {
7886 return fmt.Errorf("got %s, want %s", b, `""`)
7887 }
7888 *v = "called"
7889 return nil
7890 })),
7891 },
7892 inBuf: `""`,
7893 inVal: addr(""),
7894 want: addr("called"),
7895 }, {
7896 name: jsontest.Name("Functions/String/Empty"),
7897 opts: []Options{WithUnmarshalers(nil)},
7898 inBuf: `"hello"`,
7899 inVal: addr(""),
7900 want: addr("hello"),
7901 }, {
7902 name: jsontest.Name("Functions/NamedString/V1/NoMatch"),
7903 opts: []Options{
7904 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7905 panic("should not be called")
7906 })),
7907 },
7908 inBuf: `""`,
7909 inVal: addr(""),
7910 want: addr(""),
7911 }, {
7912 name: jsontest.Name("Functions/NamedString/V1/Match"),
7913 opts: []Options{
7914 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7915 if string(b) != `""` {
7916 return fmt.Errorf("got %s, want %s", b, `""`)
7917 }
7918 *v = "called"
7919 return nil
7920 })),
7921 },
7922 inBuf: `""`,
7923 inVal: addr(namedString("")),
7924 want: addr(namedString("called")),
7925 }, {
7926 name: jsontest.Name("Functions/String/V2"),
7927 opts: []Options{
7928 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
7929 switch b, err := dec.ReadValue(); {
7930 case err != nil:
7931 return err
7932 case string(b) != `""`:
7933 return fmt.Errorf("got %s, want %s", b, `""`)
7934 }
7935 *v = "called"
7936 return nil
7937 })),
7938 },
7939 inBuf: `""`,
7940 inVal: addr(""),
7941 want: addr("called"),
7942 }, {
7943 name: jsontest.Name("Functions/NamedString/V2/NoMatch"),
7944 opts: []Options{
7945 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7946 panic("should not be called")
7947 })),
7948 },
7949 inBuf: `""`,
7950 inVal: addr(""),
7951 want: addr(""),
7952 }, {
7953 name: jsontest.Name("Functions/NamedString/V2/Match"),
7954 opts: []Options{
7955 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7956 switch t, err := dec.ReadToken(); {
7957 case err != nil:
7958 return err
7959 case t.String() != ``:
7960 return fmt.Errorf("got %q, want %q", t, ``)
7961 }
7962 *v = "called"
7963 return nil
7964 })),
7965 },
7966 inBuf: `""`,
7967 inVal: addr(namedString("")),
7968 want: addr(namedString("called")),
7969 }, {
7970 name: jsontest.Name("Functions/String/Empty1/NoMatch"),
7971 opts: []Options{
7972 WithUnmarshalers(new(Unmarshalers)),
7973 },
7974 inBuf: `""`,
7975 inVal: addr(""),
7976 want: addr(""),
7977 }, {
7978 name: jsontest.Name("Functions/String/Empty2/NoMatch"),
7979 opts: []Options{
7980 WithUnmarshalers(JoinUnmarshalers()),
7981 },
7982 inBuf: `""`,
7983 inVal: addr(""),
7984 want: addr(""),
7985 }, {
7986 name: jsontest.Name("Functions/String/V1/DirectError"),
7987 opts: []Options{
7988 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
7989 return errSomeError
7990 })),
7991 },
7992 inBuf: `""`,
7993 inVal: addr(""),
7994 want: addr(""),
7995 wantErr: EU(errSomeError).withType('"', reflect.PointerTo(stringType)),
7996 }, {
7997 name: jsontest.Name("Functions/String/V1/SkipError"),
7998 opts: []Options{
7999 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8000 return SkipFunc
8001 })),
8002 },
8003 inBuf: `""`,
8004 inVal: addr(""),
8005 want: addr(""),
8006 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal function of type func([]byte, T) error")).withType('"', reflect.PointerTo(stringType)),
8007 }, {
8008 name: jsontest.Name("Functions/String/V2/DirectError"),
8009 opts: []Options{
8010 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8011 return errSomeError
8012 })),
8013 },
8014 inBuf: `""`,
8015 inVal: addr(""),
8016 want: addr(""),
8017 wantErr: EU(errSomeError).withType(0, reflect.PointerTo(stringType)),
8018 }, {
8019 name: jsontest.Name("Functions/String/V2/TooFew"),
8020 opts: []Options{
8021 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8022 return nil
8023 })),
8024 },
8025 inBuf: `""`,
8026 inVal: addr(""),
8027 want: addr(""),
8028 wantErr: EU(errNonSingularValue).withType(0, reflect.PointerTo(stringType)),
8029 }, {
8030 name: jsontest.Name("Functions/String/V2/TooMany"),
8031 opts: []Options{
8032 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8033 if _, err := dec.ReadValue(); err != nil {
8034 return err
8035 }
8036 if _, err := dec.ReadValue(); err != nil {
8037 return err
8038 }
8039 return nil
8040 })),
8041 },
8042 inBuf: `{"X":["",""]}`,
8043 inVal: addr(struct{ X []string }{}),
8044 want: addr(struct{ X []string }{[]string{""}}),
8045 wantErr: EU(errNonSingularValue).withPos(`{"X":["",`, "/X").withType(0, reflect.PointerTo(stringType)),
8046 }, {
8047 name: jsontest.Name("Functions/String/V2/Skipped"),
8048 opts: []Options{
8049 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8050 return SkipFunc
8051 })),
8052 },
8053 inBuf: `""`,
8054 inVal: addr(""),
8055 want: addr(""),
8056 }, {
8057 name: jsontest.Name("Functions/String/V2/ProcessBeforeSkip"),
8058 opts: []Options{
8059 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8060 if _, err := dec.ReadValue(); err != nil {
8061 return err
8062 }
8063 return SkipFunc
8064 })),
8065 },
8066 inBuf: `""`,
8067 inVal: addr(""),
8068 want: addr(""),
8069 wantErr: EU(errSkipMutation).withType(0, reflect.PointerTo(stringType)),
8070 }, {
8071 name: jsontest.Name("Functions/String/V2/WrappedSkipError"),
8072 opts: []Options{
8073 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8074 return fmt.Errorf("wrap: %w", SkipFunc)
8075 })),
8076 },
8077 inBuf: `""`,
8078 inVal: addr(""),
8079 want: addr(""),
8080 wantErr: EU(fmt.Errorf("wrap: %w", SkipFunc)).withType(0, reflect.PointerTo(stringType)),
8081 }, {
8082 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
8083 opts: []Options{
8084 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8085 if string(b) != `"hello"` {
8086 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8087 }
8088 *v = "called"
8089 return nil
8090 })),
8091 },
8092 inBuf: `{"hello":"world"}`,
8093 inVal: addr(map[nocaseString]string{}),
8094 want: addr(map[nocaseString]string{"called": "world"}),
8095 }, {
8096 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
8097 opts: []Options{
8098 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8099 if string(b) != `"hello"` {
8100 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8101 }
8102 *v.(*nocaseString) = "called"
8103 return nil
8104 })),
8105 },
8106 inBuf: `{"hello":"world"}`,
8107 inVal: addr(map[nocaseString]string{}),
8108 want: addr(map[nocaseString]string{"called": "world"}),
8109 }, {
8110 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
8111 opts: []Options{
8112 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8113 switch t, err := dec.ReadToken(); {
8114 case err != nil:
8115 return err
8116 case t.String() != "hello":
8117 return fmt.Errorf("got %q, want %q", t, "hello")
8118 }
8119 *v = "called"
8120 return nil
8121 })),
8122 },
8123 inBuf: `{"hello":"world"}`,
8124 inVal: addr(map[nocaseString]string{}),
8125 want: addr(map[nocaseString]string{"called": "world"}),
8126 }, {
8127 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
8128 opts: []Options{
8129 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8130 switch b, err := dec.ReadValue(); {
8131 case err != nil:
8132 return err
8133 case string(b) != `"hello"`:
8134 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8135 }
8136 *v.(*nocaseString) = "called"
8137 return nil
8138 })),
8139 },
8140 inBuf: `{"hello":"world"}`,
8141 inVal: addr(map[nocaseString]string{}),
8142 want: addr(map[nocaseString]string{"called": "world"}),
8143 }, {
8144 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
8145 opts: []Options{
8146 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8147 if _, err := dec.ReadValue(); err != nil {
8148 return err
8149 }
8150 xd := export.Decoder(dec)
8151 *v = fmt.Sprintf("%d-%d", len(xd.Tokens.Stack), xd.Tokens.Last.Length())
8152 return nil
8153 })),
8154 },
8155 inBuf: `{"name":"value","name":"value"}`,
8156 inVal: addr(map[string]string{}),
8157 want: addr(map[string]string{"1-1": "1-2"}),
8158 wantErr: newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"value",`)),
8159 }, {
8160 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
8161 opts: []Options{
8162 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8163 if string(b) != `"world"` {
8164 return fmt.Errorf("got %s, want %s", b, `"world"`)
8165 }
8166 *v = "called"
8167 return nil
8168 })),
8169 },
8170 inBuf: `{"hello":"world"}`,
8171 inVal: addr(map[string]nocaseString{}),
8172 want: addr(map[string]nocaseString{"hello": "called"}),
8173 }, {
8174 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
8175 opts: []Options{
8176 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8177 if string(b) != `"world"` {
8178 return fmt.Errorf("got %s, want %s", b, `"world"`)
8179 }
8180 *v.(*nocaseString) = "called"
8181 return nil
8182 })),
8183 },
8184 inBuf: `{"hello":"world"}`,
8185 inVal: addr(map[string]nocaseString{}),
8186 want: addr(map[string]nocaseString{"hello": "called"}),
8187 }, {
8188 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
8189 opts: []Options{
8190 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8191 switch t, err := dec.ReadToken(); {
8192 case err != nil:
8193 return err
8194 case t.String() != "world":
8195 return fmt.Errorf("got %q, want %q", t, "world")
8196 }
8197 *v = "called"
8198 return nil
8199 })),
8200 },
8201 inBuf: `{"hello":"world"}`,
8202 inVal: addr(map[string]nocaseString{}),
8203 want: addr(map[string]nocaseString{"hello": "called"}),
8204 }, {
8205 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
8206 opts: []Options{
8207 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8208 switch b, err := dec.ReadValue(); {
8209 case err != nil:
8210 return err
8211 case string(b) != `"world"`:
8212 return fmt.Errorf("got %s, want %s", b, `"world"`)
8213 }
8214 *v.(*nocaseString) = "called"
8215 return nil
8216 })),
8217 },
8218 inBuf: `{"hello":"world"}`,
8219 inVal: addr(map[string]nocaseString{}),
8220 want: addr(map[string]nocaseString{"hello": "called"}),
8221 }, {
8222 name: jsontest.Name("Funtions/Struct/Fields"),
8223 opts: []Options{
8224 WithUnmarshalers(JoinUnmarshalers(
8225 UnmarshalFunc(func(b []byte, v *bool) error {
8226 if string(b) != `"called1"` {
8227 return fmt.Errorf("got %s, want %s", b, `"called1"`)
8228 }
8229 *v = true
8230 return nil
8231 }),
8232 UnmarshalFunc(func(b []byte, v *string) error {
8233 if string(b) != `"called2"` {
8234 return fmt.Errorf("got %s, want %s", b, `"called2"`)
8235 }
8236 *v = "called2"
8237 return nil
8238 }),
8239 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[]byte) error {
8240 switch t, err := dec.ReadToken(); {
8241 case err != nil:
8242 return err
8243 case t.String() != "called3":
8244 return fmt.Errorf("got %q, want %q", t, "called3")
8245 }
8246 *v = []byte("called3")
8247 return nil
8248 }),
8249 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *int64) error {
8250 switch b, err := dec.ReadValue(); {
8251 case err != nil:
8252 return err
8253 case string(b) != `"called4"`:
8254 return fmt.Errorf("got %s, want %s", b, `"called4"`)
8255 }
8256 *v = 123
8257 return nil
8258 }),
8259 )),
8260 },
8261 inBuf: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":456,"Float":789}`,
8262 inVal: addr(structScalars{}),
8263 want: addr(structScalars{Bool: true, String: "called2", Bytes: []byte("called3"), Int: 123, Uint: 456, Float: 789}),
8264 }, {
8265 name: jsontest.Name("Functions/Struct/Inlined"),
8266 opts: []Options{
8267 WithUnmarshalers(JoinUnmarshalers(
8268 UnmarshalFunc(func([]byte, *structInlinedL1) error {
8269 panic("should not be called")
8270 }),
8271 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *StructEmbed2) error {
8272 panic("should not be called")
8273 }),
8274 )),
8275 },
8276 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
8277 inVal: new(structInlined),
8278 want: addr(structInlined{
8279 X: structInlinedL1{
8280 X: &structInlinedL2{A: "A1", B: "B1" },
8281 StructEmbed1: StructEmbed1{ D: "D2" },
8282 },
8283 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
8284 }),
8285 }, {
8286 name: jsontest.Name("Functions/Slice/Elem"),
8287 opts: []Options{
8288 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8289 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8290 return nil
8291 })),
8292 },
8293 inBuf: `["hello","World"]`,
8294 inVal: addr([]string{}),
8295 want: addr([]string{"HELLO", "WORLD"}),
8296 }, {
8297 name: jsontest.Name("Functions/Array/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([2]string{}),
8306 want: addr([2]string{"HELLO", "WORLD"}),
8307 }, {
8308 name: jsontest.Name("Functions/Pointer/Nil"),
8309 opts: []Options{
8310 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8311 t, err := dec.ReadToken()
8312 *v = strings.ToUpper(t.String())
8313 return err
8314 })),
8315 },
8316 inBuf: `{"X":"hello"}`,
8317 inVal: addr(struct{ X *string }{nil}),
8318 want: addr(struct{ X *string }{addr("HELLO")}),
8319 }, {
8320 name: jsontest.Name("Functions/Pointer/NonNil"),
8321 opts: []Options{
8322 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8323 t, err := dec.ReadToken()
8324 *v = strings.ToUpper(t.String())
8325 return err
8326 })),
8327 },
8328 inBuf: `{"X":"hello"}`,
8329 inVal: addr(struct{ X *string }{addr("")}),
8330 want: addr(struct{ X *string }{addr("HELLO")}),
8331 }, {
8332 name: jsontest.Name("Functions/Interface/Nil"),
8333 opts: []Options{
8334 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v fmt.Stringer) error {
8335 panic("should not be called")
8336 })),
8337 },
8338 inBuf: `{"X":"hello"}`,
8339 inVal: addr(struct{ X fmt.Stringer }{nil}),
8340 want: addr(struct{ X fmt.Stringer }{nil}),
8341 wantErr: EU(errNilInterface).withPos(`{"X":`, "/X").withType(0, T[fmt.Stringer]()),
8342 }, {
8343 name: jsontest.Name("Functions/Interface/NetIP"),
8344 opts: []Options{
8345 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8346 *v = net.IP{}
8347 return SkipFunc
8348 })),
8349 },
8350 inBuf: `{"X":"1.1.1.1"}`,
8351 inVal: addr(struct{ X fmt.Stringer }{nil}),
8352 want: addr(struct{ X fmt.Stringer }{net.IPv4(1, 1, 1, 1)}),
8353 }, {
8354 name: jsontest.Name("Functions/Interface/NewPointerNetIP"),
8355 opts: []Options{
8356 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8357 *v = new(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 }{addr(net.IPv4(1, 1, 1, 1))}),
8364 }, {
8365 name: jsontest.Name("Functions/Interface/NilPointerNetIP"),
8366 opts: []Options{
8367 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8368 *v = (*net.IP)(nil)
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/Override"),
8377 opts: []Options{
8378 WithUnmarshalers(JoinUnmarshalers(
8379 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8380 *v = (*net.IP)(nil)
8381 return SkipFunc
8382 }),
8383 UnmarshalFunc(func(b []byte, v *net.IP) error {
8384 b = bytes.ReplaceAll(b, []byte(`1`), []byte(`8`))
8385 return v.UnmarshalText(bytes.Trim(b, `"`))
8386 }),
8387 )),
8388 },
8389 inBuf: `{"X":"1.1.1.1"}`,
8390 inVal: addr(struct{ X fmt.Stringer }{nil}),
8391 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(8, 8, 8, 8))}),
8392 }, {
8393 name: jsontest.Name("Functions/Interface/Any"),
8394 inBuf: `[null,{},{},{},{},{},{},{},{},{},{},{},{},"LAST"]`,
8395 inVal: addr([...]any{
8396 nil,
8397 valueStringer{},
8398 (*valueStringer)(nil),
8399 addr(valueStringer{}),
8400 (**valueStringer)(nil),
8401 addr((*valueStringer)(nil)),
8402 addr(addr(valueStringer{})),
8403 pointerStringer{},
8404 (*pointerStringer)(nil),
8405 addr(pointerStringer{}),
8406 (**pointerStringer)(nil),
8407 addr((*pointerStringer)(nil)),
8408 addr(addr(pointerStringer{})),
8409 "LAST",
8410 }),
8411 opts: []Options{
8412 WithUnmarshalers(func() *Unmarshalers {
8413 type P struct {
8414 D int
8415 N int64
8416 }
8417 type PV struct {
8418 P P
8419 V any
8420 }
8421
8422 var lastChecks []func() error
8423 checkLast := func() error {
8424 for _, fn := range lastChecks {
8425 if err := fn(); err != nil {
8426 return err
8427 }
8428 }
8429 return SkipFunc
8430 }
8431 makeValueChecker := func(name string, want []PV) func(d *jsontext.Decoder, v any) error {
8432 checkNext := func(d *jsontext.Decoder, v any) error {
8433 xd := export.Decoder(d)
8434 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8435 rv := reflect.ValueOf(v)
8436 pv := PV{p, v}
8437 switch {
8438 case len(want) == 0:
8439 return fmt.Errorf("%s: %v: got more values than expected", name, p)
8440 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
8441 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
8442 case !reflect.DeepEqual(pv, want[0]):
8443 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
8444 default:
8445 want = want[1:]
8446 return SkipFunc
8447 }
8448 }
8449 lastChecks = append(lastChecks, func() error {
8450 if len(want) > 0 {
8451 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8452 }
8453 return nil
8454 })
8455 return checkNext
8456 }
8457 makePositionChecker := func(name string, want []P) func(d *jsontext.Decoder, v any) error {
8458 checkNext := func(d *jsontext.Decoder, v any) error {
8459 xd := export.Decoder(d)
8460 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8461 switch {
8462 case len(want) == 0:
8463 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
8464 case p != want[0]:
8465 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
8466 default:
8467 want = want[1:]
8468 return SkipFunc
8469 }
8470 }
8471 lastChecks = append(lastChecks, func() error {
8472 if len(want) > 0 {
8473 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8474 }
8475 return nil
8476 })
8477 return checkNext
8478 }
8479
8480
8481
8482 wantAny := []PV{
8483 {P{1, 0}, addr(any(nil))},
8484 {P{1, 1}, addr(any(valueStringer{}))},
8485 {P{1, 1}, addr(valueStringer{})},
8486 {P{1, 2}, addr(any((*valueStringer)(nil)))},
8487 {P{1, 2}, addr((*valueStringer)(nil))},
8488 {P{1, 2}, addr(valueStringer{})},
8489 {P{1, 3}, addr(any(addr(valueStringer{})))},
8490 {P{1, 3}, addr(addr(valueStringer{}))},
8491 {P{1, 3}, addr(valueStringer{})},
8492 {P{1, 4}, addr(any((**valueStringer)(nil)))},
8493 {P{1, 4}, addr((**valueStringer)(nil))},
8494 {P{1, 4}, addr((*valueStringer)(nil))},
8495 {P{1, 4}, addr(valueStringer{})},
8496 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
8497 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
8498 {P{1, 5}, addr((*valueStringer)(nil))},
8499 {P{1, 5}, addr(valueStringer{})},
8500 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
8501 {P{1, 6}, addr(addr(addr(valueStringer{})))},
8502 {P{1, 6}, addr(addr(valueStringer{}))},
8503 {P{1, 6}, addr(valueStringer{})},
8504 {P{1, 7}, addr(any(pointerStringer{}))},
8505 {P{1, 7}, addr(pointerStringer{})},
8506 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
8507 {P{1, 8}, addr((*pointerStringer)(nil))},
8508 {P{1, 8}, addr(pointerStringer{})},
8509 {P{1, 9}, addr(any(addr(pointerStringer{})))},
8510 {P{1, 9}, addr(addr(pointerStringer{}))},
8511 {P{1, 9}, addr(pointerStringer{})},
8512 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
8513 {P{1, 10}, addr((**pointerStringer)(nil))},
8514 {P{1, 10}, addr((*pointerStringer)(nil))},
8515 {P{1, 10}, addr(pointerStringer{})},
8516 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
8517 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
8518 {P{1, 11}, addr((*pointerStringer)(nil))},
8519 {P{1, 11}, addr(pointerStringer{})},
8520 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
8521 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
8522 {P{1, 12}, addr(addr(pointerStringer{}))},
8523 {P{1, 12}, addr(pointerStringer{})},
8524 {P{1, 13}, addr(any("LAST"))},
8525 {P{1, 13}, addr("LAST")},
8526 }
8527 checkAny := makeValueChecker("any", wantAny)
8528 anyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v any) error {
8529 return checkAny(dec, v)
8530 })
8531
8532 var wantPointerAny []PV
8533 for _, v := range wantAny {
8534 if _, ok := v.V.(*any); ok {
8535 wantPointerAny = append(wantPointerAny, v)
8536 }
8537 }
8538 checkPointerAny := makeValueChecker("*any", wantPointerAny)
8539 pointerAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *any) error {
8540 return checkPointerAny(dec, v)
8541 })
8542
8543 checkNamedAny := makeValueChecker("namedAny", wantAny)
8544 namedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v namedAny) error {
8545 return checkNamedAny(dec, v)
8546 })
8547
8548 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
8549 pointerNamedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedAny) error {
8550 return checkPointerNamedAny(dec, v)
8551 })
8552
8553 type stringer = fmt.Stringer
8554 var wantStringer []PV
8555 for _, v := range wantAny {
8556 if _, ok := v.V.(stringer); ok {
8557 wantStringer = append(wantStringer, v)
8558 }
8559 }
8560 checkStringer := makeValueChecker("stringer", wantStringer)
8561 stringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v stringer) error {
8562 return checkStringer(dec, v)
8563 })
8564
8565 checkPointerStringer := makeValueChecker("*stringer", nil)
8566 pointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *stringer) error {
8567 return checkPointerStringer(dec, v)
8568 })
8569
8570 wantValueStringer := []P{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}}
8571 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
8572 pointerValueStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *valueStringer) error {
8573 return checkPointerValueStringer(dec, v)
8574 })
8575
8576 wantPointerStringer := []P{{1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}}
8577 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
8578 pointerPointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *pointerStringer) error {
8579 return checkPointerPointerStringer(dec, v)
8580 })
8581
8582 lastUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8583 return checkLast()
8584 })
8585
8586 return JoinUnmarshalers(
8587
8588
8589 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[14]any) error {
8590 if _, err := dec.ReadToken(); err != nil {
8591 return err
8592 }
8593 for i := range len(*v) {
8594 if err := UnmarshalDecode(dec, &(*v)[i]); err != nil {
8595 return err
8596 }
8597 }
8598 if _, err := dec.ReadToken(); err != nil {
8599 return err
8600 }
8601 return nil
8602 }),
8603
8604 anyUnmarshaler,
8605 pointerAnyUnmarshaler,
8606 namedAnyUnmarshaler,
8607 pointerNamedAnyUnmarshaler,
8608 stringerUnmarshaler,
8609 pointerStringerUnmarshaler,
8610 pointerValueStringerUnmarshaler,
8611 pointerPointerStringerUnmarshaler,
8612 lastUnmarshaler,
8613 )
8614 }()),
8615 },
8616 }, {
8617 name: jsontest.Name("Functions/Precedence/V1First"),
8618 opts: []Options{
8619 WithUnmarshalers(JoinUnmarshalers(
8620 UnmarshalFunc(func(b []byte, v *string) error {
8621 if string(b) != `"called"` {
8622 return fmt.Errorf("got %s, want %s", b, `"called"`)
8623 }
8624 *v = "called"
8625 return nil
8626 }),
8627 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8628 panic("should not be called")
8629 }),
8630 )),
8631 },
8632 inBuf: `"called"`,
8633 inVal: addr(""),
8634 want: addr("called"),
8635 }, {
8636 name: jsontest.Name("Functions/Precedence/V2First"),
8637 opts: []Options{
8638 WithUnmarshalers(JoinUnmarshalers(
8639 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8640 switch t, err := dec.ReadToken(); {
8641 case err != nil:
8642 return err
8643 case t.String() != "called":
8644 return fmt.Errorf("got %q, want %q", t, "called")
8645 }
8646 *v = "called"
8647 return nil
8648 }),
8649 UnmarshalFunc(func([]byte, *string) error {
8650 panic("should not be called")
8651 }),
8652 )),
8653 },
8654 inBuf: `"called"`,
8655 inVal: addr(""),
8656 want: addr("called"),
8657 }, {
8658 name: jsontest.Name("Functions/Precedence/V2Skipped"),
8659 opts: []Options{
8660 WithUnmarshalers(JoinUnmarshalers(
8661 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8662 return SkipFunc
8663 }),
8664 UnmarshalFunc(func(b []byte, v *string) error {
8665 if string(b) != `"called"` {
8666 return fmt.Errorf("got %s, want %s", b, `"called"`)
8667 }
8668 *v = "called"
8669 return nil
8670 }),
8671 )),
8672 },
8673 inBuf: `"called"`,
8674 inVal: addr(""),
8675 want: addr("called"),
8676 }, {
8677 name: jsontest.Name("Functions/Precedence/NestedFirst"),
8678 opts: []Options{
8679 WithUnmarshalers(JoinUnmarshalers(
8680 JoinUnmarshalers(
8681 UnmarshalFunc(func(b []byte, v *string) error {
8682 if string(b) != `"called"` {
8683 return fmt.Errorf("got %s, want %s", b, `"called"`)
8684 }
8685 *v = "called"
8686 return nil
8687 }),
8688 ),
8689 UnmarshalFunc(func([]byte, *string) error {
8690 panic("should not be called")
8691 }),
8692 )),
8693 },
8694 inBuf: `"called"`,
8695 inVal: addr(""),
8696 want: addr("called"),
8697 }, {
8698 name: jsontest.Name("Functions/Precedence/NestedLast"),
8699 opts: []Options{
8700 WithUnmarshalers(JoinUnmarshalers(
8701 UnmarshalFunc(func(b []byte, v *string) error {
8702 if string(b) != `"called"` {
8703 return fmt.Errorf("got %s, want %s", b, `"called"`)
8704 }
8705 *v = "called"
8706 return nil
8707 }),
8708 JoinUnmarshalers(
8709 UnmarshalFunc(func([]byte, *string) error {
8710 panic("should not be called")
8711 }),
8712 ),
8713 )),
8714 },
8715 inBuf: `"called"`,
8716 inVal: addr(""),
8717 want: addr("called"),
8718 }, {
8719 name: jsontest.Name("Duration/Null"),
8720 inBuf: `{"D1":null,"D2":null}`,
8721 inVal: addr(struct {
8722 D1 time.Duration `json:",format:units"`
8723 D2 time.Duration `json:",format:nano"`
8724 }{1, 1}),
8725 want: addr(struct {
8726 D1 time.Duration `json:",format:units"`
8727 D2 time.Duration `json:",format:nano"`
8728 }{0, 0}),
8729 }, {
8730 name: jsontest.Name("Duration/Zero"),
8731 inBuf: `{"D1":"0s","D2":0}`,
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/Positive"),
8742 inBuf: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
8743 inVal: new(struct {
8744 D1 time.Duration `json:",format:units"`
8745 D2 time.Duration `json:",format:nano"`
8746 }),
8747 want: addr(struct {
8748 D1 time.Duration `json:",format:units"`
8749 D2 time.Duration `json:",format:nano"`
8750 }{
8751 123456789123456789,
8752 123456789123456789,
8753 }),
8754 }, {
8755 name: jsontest.Name("Duration/Negative"),
8756 inBuf: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
8757 inVal: new(struct {
8758 D1 time.Duration `json:",format:units"`
8759 D2 time.Duration `json:",format:nano"`
8760 }),
8761 want: addr(struct {
8762 D1 time.Duration `json:",format:units"`
8763 D2 time.Duration `json:",format:nano"`
8764 }{
8765 -123456789123456789,
8766 -123456789123456789,
8767 }),
8768 }, {
8769 name: jsontest.Name("Duration/Nanos/String"),
8770 inBuf: `{"D":"12345"}`,
8771 inVal: addr(struct {
8772 D time.Duration `json:",string,format:nano"`
8773 }{1}),
8774 want: addr(struct {
8775 D time.Duration `json:",string,format:nano"`
8776 }{12345}),
8777 }, {
8778 name: jsontest.Name("Duration/Nanos/String/Invalid"),
8779 inBuf: `{"D":"+12345"}`,
8780 inVal: addr(struct {
8781 D time.Duration `json:",string,format:nano"`
8782 }{1}),
8783 want: addr(struct {
8784 D time.Duration `json:",string,format:nano"`
8785 }{1}),
8786 wantErr: EU(fmt.Errorf(`invalid duration "+12345": %w`, strconv.ErrSyntax)).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8787 }, {
8788 name: jsontest.Name("Duration/Nanos/Mismatch"),
8789 inBuf: `{"D":"34293h33m9.123456789s"}`,
8790 inVal: addr(struct {
8791 D time.Duration `json:",format:nano"`
8792 }{1}),
8793 want: addr(struct {
8794 D time.Duration `json:",format:nano"`
8795 }{1}),
8796 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8797 }, {
8798 name: jsontest.Name("Duration/Nanos"),
8799 inBuf: `{"D":1.324}`,
8800 inVal: addr(struct {
8801 D time.Duration `json:",format:nano"`
8802 }{-1}),
8803 want: addr(struct {
8804 D time.Duration `json:",format:nano"`
8805 }{1}),
8806 }, {
8807 name: jsontest.Name("Duration/String/Mismatch"),
8808 inBuf: `{"D":-123456789123456789}`,
8809 inVal: addr(struct {
8810 D time.Duration `json:",format:units"`
8811 }{1}),
8812 want: addr(struct {
8813 D time.Duration `json:",format:units"`
8814 }{1}),
8815 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('0', timeDurationType),
8816 }, {
8817 name: jsontest.Name("Duration/String/Invalid"),
8818 inBuf: `{"D":"5minkutes"}`,
8819 inVal: addr(struct {
8820 D time.Duration `json:",format:units"`
8821 }{1}),
8822 want: addr(struct {
8823 D time.Duration `json:",format:units"`
8824 }{1}),
8825 wantErr: EU(func() error {
8826 _, err := time.ParseDuration("5minkutes")
8827 return err
8828 }()).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8829 }, {
8830 name: jsontest.Name("Duration/Syntax/Invalid"),
8831 inBuf: `{"D":x}`,
8832 inVal: addr(struct {
8833 D time.Duration `json:",format:units"`
8834 }{1}),
8835 want: addr(struct {
8836 D time.Duration `json:",format:units"`
8837 }{1}),
8838 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"D":`), "/D"),
8839 }, {
8840 name: jsontest.Name("Duration/Format"),
8841 inBuf: `{
8842 "D1": "12h34m56.078090012s",
8843 "D2": "12h34m56.078090012s",
8844 "D3": 45296.078090012,
8845 "D4": "45296.078090012",
8846 "D5": 45296078.090012,
8847 "D6": "45296078.090012",
8848 "D7": 45296078090.012,
8849 "D8": "45296078090.012",
8850 "D9": 45296078090012,
8851 "D10": "45296078090012",
8852 "D11": "PT12H34M56.078090012S"
8853 }`,
8854 inVal: new(structDurationFormat),
8855 want: addr(structDurationFormat{
8856 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8857 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8858 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8859 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8860 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8861 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8862 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8863 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8864 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8865 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8866 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8867 }),
8868 }, {
8869 name: jsontest.Name("Duration/Format/Invalid"),
8870 inBuf: `{"D":"0s"}`,
8871 inVal: addr(struct {
8872 D time.Duration `json:",format:invalid"`
8873 }{1}),
8874 want: addr(struct {
8875 D time.Duration `json:",format:invalid"`
8876 }{1}),
8877 wantErr: EU(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, timeDurationType),
8878 }, {
8879
8889
8895 name: jsontest.Name("Duration/MapKey/Legacy"),
8896 opts: []Options{jsonflags.FormatTimeWithLegacySemantics | 1},
8897 inBuf: `{"1000000000":""}`,
8898 inVal: new(map[time.Duration]string),
8899 want: addr(map[time.Duration]string{time.Second: ""}),
8900 }, {
8901
8908 name: jsontest.Name("Time/Zero"),
8909 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"}`,
8910 inVal: new(struct {
8911 T1 time.Time
8912 T2 time.Time `json:",format:RFC822"`
8913 T3 time.Time `json:",format:'2006-01-02'"`
8914 T4 time.Time `json:",omitzero"`
8915 T5 time.Time `json:",omitempty"`
8916 }),
8917 want: addr(struct {
8918 T1 time.Time
8919 T2 time.Time `json:",format:RFC822"`
8920 T3 time.Time `json:",format:'2006-01-02'"`
8921 T4 time.Time `json:",omitzero"`
8922 T5 time.Time `json:",omitempty"`
8923 }{
8924 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8925 mustParseTime(time.RFC822, "01 Jan 01 00:00 UTC"),
8926 mustParseTime("2006-01-02", "0001-01-01"),
8927 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8928 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8929 }),
8930 }, {
8931 name: jsontest.Name("Time/Format"),
8932 inBuf: `{
8933 "T1": "1234-01-02T03:04:05.000000006Z",
8934 "T2": "Mon Jan 2 03:04:05 1234",
8935 "T3": "Mon Jan 2 03:04:05 UTC 1234",
8936 "T4": "Mon Jan 02 03:04:05 +0000 1234",
8937 "T5": "02 Jan 34 03:04 UTC",
8938 "T6": "02 Jan 34 03:04 +0000",
8939 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
8940 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
8941 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
8942 "T10": "1234-01-02T03:04:05Z",
8943 "T11": "1234-01-02T03:04:05.000000006Z",
8944 "T12": "3:04AM",
8945 "T13": "Jan 2 03:04:05",
8946 "T14": "Jan 2 03:04:05.000",
8947 "T15": "Jan 2 03:04:05.000000",
8948 "T16": "Jan 2 03:04:05.000000006",
8949 "T17": "1234-01-02 03:04:05",
8950 "T18": "1234-01-02",
8951 "T19": "03:04:05",
8952 "T20": "1234-01-02",
8953 "T21": "\"weird\"1234",
8954 "T22": -23225777754.999999994,
8955 "T23": "-23225777754.999999994",
8956 "T24": -23225777754999.999994,
8957 "T25": "-23225777754999.999994",
8958 "T26": -23225777754999999.994,
8959 "T27": "-23225777754999999.994",
8960 "T28": -23225777754999999994,
8961 "T29": "-23225777754999999994"
8962 }`,
8963 inVal: new(structTimeFormat),
8964 want: addr(structTimeFormat{
8965 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8966 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
8967 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
8968 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
8969 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
8970 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
8971 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
8972 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
8973 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
8974 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
8975 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8976 mustParseTime(time.Kitchen, "3:04AM"),
8977 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
8978 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
8979 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
8980 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
8981 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
8982 mustParseTime(time.DateOnly, "1234-01-02"),
8983 mustParseTime(time.TimeOnly, "03:04:05"),
8984 mustParseTime("2006-01-02", "1234-01-02"),
8985 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
8986 time.Unix(-23225777755, 6).UTC(),
8987 time.Unix(-23225777755, 6).UTC(),
8988 time.Unix(-23225777755, 6).UTC(),
8989 time.Unix(-23225777755, 6).UTC(),
8990 time.Unix(-23225777755, 6).UTC(),
8991 time.Unix(-23225777755, 6).UTC(),
8992 time.Unix(-23225777755, 6).UTC(),
8993 time.Unix(-23225777755, 6).UTC(),
8994 }),
8995 }, {
8996 name: jsontest.Name("Time/Format/UnixString/InvalidNumber"),
8997 inBuf: `{
8998 "T23": -23225777754.999999994,
8999 "T25": -23225777754999.999994,
9000 "T27": -23225777754999999.994,
9001 "T29": -23225777754999999994
9002 }`,
9003 inVal: new(structTimeFormat),
9004 want: new(structTimeFormat),
9005 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T23": `, "/T23").withType('0', timeTimeType),
9006 }, {
9007 name: jsontest.Name("Time/Format/UnixString/InvalidString"),
9008 inBuf: `{
9009 "T22": "-23225777754.999999994",
9010 "T24": "-23225777754999.999994",
9011 "T26": "-23225777754999999.994",
9012 "T28": "-23225777754999999994"
9013 }`,
9014 inVal: new(structTimeFormat),
9015 want: new(structTimeFormat),
9016 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T22": `, "/T22").withType('"', timeTimeType),
9017 }, {
9018 name: jsontest.Name("Time/Format/Null"),
9019 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}`,
9020 inVal: addr(structTimeFormat{
9021 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9022 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9023 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9024 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9025 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9026 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9027 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9028 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9029 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9030 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9031 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9032 mustParseTime(time.Kitchen, "3:04AM"),
9033 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9034 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9035 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9036 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9037 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9038 mustParseTime(time.DateOnly, "1234-01-02"),
9039 mustParseTime(time.TimeOnly, "03:04:05"),
9040 mustParseTime("2006-01-02", "1234-01-02"),
9041 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9042 time.Unix(-23225777755, 6).UTC(),
9043 time.Unix(-23225777755, 6).UTC(),
9044 time.Unix(-23225777755, 6).UTC(),
9045 time.Unix(-23225777755, 6).UTC(),
9046 time.Unix(-23225777755, 6).UTC(),
9047 time.Unix(-23225777755, 6).UTC(),
9048 time.Unix(-23225777755, 6).UTC(),
9049 time.Unix(-23225777755, 6).UTC(),
9050 }),
9051 want: new(structTimeFormat),
9052 }, {
9053 name: jsontest.Name("Time/RFC3339/Mismatch"),
9054 inBuf: `{"T":1234}`,
9055 inVal: new(struct {
9056 T time.Time
9057 }),
9058 wantErr: EU(nil).withPos(`{"T":`, "/T").withType('0', timeTimeType),
9059 }, {
9060 name: jsontest.Name("Time/RFC3339/ParseError"),
9061 inBuf: `{"T":"2021-09-29T12:44:52"}`,
9062 inVal: new(struct {
9063 T time.Time
9064 }),
9065 wantErr: EU(func() error {
9066 _, err := time.Parse(time.RFC3339, "2021-09-29T12:44:52")
9067 return err
9068 }()).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9069 }, {
9070 name: jsontest.Name("Time/Format/Invalid"),
9071 inBuf: `{"T":""}`,
9072 inVal: new(struct {
9073 T time.Time `json:",format:UndefinedConstant"`
9074 }),
9075 wantErr: EU(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
9076 }, {
9077 name: jsontest.Name("Time/Format/SingleDigitHour"),
9078 inBuf: `{"T":"2000-01-01T1:12:34Z"}`,
9079 inVal: new(struct{ T time.Time }),
9080 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T1:12:34Z", "15", "1", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9081 }, {
9082 name: jsontest.Name("Time/Format/SubsecondComma"),
9083 inBuf: `{"T":"2000-01-01T00:00:00,000Z"}`,
9084 inVal: new(struct{ T time.Time }),
9085 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00,000Z", ".", ",", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9086 }, {
9087 name: jsontest.Name("Time/Format/TimezoneHourOverflow"),
9088 inBuf: `{"T":"2000-01-01T00:00:00+24:00"}`,
9089 inVal: new(struct{ T time.Time }),
9090 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),
9091 }, {
9092 name: jsontest.Name("Time/Format/TimezoneMinuteOverflow"),
9093 inBuf: `{"T":"2000-01-01T00:00:00+00:60"}`,
9094 inVal: new(struct{ T time.Time }),
9095 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),
9096 }, {
9097 name: jsontest.Name("Time/Syntax/Invalid"),
9098 inBuf: `{"T":x}`,
9099 inVal: new(struct {
9100 T time.Time
9101 }),
9102 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"T":`), "/T"),
9103 }, {
9104 name: jsontest.Name("Time/IgnoreInvalidFormat"),
9105 opts: []Options{invalidFormatOption},
9106 inBuf: `"2000-01-01T00:00:00Z"`,
9107 inVal: addr(time.Time{}),
9108 want: addr(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)),
9109 }}
9110
9111 for _, tt := range tests {
9112 t.Run(tt.name.Name, func(t *testing.T) {
9113 got := tt.inVal
9114 gotErr := Unmarshal([]byte(tt.inBuf), got, tt.opts...)
9115 if !reflect.DeepEqual(got, tt.want) && tt.want != nil {
9116 t.Errorf("%s: Unmarshal output mismatch:\ngot %v\nwant %v", tt.name.Where, got, tt.want)
9117 }
9118 if !reflect.DeepEqual(gotErr, tt.wantErr) {
9119 t.Errorf("%s: Unmarshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
9120 }
9121 })
9122 }
9123 }
9124
9125 func TestMarshalInvalidNamespace(t *testing.T) {
9126 tests := []struct {
9127 name jsontest.CaseName
9128 val any
9129 }{
9130 {jsontest.Name("Map"), map[string]string{"X": "\xde\xad\xbe\xef"}},
9131 {jsontest.Name("Struct"), struct{ X string }{"\xde\xad\xbe\xef"}},
9132 }
9133 for _, tt := range tests {
9134 t.Run(tt.name.Name, func(t *testing.T) {
9135 enc := jsontext.NewEncoder(new(bytes.Buffer))
9136 if err := MarshalEncode(enc, tt.val); err == nil {
9137 t.Fatalf("%s: MarshalEncode error is nil, want non-nil", tt.name.Where)
9138 }
9139 for _, tok := range []jsontext.Token{
9140 jsontext.Null, jsontext.String(""), jsontext.Int(0), jsontext.BeginObject, jsontext.EndObject, jsontext.BeginArray, jsontext.EndArray,
9141 } {
9142 if err := enc.WriteToken(tok); err == nil {
9143 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9144 }
9145 }
9146 for _, val := range []string{`null`, `""`, `0`, `{}`, `[]`} {
9147 if err := enc.WriteValue([]byte(val)); err == nil {
9148 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9149 }
9150 }
9151 })
9152 }
9153 }
9154
9155 func TestUnmarshalInvalidNamespace(t *testing.T) {
9156 tests := []struct {
9157 name jsontest.CaseName
9158 val any
9159 }{
9160 {jsontest.Name("Map"), addr(map[string]int{})},
9161 {jsontest.Name("Struct"), addr(struct{ X int }{})},
9162 }
9163 for _, tt := range tests {
9164 t.Run(tt.name.Name, func(t *testing.T) {
9165 dec := jsontext.NewDecoder(strings.NewReader(`{"X":""}`))
9166 if err := UnmarshalDecode(dec, tt.val); err == nil {
9167 t.Fatalf("%s: UnmarshalDecode error is nil, want non-nil", tt.name.Where)
9168 }
9169 if _, err := dec.ReadToken(); err == nil {
9170 t.Fatalf("%s: ReadToken error is nil, want non-nil", tt.name.Where)
9171 }
9172 if _, err := dec.ReadValue(); err == nil {
9173 t.Fatalf("%s: ReadValue error is nil, want non-nil", tt.name.Where)
9174 }
9175 })
9176 }
9177 }
9178
9179 func TestUnmarshalReuse(t *testing.T) {
9180 t.Run("Bytes", func(t *testing.T) {
9181 in := make([]byte, 3)
9182 want := &in[0]
9183 if err := Unmarshal([]byte(`"AQID"`), &in); err != nil {
9184 t.Fatalf("Unmarshal error: %v", err)
9185 }
9186 got := &in[0]
9187 if got != want {
9188 t.Errorf("input buffer was not reused")
9189 }
9190 })
9191 t.Run("Slices", func(t *testing.T) {
9192 in := make([]int, 3)
9193 want := &in[0]
9194 if err := Unmarshal([]byte(`[0,1,2]`), &in); err != nil {
9195 t.Fatalf("Unmarshal error: %v", err)
9196 }
9197 got := &in[0]
9198 if got != want {
9199 t.Errorf("input slice was not reused")
9200 }
9201 })
9202 t.Run("Maps", func(t *testing.T) {
9203 in := make(map[string]string)
9204 want := reflect.ValueOf(in).Pointer()
9205 if err := Unmarshal([]byte(`{"key":"value"}`), &in); err != nil {
9206 t.Fatalf("Unmarshal error: %v", err)
9207 }
9208 got := reflect.ValueOf(in).Pointer()
9209 if got != want {
9210 t.Errorf("input map was not reused")
9211 }
9212 })
9213 t.Run("Pointers", func(t *testing.T) {
9214 in := addr(addr(addr("hello")))
9215 want := **in
9216 if err := Unmarshal([]byte(`"goodbye"`), &in); err != nil {
9217 t.Fatalf("Unmarshal error: %v", err)
9218 }
9219 got := **in
9220 if got != want {
9221 t.Errorf("input pointer was not reused")
9222 }
9223 })
9224 }
9225
9226 type ReaderFunc func([]byte) (int, error)
9227
9228 func (f ReaderFunc) Read(b []byte) (int, error) { return f(b) }
9229
9230 type WriterFunc func([]byte) (int, error)
9231
9232 func (f WriterFunc) Write(b []byte) (int, error) { return f(b) }
9233
9234 func TestCoderBufferGrowth(t *testing.T) {
9235
9236
9237 checkGrowth := func(ns []int) {
9238 t.Helper()
9239 var sumBytes, sumRates, numGrows float64
9240 prev := ns[0]
9241 for i := 1; i < len(ns)-1; i++ {
9242 n := ns[i]
9243 if n != prev {
9244 sumRates += float64(n) / float64(prev)
9245 numGrows++
9246 prev = n
9247 }
9248 if n > 1<<20 {
9249 t.Fatalf("single Read/Write too large: %d", n)
9250 }
9251 sumBytes += float64(n)
9252 }
9253 if mean := sumBytes / float64(len(ns)); mean < 1<<10 {
9254 t.Fatalf("average Read/Write too small: %0.1f", mean)
9255 }
9256 switch mean := sumRates / numGrows; {
9257 case mean < 1.25:
9258 t.Fatalf("average growth rate too slow: %0.3f", mean)
9259 case mean > 2.00:
9260 t.Fatalf("average growth rate too fast: %0.3f", mean)
9261 }
9262 }
9263
9264
9265
9266 bb := struct{ *bytes.Buffer }{new(bytes.Buffer)}
9267
9268 var writeSizes []int
9269 if err := MarshalWrite(WriterFunc(func(b []byte) (int, error) {
9270 n, err := bb.Write(b)
9271 writeSizes = append(writeSizes, n)
9272 return n, err
9273 }), make([]struct{}, 1e6)); err != nil {
9274 t.Fatalf("MarshalWrite error: %v", err)
9275 }
9276 checkGrowth(writeSizes)
9277
9278 var readSizes []int
9279 if err := UnmarshalRead(ReaderFunc(func(b []byte) (int, error) {
9280 n, err := bb.Read(b)
9281 readSizes = append(readSizes, n)
9282 return n, err
9283 }), new([]struct{})); err != nil {
9284 t.Fatalf("UnmarshalRead error: %v", err)
9285 }
9286 checkGrowth(readSizes)
9287 }
9288
9289 func TestUintSet(t *testing.T) {
9290 type operation any
9291 type has struct {
9292 in uint
9293 want bool
9294 }
9295 type insert struct {
9296 in uint
9297 want bool
9298 }
9299
9300
9301 ops := []operation{
9302 has{0, false},
9303 has{63, false},
9304 has{64, false},
9305 has{1234, false},
9306 insert{3, true},
9307 has{2, false},
9308 has{3, true},
9309 has{4, false},
9310 has{63, false},
9311 insert{3, false},
9312 insert{63, true},
9313 has{63, true},
9314 insert{64, true},
9315 insert{64, false},
9316 has{64, true},
9317 insert{3264, true},
9318 has{3264, true},
9319 insert{3, false},
9320 has{3, true},
9321 }
9322
9323 var us uintSet
9324 for i, op := range ops {
9325 switch op := op.(type) {
9326 case has:
9327 if got := us.has(op.in); got != op.want {
9328 t.Fatalf("%d: uintSet.has(%v) = %v, want %v", i, op.in, got, op.want)
9329 }
9330 case insert:
9331 if got := us.insert(op.in); got != op.want {
9332 t.Fatalf("%d: uintSet.insert(%v) = %v, want %v", i, op.in, got, op.want)
9333 }
9334 default:
9335 panic(fmt.Sprintf("unknown operation: %T", op))
9336 }
9337 }
9338 }
9339
9340 func TestUnmarshalDecodeOptions(t *testing.T) {
9341 var calledFuncs int
9342 var calledOptions Options
9343 in := strings.NewReader(strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9344 dec := jsontext.NewDecoder(in,
9345 jsontext.AllowInvalidUTF8(true),
9346 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ any) error {
9347 opts := dec.Options()
9348 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9349 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9350 }
9351 calledFuncs++
9352 calledOptions = opts
9353 return SkipFunc
9354 })),
9355 )
9356
9357 if err := UnmarshalDecode(dec, new(string)); err != nil {
9358 t.Fatalf("UnmarshalDecode: %v", err)
9359 }
9360 if calledFuncs != 1 {
9361 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9362 }
9363 if err := UnmarshalDecode(dec, new(string), calledOptions); err != nil {
9364 t.Fatalf("UnmarshalDecode: %v", err)
9365 }
9366 if calledFuncs != 2 {
9367 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9368 }
9369 if err := UnmarshalDecode(dec, new(string),
9370 jsontext.AllowInvalidUTF8(false),
9371 WithUnmarshalers(nil),
9372 ); err != nil {
9373 t.Fatalf("UnmarshalDecode: %v", err)
9374 }
9375 if calledFuncs != 2 {
9376 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9377 }
9378 if err := UnmarshalDecode(dec, new(string)); err != nil {
9379 t.Fatalf("UnmarshalDecode: %v", err)
9380 }
9381 if calledFuncs != 3 {
9382 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9383 }
9384 if err := UnmarshalDecode(dec, new(string), JoinOptions(
9385 jsontext.AllowInvalidUTF8(false),
9386 WithUnmarshalers(UnmarshalFromFunc(func(_ *jsontext.Decoder, _ any) error {
9387 opts := dec.Options()
9388 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9389 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9390 }
9391 calledFuncs = math.MaxInt
9392 return SkipFunc
9393 })),
9394 )); err != nil {
9395 t.Fatalf("UnmarshalDecode: %v", err)
9396 }
9397 if calledFuncs != math.MaxInt {
9398 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9399 }
9400
9401
9402
9403 opts := dec.Options()
9404 dec.Reset(in, jsontext.AllowInvalidUTF8(false), opts)
9405 if v, _ := GetOption(dec.Options(), jsontext.AllowInvalidUTF8); v == false {
9406 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9407 }
9408 }
9409
9410
9411
9412 func BenchmarkUnmarshalDecodeOptions(b *testing.B) {
9413 var i int
9414 in := new(bytes.Buffer)
9415 dec := jsontext.NewDecoder(in)
9416 makeBench := func(opts ...Options) func(*testing.B) {
9417 return func(b *testing.B) {
9418 for range b.N {
9419 in.WriteString("0 ")
9420 }
9421 dec.Reset(in)
9422 b.ResetTimer()
9423 for range b.N {
9424 UnmarshalDecode(dec, &i, opts...)
9425 }
9426 }
9427 }
9428 b.Run("None", makeBench())
9429 b.Run("Same", makeBench(&export.Decoder(dec).Struct))
9430 b.Run("New", makeBench(DefaultOptionsV2()))
9431 }
9432
9433 func TestMarshalEncodeOptions(t *testing.T) {
9434 var calledFuncs int
9435 var calledOptions Options
9436 out := new(bytes.Buffer)
9437 enc := jsontext.NewEncoder(
9438 out,
9439 jsontext.AllowInvalidUTF8(true),
9440 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9441 opts := enc.Options()
9442 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9443 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9444 }
9445 calledFuncs++
9446 calledOptions = opts
9447 return SkipFunc
9448 })),
9449 )
9450
9451 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9452 t.Fatalf("MarshalEncode: %v", err)
9453 }
9454 if calledFuncs != 1 {
9455 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9456 }
9457 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", calledOptions); err != nil {
9458 t.Fatalf("MarshalEncode: %v", err)
9459 }
9460 if calledFuncs != 2 {
9461 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9462 }
9463 if err := MarshalEncode(enc, "\xde\xad\xbe\xef",
9464 jsontext.AllowInvalidUTF8(false),
9465 WithMarshalers(nil),
9466 ); err != nil {
9467 t.Fatalf("MarshalEncode: %v", err)
9468 }
9469 if calledFuncs != 2 {
9470 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9471 }
9472 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9473 t.Fatalf("MarshalEncode: %v", err)
9474 }
9475 if calledFuncs != 3 {
9476 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9477 }
9478 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", JoinOptions(
9479 jsontext.AllowInvalidUTF8(false),
9480 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9481 opts := enc.Options()
9482 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9483 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9484 }
9485 calledFuncs = math.MaxInt
9486 return SkipFunc
9487 })),
9488 )); err != nil {
9489 t.Fatalf("MarshalEncode: %v", err)
9490 }
9491 if calledFuncs != math.MaxInt {
9492 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9493 }
9494 if out.String() != strings.Repeat("\"\xde\xad\ufffd\ufffd\"\n", 5) {
9495 t.Fatalf("output mismatch:\n\tgot: %s\n\twant: %s", out.String(), strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9496 }
9497
9498
9499
9500 opts := enc.Options()
9501 enc.Reset(out, jsontext.AllowInvalidUTF8(false), opts)
9502 if v, _ := GetOption(enc.Options(), jsontext.AllowInvalidUTF8); v == false {
9503 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9504 }
9505 }
9506
9507
9508
9509 func BenchmarkMarshalEncodeOptions(b *testing.B) {
9510 var i int
9511 out := new(bytes.Buffer)
9512 enc := jsontext.NewEncoder(out)
9513 makeBench := func(opts ...Options) func(*testing.B) {
9514 return func(b *testing.B) {
9515 out.Reset()
9516 enc.Reset(out)
9517 b.ResetTimer()
9518 for range b.N {
9519 MarshalEncode(enc, &i, opts...)
9520 }
9521 }
9522 }
9523 b.Run("None", makeBench())
9524 b.Run("Same", makeBench(&export.Encoder(enc).Struct))
9525 b.Run("New", makeBench(DefaultOptionsV2()))
9526 }
9527
View as plain text