1
2
3
4
5
6
7 package json
8
9 import (
10 "bytes"
11 "encoding"
12 "encoding/base32"
13 "encoding/base64"
14 "encoding/hex"
15 "errors"
16 "fmt"
17 "io"
18 "math"
19 "net"
20 "net/netip"
21 "reflect"
22 "strconv"
23 "strings"
24 "testing"
25 "time"
26
27 "encoding/json/internal"
28 "encoding/json/internal/jsonflags"
29 "encoding/json/internal/jsonopts"
30 "encoding/json/internal/jsontest"
31 "encoding/json/internal/jsonwire"
32 "encoding/json/jsontext"
33 )
34
35 func newNonStringNameError(offset int64, pointer jsontext.Pointer) error {
36 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsontext.ErrNonStringName}
37 }
38
39 func newInvalidCharacterError(prefix, where string, offset int64, pointer jsontext.Pointer) error {
40 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.NewInvalidCharacterError(prefix, where)}
41 }
42
43 func newInvalidUTF8Error(offset int64, pointer jsontext.Pointer) error {
44 return &jsontext.SyntacticError{ByteOffset: offset, JSONPointer: pointer, Err: jsonwire.ErrInvalidUTF8}
45 }
46
47 func newParseTimeError(layout, value, layoutElem, valueElem, message string) error {
48 return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message}
49 }
50
51 func EM(err error) *SemanticError {
52 return &SemanticError{action: "marshal", Err: err}
53 }
54
55 func EU(err error) *SemanticError {
56 return &SemanticError{action: "unmarshal", Err: err}
57 }
58
59 func (e *SemanticError) withVal(val string) *SemanticError {
60 e.JSONValue = jsontext.Value(val)
61 return e
62 }
63
64 func (e *SemanticError) withPos(prefix string, pointer jsontext.Pointer) *SemanticError {
65 e.ByteOffset = int64(len(prefix))
66 e.JSONPointer = pointer
67 return e
68 }
69
70 func (e *SemanticError) withType(k jsontext.Kind, t reflect.Type) *SemanticError {
71 e.JSONKind = k
72 e.GoType = t
73 return e
74 }
75
76 var (
77 errInvalidFormatFlag = errors.New(`invalid format flag "invalid"`)
78 errSomeError = errors.New("some error")
79 errMustNotCall = errors.New("must not call")
80 )
81
82 func T[T any]() reflect.Type { return reflect.TypeFor[T]() }
83
84 type (
85 jsonObject = map[string]any
86 jsonArray = []any
87
88 namedAny any
89 namedBool bool
90 namedString string
91 NamedString string
92 namedBytes []byte
93 namedInt64 int64
94 namedUint64 uint64
95 namedFloat64 float64
96 namedByte byte
97 netipAddr = netip.Addr
98
99 recursiveMap map[string]recursiveMap
100 recursiveSlice []recursiveSlice
101 recursivePointer struct{ P *recursivePointer }
102
103 structEmpty struct{}
104 structConflicting struct {
105 A string `json:"conflict"`
106 B string `json:"conflict"`
107 }
108 structNoneExported struct {
109 unexported string
110 }
111 structUnexportedIgnored struct {
112 ignored string `json:"-"`
113 }
114 structMalformedTag struct {
115 Malformed string `json:"\""`
116 }
117 structUnexportedTag struct {
118 unexported string `json:"name"`
119 }
120 structExportedEmbedded struct {
121 NamedString
122 }
123 structExportedEmbeddedTag struct {
124 NamedString `json:"name"`
125 }
126 structUnexportedEmbedded struct {
127 namedString
128 }
129 structUnexportedEmbeddedTag struct {
130 namedString `json:"name"`
131 }
132 structUnexportedEmbeddedMethodTag struct {
133
134
135 netipAddr `json:"name"`
136
137
138
139
140 }
141 structUnexportedEmbeddedStruct struct {
142 structOmitZeroAll
143 FizzBuzz int
144 structNestedAddr
145 }
146 structUnexportedEmbeddedStructPointer struct {
147 *structOmitZeroAll
148 FizzBuzz int
149 *structNestedAddr
150 }
151 structNestedAddr struct {
152 Addr netip.Addr
153 }
154 structIgnoredUnexportedEmbedded struct {
155 namedString `json:"-"`
156 }
157 structWeirdNames struct {
158 Empty string `json:"''"`
159 Comma string `json:"','"`
160 Quote string `json:"'\"'"`
161 }
162 structNoCase struct {
163 Aaa string `json:",case:strict"`
164 AA_A string
165 AaA string `json:",case:ignore"`
166 AAa string `json:",case:ignore"`
167 AAA string
168 }
169 structScalars struct {
170 unexported bool
171 Ignored bool `json:"-"`
172
173 Bool bool
174 String string
175 Bytes []byte
176 Int int64
177 Uint uint64
178 Float float64
179 }
180 structSlices struct {
181 unexported bool
182 Ignored bool `json:"-"`
183
184 SliceBool []bool
185 SliceString []string
186 SliceBytes [][]byte
187 SliceInt []int64
188 SliceUint []uint64
189 SliceFloat []float64
190 }
191 structMaps struct {
192 unexported bool
193 Ignored bool `json:"-"`
194
195 MapBool map[string]bool
196 MapString map[string]string
197 MapBytes map[string][]byte
198 MapInt map[string]int64
199 MapUint map[string]uint64
200 MapFloat map[string]float64
201 }
202 structAll struct {
203 Bool bool
204 String string
205 Bytes []byte
206 Int int64
207 Uint uint64
208 Float float64
209 Map map[string]string
210 StructScalars structScalars
211 StructMaps structMaps
212 StructSlices structSlices
213 Slice []string
214 Array [1]string
215 Pointer *structAll
216 Interface any
217 }
218 structStringifiedAll struct {
219 Bool bool `json:",string"`
220 String string `json:",string"`
221 Bytes []byte `json:",string"`
222 Int int64 `json:",string"`
223 Uint uint64 `json:",string"`
224 Float float64 `json:",string"`
225 Map map[string]string `json:",string"`
226 StructScalars structScalars `json:",string"`
227 StructMaps structMaps `json:",string"`
228 StructSlices structSlices `json:",string"`
229 Slice []string `json:",string"`
230 Array [1]string `json:",string"`
231 Pointer *structStringifiedAll `json:",string"`
232 Interface any `json:",string"`
233 }
234 structOmitZeroAll struct {
235 Bool bool `json:",omitzero"`
236 String string `json:",omitzero"`
237 Bytes []byte `json:",omitzero"`
238 Int int64 `json:",omitzero"`
239 Uint uint64 `json:",omitzero"`
240 Float float64 `json:",omitzero"`
241 Map map[string]string `json:",omitzero"`
242 StructScalars structScalars `json:",omitzero"`
243 StructMaps structMaps `json:",omitzero"`
244 StructSlices structSlices `json:",omitzero"`
245 Slice []string `json:",omitzero"`
246 Array [1]string `json:",omitzero"`
247 Pointer *structOmitZeroAll `json:",omitzero"`
248 Interface any `json:",omitzero"`
249 }
250 structOmitZeroMethodAll struct {
251 ValueAlwaysZero valueAlwaysZero `json:",omitzero"`
252 ValueNeverZero valueNeverZero `json:",omitzero"`
253 PointerAlwaysZero pointerAlwaysZero `json:",omitzero"`
254 PointerNeverZero pointerNeverZero `json:",omitzero"`
255 PointerValueAlwaysZero *valueAlwaysZero `json:",omitzero"`
256 PointerValueNeverZero *valueNeverZero `json:",omitzero"`
257 PointerPointerAlwaysZero *pointerAlwaysZero `json:",omitzero"`
258 PointerPointerNeverZero *pointerNeverZero `json:",omitzero"`
259 PointerPointerValueAlwaysZero **valueAlwaysZero `json:",omitzero"`
260 PointerPointerValueNeverZero **valueNeverZero `json:",omitzero"`
261 PointerPointerPointerAlwaysZero **pointerAlwaysZero `json:",omitzero"`
262 PointerPointerPointerNeverZero **pointerNeverZero `json:",omitzero"`
263 }
264 structOmitZeroMethodInterfaceAll struct {
265 ValueAlwaysZero isZeroer `json:",omitzero"`
266 ValueNeverZero isZeroer `json:",omitzero"`
267 PointerValueAlwaysZero isZeroer `json:",omitzero"`
268 PointerValueNeverZero isZeroer `json:",omitzero"`
269 PointerPointerAlwaysZero isZeroer `json:",omitzero"`
270 PointerPointerNeverZero isZeroer `json:",omitzero"`
271 }
272 structOmitEmptyAll struct {
273 Bool bool `json:",omitempty"`
274 PointerBool *bool `json:",omitempty"`
275 String string `json:",omitempty"`
276 StringEmpty stringMarshalEmpty `json:",omitempty"`
277 StringNonEmpty stringMarshalNonEmpty `json:",omitempty"`
278 PointerString *string `json:",omitempty"`
279 PointerStringEmpty *stringMarshalEmpty `json:",omitempty"`
280 PointerStringNonEmpty *stringMarshalNonEmpty `json:",omitempty"`
281 Bytes []byte `json:",omitempty"`
282 BytesEmpty bytesMarshalEmpty `json:",omitempty"`
283 BytesNonEmpty bytesMarshalNonEmpty `json:",omitempty"`
284 PointerBytes *[]byte `json:",omitempty"`
285 PointerBytesEmpty *bytesMarshalEmpty `json:",omitempty"`
286 PointerBytesNonEmpty *bytesMarshalNonEmpty `json:",omitempty"`
287 Float float64 `json:",omitempty"`
288 PointerFloat *float64 `json:",omitempty"`
289 Map map[string]string `json:",omitempty"`
290 MapEmpty mapMarshalEmpty `json:",omitempty"`
291 MapNonEmpty mapMarshalNonEmpty `json:",omitempty"`
292 PointerMap *map[string]string `json:",omitempty"`
293 PointerMapEmpty *mapMarshalEmpty `json:",omitempty"`
294 PointerMapNonEmpty *mapMarshalNonEmpty `json:",omitempty"`
295 Slice []string `json:",omitempty"`
296 SliceEmpty sliceMarshalEmpty `json:",omitempty"`
297 SliceNonEmpty sliceMarshalNonEmpty `json:",omitempty"`
298 PointerSlice *[]string `json:",omitempty"`
299 PointerSliceEmpty *sliceMarshalEmpty `json:",omitempty"`
300 PointerSliceNonEmpty *sliceMarshalNonEmpty `json:",omitempty"`
301 Pointer *structOmitZeroEmptyAll `json:",omitempty"`
302 Interface any `json:",omitempty"`
303 }
304 structOmitZeroEmptyAll struct {
305 Bool bool `json:",omitzero,omitempty"`
306 String string `json:",omitzero,omitempty"`
307 Bytes []byte `json:",omitzero,omitempty"`
308 Int int64 `json:",omitzero,omitempty"`
309 Uint uint64 `json:",omitzero,omitempty"`
310 Float float64 `json:",omitzero,omitempty"`
311 Map map[string]string `json:",omitzero,omitempty"`
312 Slice []string `json:",omitzero,omitempty"`
313 Array [1]string `json:",omitzero,omitempty"`
314 Pointer *structOmitZeroEmptyAll `json:",omitzero,omitempty"`
315 Interface any `json:",omitzero,omitempty"`
316 }
317 structFormatBytes struct {
318 Base16 []byte `json:",format:base16"`
319 Base32 []byte `json:",format:base32"`
320 Base32Hex []byte `json:",format:base32hex"`
321 Base64 []byte `json:",format:base64"`
322 Base64URL []byte `json:",format:base64url"`
323 Array []byte `json:",format:array"`
324 }
325 structFormatArrayBytes struct {
326 Base16 [4]byte `json:",format:base16"`
327 Base32 [4]byte `json:",format:base32"`
328 Base32Hex [4]byte `json:",format:base32hex"`
329 Base64 [4]byte `json:",format:base64"`
330 Base64URL [4]byte `json:",format:base64url"`
331 Array [4]byte `json:",format:array"`
332 Default [4]byte
333 }
334 structFormatFloats struct {
335 NonFinite float64 `json:",format:nonfinite"`
336 PointerNonFinite *float64 `json:",format:nonfinite"`
337 }
338 structFormatMaps struct {
339 EmitNull map[string]string `json:",format:emitnull"`
340 PointerEmitNull *map[string]string `json:",format:emitnull"`
341 EmitEmpty map[string]string `json:",format:emitempty"`
342 PointerEmitEmpty *map[string]string `json:",format:emitempty"`
343 EmitDefault map[string]string
344 PointerEmitDefault *map[string]string
345 }
346 structFormatSlices struct {
347 EmitNull []string `json:",format:emitnull"`
348 PointerEmitNull *[]string `json:",format:emitnull"`
349 EmitEmpty []string `json:",format:emitempty"`
350 PointerEmitEmpty *[]string `json:",format:emitempty"`
351 EmitDefault []string
352 PointerEmitDefault *[]string
353 }
354 structFormatInvalid struct {
355 Bool bool `json:",omitzero,format:invalid"`
356 String string `json:",omitzero,format:invalid"`
357 Bytes []byte `json:",omitzero,format:invalid"`
358 Int int64 `json:",omitzero,format:invalid"`
359 Uint uint64 `json:",omitzero,format:invalid"`
360 Float float64 `json:",omitzero,format:invalid"`
361 Map map[string]string `json:",omitzero,format:invalid"`
362 Struct structAll `json:",omitzero,format:invalid"`
363 Slice []string `json:",omitzero,format:invalid"`
364 Array [1]string `json:",omitzero,format:invalid"`
365 Interface any `json:",omitzero,format:invalid"`
366 }
367 structDurationFormat struct {
368 D1 time.Duration `json:",format:units"`
369 D2 time.Duration `json:",format:units"`
370 D3 time.Duration `json:",format:sec"`
371 D4 time.Duration `json:",string,format:sec"`
372 D5 time.Duration `json:",format:milli"`
373 D6 time.Duration `json:",string,format:milli"`
374 D7 time.Duration `json:",format:micro"`
375 D8 time.Duration `json:",string,format:micro"`
376 D9 time.Duration `json:",format:nano"`
377 D10 time.Duration `json:",string,format:nano"`
378 D11 time.Duration `json:",format:iso8601"`
379 }
380 structTimeFormat struct {
381 T1 time.Time
382 T2 time.Time `json:",format:ANSIC"`
383 T3 time.Time `json:",format:UnixDate"`
384 T4 time.Time `json:",format:RubyDate"`
385 T5 time.Time `json:",format:RFC822"`
386 T6 time.Time `json:",format:RFC822Z"`
387 T7 time.Time `json:",format:RFC850"`
388 T8 time.Time `json:",format:RFC1123"`
389 T9 time.Time `json:",format:RFC1123Z"`
390 T10 time.Time `json:",format:RFC3339"`
391 T11 time.Time `json:",format:RFC3339Nano"`
392 T12 time.Time `json:",format:Kitchen"`
393 T13 time.Time `json:",format:Stamp"`
394 T14 time.Time `json:",format:StampMilli"`
395 T15 time.Time `json:",format:StampMicro"`
396 T16 time.Time `json:",format:StampNano"`
397 T17 time.Time `json:",format:DateTime"`
398 T18 time.Time `json:",format:DateOnly"`
399 T19 time.Time `json:",format:TimeOnly"`
400 T20 time.Time `json:",format:'2006-01-02'"`
401 T21 time.Time `json:",format:'\"weird\"2006'"`
402 T22 time.Time `json:",format:unix"`
403 T23 time.Time `json:",string,format:unix"`
404 T24 time.Time `json:",format:unixmilli"`
405 T25 time.Time `json:",string,format:unixmilli"`
406 T26 time.Time `json:",format:unixmicro"`
407 T27 time.Time `json:",string,format:unixmicro"`
408 T28 time.Time `json:",format:unixnano"`
409 T29 time.Time `json:",string,format:unixnano"`
410 }
411 structInlined struct {
412 X structInlinedL1 `json:",inline"`
413 *StructEmbed2
414 }
415 structInlinedL1 struct {
416 X *structInlinedL2 `json:",inline"`
417 StructEmbed1 `json:",inline"`
418 }
419 structInlinedL2 struct{ A, B, C string }
420 StructEmbed1 struct{ C, D, E string }
421 StructEmbed2 struct{ E, F, G string }
422 structUnknownTextValue struct {
423 A int `json:",omitzero"`
424 X jsontext.Value `json:",unknown"`
425 B int `json:",omitzero"`
426 }
427 structInlineTextValue struct {
428 A int `json:",omitzero"`
429 X jsontext.Value `json:",inline"`
430 B int `json:",omitzero"`
431 }
432 structInlinePointerTextValue struct {
433 A int `json:",omitzero"`
434 X *jsontext.Value `json:",inline"`
435 B int `json:",omitzero"`
436 }
437 structInlinePointerInlineTextValue struct {
438 X *struct {
439 A int
440 X jsontext.Value `json:",inline"`
441 } `json:",inline"`
442 }
443 structInlineInlinePointerTextValue struct {
444 X struct {
445 X *jsontext.Value `json:",inline"`
446 } `json:",inline"`
447 }
448 structInlineMapStringAny struct {
449 A int `json:",omitzero"`
450 X jsonObject `json:",inline"`
451 B int `json:",omitzero"`
452 }
453 structInlinePointerMapStringAny struct {
454 A int `json:",omitzero"`
455 X *jsonObject `json:",inline"`
456 B int `json:",omitzero"`
457 }
458 structInlinePointerInlineMapStringAny struct {
459 X *struct {
460 A int
461 X jsonObject `json:",inline"`
462 } `json:",inline"`
463 }
464 structInlineInlinePointerMapStringAny struct {
465 X struct {
466 X *jsonObject `json:",inline"`
467 } `json:",inline"`
468 }
469 structInlineMapStringInt struct {
470 X map[string]int `json:",inline"`
471 }
472 structInlineMapNamedStringInt struct {
473 X map[namedString]int `json:",inline"`
474 }
475 structInlineMapNamedStringAny struct {
476 A int `json:",omitzero"`
477 X map[namedString]any `json:",inline"`
478 B int `json:",omitzero"`
479 }
480 structNoCaseInlineTextValue struct {
481 AAA string `json:",omitempty,case:strict"`
482 AA_b string `json:",omitempty"`
483 AaA string `json:",omitempty,case:ignore"`
484 AAa string `json:",omitempty,case:ignore"`
485 Aaa string `json:",omitempty"`
486 X jsontext.Value `json:",inline"`
487 }
488 structNoCaseInlineMapStringAny struct {
489 AAA string `json:",omitempty"`
490 AaA string `json:",omitempty,case:ignore"`
491 AAa string `json:",omitempty,case:ignore"`
492 Aaa string `json:",omitempty"`
493 X jsonObject `json:",inline"`
494 }
495
496 allMethods struct {
497 method string
498 value []byte
499 }
500 allMethodsExceptJSONv2 struct {
501 allMethods
502 MarshalJSONTo struct{}
503 UnmarshalJSONFrom struct{}
504 }
505 allMethodsExceptJSONv1 struct {
506 allMethods
507 MarshalJSON struct{}
508 UnmarshalJSON struct{}
509 }
510 allMethodsExceptText struct {
511 allMethods
512 MarshalText struct{}
513 UnmarshalText struct{}
514 }
515 onlyMethodJSONv2 struct {
516 allMethods
517 MarshalJSON struct{}
518 UnmarshalJSON struct{}
519 MarshalText struct{}
520 UnmarshalText struct{}
521 }
522 onlyMethodJSONv1 struct {
523 allMethods
524 MarshalJSONTo struct{}
525 UnmarshalJSONFrom struct{}
526 MarshalText struct{}
527 UnmarshalText struct{}
528 }
529 onlyMethodText struct {
530 allMethods
531 MarshalJSONTo struct{}
532 UnmarshalJSONFrom struct{}
533 MarshalJSON struct{}
534 UnmarshalJSON struct{}
535 }
536
537 structMethodJSONv2 struct{ value string }
538 structMethodJSONv1 struct{ value string }
539 structMethodText struct{ value string }
540
541 marshalJSONv2Func func(*jsontext.Encoder) error
542 marshalJSONv1Func func() ([]byte, error)
543 appendTextFunc func([]byte) ([]byte, error)
544 marshalTextFunc func() ([]byte, error)
545 unmarshalJSONv2Func func(*jsontext.Decoder) error
546 unmarshalJSONv1Func func([]byte) error
547 unmarshalTextFunc func([]byte) error
548
549 nocaseString string
550
551 stringMarshalEmpty string
552 stringMarshalNonEmpty string
553 bytesMarshalEmpty []byte
554 bytesMarshalNonEmpty []byte
555 mapMarshalEmpty map[string]string
556 mapMarshalNonEmpty map[string]string
557 sliceMarshalEmpty []string
558 sliceMarshalNonEmpty []string
559
560 valueAlwaysZero string
561 valueNeverZero string
562 pointerAlwaysZero string
563 pointerNeverZero string
564
565 valueStringer struct{}
566 pointerStringer struct{}
567
568 cyclicA struct {
569 B1 cyclicB `json:",inline"`
570 B2 cyclicB `json:",inline"`
571 }
572 cyclicB struct {
573 F int
574 A *cyclicA `json:",inline"`
575 }
576 )
577
578 func (structUnexportedEmbeddedMethodTag) MarshalText() {}
579 func (structUnexportedEmbeddedMethodTag) AppendText() {}
580
581 func (p *allMethods) MarshalJSONTo(enc *jsontext.Encoder) error {
582 if got, want := "MarshalJSONTo", p.method; got != want {
583 return fmt.Errorf("called wrong method: got %v, want %v", got, want)
584 }
585 return enc.WriteValue(p.value)
586 }
587 func (p *allMethods) MarshalJSON() ([]byte, error) {
588 if got, want := "MarshalJSON", p.method; got != want {
589 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
590 }
591 return p.value, nil
592 }
593 func (p *allMethods) MarshalText() ([]byte, error) {
594 if got, want := "MarshalText", p.method; got != want {
595 return nil, fmt.Errorf("called wrong method: got %v, want %v", got, want)
596 }
597 return p.value, nil
598 }
599
600 func (p *allMethods) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
601 p.method = "UnmarshalJSONFrom"
602 val, err := dec.ReadValue()
603 p.value = val
604 return err
605 }
606 func (p *allMethods) UnmarshalJSON(val []byte) error {
607 p.method = "UnmarshalJSON"
608 p.value = val
609 return nil
610 }
611 func (p *allMethods) UnmarshalText(val []byte) error {
612 p.method = "UnmarshalText"
613 p.value = val
614 return nil
615 }
616
617 func (s structMethodJSONv2) MarshalJSONTo(enc *jsontext.Encoder) error {
618 return enc.WriteToken(jsontext.String(s.value))
619 }
620 func (s *structMethodJSONv2) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
621 tok, err := dec.ReadToken()
622 if err != nil {
623 return err
624 }
625 if k := tok.Kind(); k != '"' {
626 return EU(nil).withType(k, T[structMethodJSONv2]())
627 }
628 s.value = tok.String()
629 return nil
630 }
631
632 func (s structMethodJSONv1) MarshalJSON() ([]byte, error) {
633 return jsontext.AppendQuote(nil, s.value)
634 }
635 func (s *structMethodJSONv1) UnmarshalJSON(b []byte) error {
636 if k := jsontext.Value(b).Kind(); k != '"' {
637 return EU(nil).withType(k, T[structMethodJSONv1]())
638 }
639 b, _ = jsontext.AppendUnquote(nil, b)
640 s.value = string(b)
641 return nil
642 }
643
644 func (s structMethodText) MarshalText() ([]byte, error) {
645 return []byte(s.value), nil
646 }
647 func (s *structMethodText) UnmarshalText(b []byte) error {
648 s.value = string(b)
649 return nil
650 }
651
652 func (f marshalJSONv2Func) MarshalJSONTo(enc *jsontext.Encoder) error {
653 return f(enc)
654 }
655 func (f marshalJSONv1Func) MarshalJSON() ([]byte, error) {
656 return f()
657 }
658 func (f appendTextFunc) AppendText(b []byte) ([]byte, error) {
659 return f(b)
660 }
661 func (f marshalTextFunc) MarshalText() ([]byte, error) {
662 return f()
663 }
664 func (f unmarshalJSONv2Func) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
665 return f(dec)
666 }
667 func (f unmarshalJSONv1Func) UnmarshalJSON(b []byte) error {
668 return f(b)
669 }
670 func (f unmarshalTextFunc) UnmarshalText(b []byte) error {
671 return f(b)
672 }
673
674 func (k nocaseString) MarshalText() ([]byte, error) {
675 return []byte(strings.ToLower(string(k))), nil
676 }
677 func (k *nocaseString) UnmarshalText(b []byte) error {
678 *k = nocaseString(strings.ToLower(string(b)))
679 return nil
680 }
681
682 func (stringMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`""`), nil }
683 func (stringMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`"value"`), nil }
684 func (bytesMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
685 func (bytesMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
686 func (mapMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`{}`), nil }
687 func (mapMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`{"key":"value"}`), nil }
688 func (sliceMarshalEmpty) MarshalJSON() ([]byte, error) { return []byte(`[]`), nil }
689 func (sliceMarshalNonEmpty) MarshalJSON() ([]byte, error) { return []byte(`["value"]`), nil }
690
691 func (valueAlwaysZero) IsZero() bool { return true }
692 func (valueNeverZero) IsZero() bool { return false }
693 func (*pointerAlwaysZero) IsZero() bool { return true }
694 func (*pointerNeverZero) IsZero() bool { return false }
695
696 func (valueStringer) String() string { return "" }
697 func (*pointerStringer) String() string { return "" }
698
699 func addr[T any](v T) *T {
700 return &v
701 }
702
703 func mustParseTime(layout, value string) time.Time {
704 t, err := time.Parse(layout, value)
705 if err != nil {
706 panic(err)
707 }
708 return t
709 }
710
711 var invalidFormatOption = &jsonopts.Struct{
712 ArshalValues: jsonopts.ArshalValues{FormatDepth: 1000, Format: "invalid"},
713 }
714
715 func TestMarshal(t *testing.T) {
716 tests := []struct {
717 name jsontest.CaseName
718 opts []Options
719 in any
720 want string
721 wantErr error
722
723 canonicalize bool
724 useWriter bool
725 }{{
726 name: jsontest.Name("Nil"),
727 in: nil,
728 want: `null`,
729 }, {
730 name: jsontest.Name("Bools"),
731 in: []bool{false, true},
732 want: `[false,true]`,
733 }, {
734 name: jsontest.Name("Bools/Named"),
735 in: []namedBool{false, true},
736 want: `[false,true]`,
737 }, {
738 name: jsontest.Name("Bools/NotStringified"),
739 opts: []Options{StringifyNumbers(true)},
740 in: []bool{false, true},
741 want: `[false,true]`,
742 }, {
743 name: jsontest.Name("Bools/StringifiedBool"),
744 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
745 in: []bool{false, true},
746 want: `["false","true"]`,
747 }, {
748 name: jsontest.Name("Bools/IgnoreInvalidFormat"),
749 opts: []Options{invalidFormatOption},
750 in: true,
751 want: `true`,
752 }, {
753 name: jsontest.Name("Strings"),
754 in: []string{"", "hello", "世界"},
755 want: `["","hello","世界"]`,
756 }, {
757 name: jsontest.Name("Strings/Named"),
758 in: []namedString{"", "hello", "世界"},
759 want: `["","hello","世界"]`,
760 }, {
761 name: jsontest.Name("Strings/StringifiedBool"),
762 opts: []Options{jsonflags.StringifyBoolsAndStrings | 1},
763 in: []string{"", "hello", "世界"},
764 want: `["\"\"","\"hello\"","\"世界\""]`,
765 }, {
766 name: jsontest.Name("Strings/IgnoreInvalidFormat"),
767 opts: []Options{invalidFormatOption},
768 in: "string",
769 want: `"string"`,
770 }, {
771 name: jsontest.Name("Bytes"),
772 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
773 want: `["","","AQ==","AQI=","AQID"]`,
774 }, {
775 name: jsontest.Name("Bytes/FormatNilSliceAsNull"),
776 opts: []Options{FormatNilSliceAsNull(true)},
777 in: [][]byte{nil, {}},
778 want: `[null,""]`,
779 }, {
780 name: jsontest.Name("Bytes/Large"),
781 in: []byte("the quick brown fox jumped over the lazy dog and ate the homework that I spent so much time on."),
782 want: `"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cgYW5kIGF0ZSB0aGUgaG9tZXdvcmsgdGhhdCBJIHNwZW50IHNvIG11Y2ggdGltZSBvbi4="`,
783 }, {
784 name: jsontest.Name("Bytes/Named"),
785 in: []namedBytes{nil, {}, {1}, {1, 2}, {1, 2, 3}},
786 want: `["","","AQ==","AQI=","AQID"]`,
787 }, {
788 name: jsontest.Name("Bytes/NotStringified"),
789 opts: []Options{StringifyNumbers(true)},
790 in: [][]byte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
791 want: `["","","AQ==","AQI=","AQID"]`,
792 }, {
793
794
795 name: jsontest.Name("Bytes/Invariant"),
796 in: [][]namedByte{nil, {}, {1}, {1, 2}, {1, 2, 3}},
797 want: `[[],[],[1],[1,2],[1,2,3]]`,
798 }, {
799
800
801 name: jsontest.Name("Bytes/ByteArray"),
802 in: [5]byte{'h', 'e', 'l', 'l', 'o'},
803 want: `"aGVsbG8="`,
804 }, {
805
806
807 name: jsontest.Name("Bytes/NamedByteArray"),
808 in: [5]namedByte{'h', 'e', 'l', 'l', 'o'},
809 want: `[104,101,108,108,111]`,
810 }, {
811 name: jsontest.Name("Bytes/IgnoreInvalidFormat"),
812 opts: []Options{invalidFormatOption},
813 in: []byte("hello"),
814 want: `"aGVsbG8="`,
815 }, {
816 name: jsontest.Name("Ints"),
817 in: []any{
818 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
819 },
820 want: `[0,-128,-32768,-2147483648,-9223372036854775808,-6464]`,
821 }, {
822 name: jsontest.Name("Ints/Stringified"),
823 opts: []Options{StringifyNumbers(true)},
824 in: []any{
825 int(0), int8(math.MinInt8), int16(math.MinInt16), int32(math.MinInt32), int64(math.MinInt64), namedInt64(-6464),
826 },
827 want: `["0","-128","-32768","-2147483648","-9223372036854775808","-6464"]`,
828 }, {
829 name: jsontest.Name("Ints/IgnoreInvalidFormat"),
830 opts: []Options{invalidFormatOption},
831 in: int(0),
832 want: `0`,
833 }, {
834 name: jsontest.Name("Uints"),
835 in: []any{
836 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464), uintptr(1234),
837 },
838 want: `[0,255,65535,4294967295,18446744073709551615,6464,1234]`,
839 }, {
840 name: jsontest.Name("Uints/Stringified"),
841 opts: []Options{StringifyNumbers(true)},
842 in: []any{
843 uint(0), uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64), namedUint64(6464),
844 },
845 want: `["0","255","65535","4294967295","18446744073709551615","6464"]`,
846 }, {
847 name: jsontest.Name("Uints/IgnoreInvalidFormat"),
848 opts: []Options{invalidFormatOption},
849 in: uint(0),
850 want: `0`,
851 }, {
852 name: jsontest.Name("Floats"),
853 in: []any{
854 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
855 },
856 want: `[3.4028235e+38,1.7976931348623157e+308,64.64]`,
857 }, {
858 name: jsontest.Name("Floats/Stringified"),
859 opts: []Options{StringifyNumbers(true)},
860 in: []any{
861 float32(math.MaxFloat32), float64(math.MaxFloat64), namedFloat64(64.64),
862 },
863 want: `["3.4028235e+38","1.7976931348623157e+308","64.64"]`,
864 }, {
865 name: jsontest.Name("Floats/Invalid/NaN"),
866 opts: []Options{StringifyNumbers(true)},
867 in: math.NaN(),
868 wantErr: EM(fmt.Errorf("unsupported value: %v", math.NaN())).withType(0, float64Type),
869 }, {
870 name: jsontest.Name("Floats/Invalid/PositiveInfinity"),
871 in: math.Inf(+1),
872 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(+1))).withType(0, float64Type),
873 }, {
874 name: jsontest.Name("Floats/Invalid/NegativeInfinity"),
875 in: math.Inf(-1),
876 wantErr: EM(fmt.Errorf("unsupported value: %v", math.Inf(-1))).withType(0, float64Type),
877 }, {
878 name: jsontest.Name("Floats/IgnoreInvalidFormat"),
879 opts: []Options{invalidFormatOption},
880 in: float64(0),
881 want: `0`,
882 }, {
883 name: jsontest.Name("Maps/InvalidKey/Bool"),
884 in: map[bool]string{false: "value"},
885 want: `{`,
886 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, boolType),
887 }, {
888 name: jsontest.Name("Maps/InvalidKey/NamedBool"),
889 in: map[namedBool]string{false: "value"},
890 want: `{`,
891 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[namedBool]()),
892 }, {
893 name: jsontest.Name("Maps/InvalidKey/Array"),
894 in: map[[1]string]string{{"key"}: "value"},
895 want: `{`,
896 wantErr: EM(newNonStringNameError(len64(`{`), "")).withPos(`{`, "").withType(0, T[[1]string]()),
897 }, {
898 name: jsontest.Name("Maps/InvalidKey/Channel"),
899 in: map[chan string]string{make(chan string): "value"},
900 want: `{`,
901 wantErr: EM(nil).withPos(`{`, "").withType(0, T[chan string]()),
902 }, {
903 name: jsontest.Name("Maps/ValidKey/Int"),
904 in: map[int64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
905 canonicalize: true,
906 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
907 }, {
908 name: jsontest.Name("Maps/ValidKey/PointerInt"),
909 in: map[*int64]string{addr(int64(math.MinInt64)): "MinInt64", addr(int64(0)): "Zero", addr(int64(math.MaxInt64)): "MaxInt64"},
910 canonicalize: true,
911 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
912 }, {
913 name: jsontest.Name("Maps/DuplicateName/PointerInt"),
914 in: map[*int64]string{addr(int64(0)): "0", addr(int64(0)): "0"},
915 canonicalize: true,
916 want: `{"0":"0"`,
917 wantErr: newDuplicateNameError("", []byte(`"0"`), len64(`{"0":"0",`)),
918 }, {
919 name: jsontest.Name("Maps/ValidKey/NamedInt"),
920 in: map[namedInt64]string{math.MinInt64: "MinInt64", 0: "Zero", math.MaxInt64: "MaxInt64"},
921 canonicalize: true,
922 want: `{"-9223372036854775808":"MinInt64","0":"Zero","9223372036854775807":"MaxInt64"}`,
923 }, {
924 name: jsontest.Name("Maps/ValidKey/Uint"),
925 in: map[uint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
926 canonicalize: true,
927 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
928 }, {
929 name: jsontest.Name("Maps/ValidKey/NamedUint"),
930 in: map[namedUint64]string{0: "Zero", math.MaxUint64: "MaxUint64"},
931 canonicalize: true,
932 want: `{"0":"Zero","18446744073709551615":"MaxUint64"}`,
933 }, {
934 name: jsontest.Name("Maps/ValidKey/Float"),
935 in: map[float64]string{3.14159: "value"},
936 want: `{"3.14159":"value"}`,
937 }, {
938 name: jsontest.Name("Maps/InvalidKey/Float/NaN"),
939 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
940 want: `{`,
941 wantErr: EM(errors.New("unsupported value: NaN")).withPos(`{`, "").withType(0, float64Type),
942 }, {
943 name: jsontest.Name("Maps/ValidKey/Interface"),
944 in: map[any]any{
945 "key": "key",
946 namedInt64(-64): int32(-32),
947 namedUint64(+64): uint32(+32),
948 namedFloat64(64.64): float32(32.32),
949 },
950 canonicalize: true,
951 want: `{"-64":-32,"64":32,"64.64":32.32,"key":"key"}`,
952 }, {
953 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8+AllowDuplicateNames"),
954 opts: []Options{jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
955 in: map[string]string{"\x80": "", "\x81": ""},
956 want: `{"�":"","�":""}`,
957 }, {
958 name: jsontest.Name("Maps/DuplicateName/String/AllowInvalidUTF8"),
959 opts: []Options{jsontext.AllowInvalidUTF8(true)},
960 in: map[string]string{"\x80": "", "\x81": ""},
961 want: `{"�":""`,
962 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":"",`)),
963 }, {
964 name: jsontest.Name("Maps/DuplicateName/NoCaseString/AllowDuplicateNames"),
965 opts: []Options{jsontext.AllowDuplicateNames(true)},
966 in: map[nocaseString]string{"hello": "", "HELLO": ""},
967 want: `{"hello":"","hello":""}`,
968 }, {
969 name: jsontest.Name("Maps/DuplicateName/NoCaseString"),
970 in: map[nocaseString]string{"hello": "", "HELLO": ""},
971 want: `{"hello":""`,
972 wantErr: EM(newDuplicateNameError("", []byte(`"hello"`), len64(`{"hello":"",`))).withPos(`{"hello":"",`, "").withType(0, T[nocaseString]()),
973 }, {
974 name: jsontest.Name("Maps/DuplicateName/NaNs/Deterministic+AllowDuplicateNames"),
975 opts: []Options{
976 WithMarshalers(
977 MarshalFunc(func(v float64) ([]byte, error) { return []byte(`"NaN"`), nil }),
978 ),
979 Deterministic(true),
980 jsontext.AllowDuplicateNames(true),
981 },
982 in: map[float64]string{math.NaN(): "NaN", math.NaN(): "NaN"},
983 want: `{"NaN":"NaN","NaN":"NaN"}`,
984 }, {
985 name: jsontest.Name("Maps/InvalidValue/Channel"),
986 in: map[string]chan string{
987 "key": nil,
988 },
989 want: `{"key"`,
990 wantErr: EM(nil).withPos(`{"key":`, "/key").withType(0, T[chan string]()),
991 }, {
992 name: jsontest.Name("Maps/String/Deterministic"),
993 opts: []Options{Deterministic(true)},
994 in: map[string]int{"a": 0, "b": 1, "c": 2},
995 want: `{"a":0,"b":1,"c":2}`,
996 }, {
997 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
998 opts: []Options{
999 Deterministic(true),
1000 jsontext.AllowInvalidUTF8(true),
1001 jsontext.AllowDuplicateNames(false),
1002 },
1003 in: map[string]int{"\xff": 0, "\xfe": 1},
1004 want: `{"�":1`,
1005 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1,`)),
1006 }, {
1007 name: jsontest.Name("Maps/String/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
1008 opts: []Options{
1009 Deterministic(true),
1010 jsontext.AllowInvalidUTF8(true),
1011 jsontext.AllowDuplicateNames(true),
1012 },
1013 in: map[string]int{"\xff": 0, "\xfe": 1},
1014 want: `{"�":1,"�":0}`,
1015 }, {
1016 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs"),
1017 opts: []Options{
1018 Deterministic(true),
1019 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1020 if p := enc.StackPointer(); p != "/X" {
1021 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1022 }
1023 switch v {
1024 case "a":
1025 return enc.WriteToken(jsontext.String("b"))
1026 case "b":
1027 return enc.WriteToken(jsontext.String("a"))
1028 default:
1029 return fmt.Errorf("invalid value: %q", v)
1030 }
1031 })),
1032 },
1033 in: map[namedString]map[string]int{"X": {"a": -1, "b": 1}},
1034 want: `{"X":{"a":1,"b":-1}}`,
1035 }, {
1036 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+RejectDuplicateNames"),
1037 opts: []Options{
1038 Deterministic(true),
1039 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1040 if p := enc.StackPointer(); p != "/X" {
1041 return fmt.Errorf("invalid stack pointer: got %s, want /X", p)
1042 }
1043 switch v {
1044 case "a", "b":
1045 return enc.WriteToken(jsontext.String("x"))
1046 default:
1047 return fmt.Errorf("invalid value: %q", v)
1048 }
1049 })),
1050 jsontext.AllowDuplicateNames(false),
1051 },
1052 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1053 want: `{"X":{"x":1`,
1054 wantErr: newDuplicateNameError("/X/x", nil, len64(`{"X":{"x":1,`)),
1055 }, {
1056 name: jsontest.Name("Maps/String/Deterministic+MarshalFuncs+AllowDuplicateNames"),
1057 opts: []Options{
1058 Deterministic(true),
1059 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, v string) error {
1060 if p := enc.StackPointer(); p != "/X" {
1061 return fmt.Errorf("invalid stack pointer: got %s, want /0", p)
1062 }
1063 switch v {
1064 case "a", "b":
1065 return enc.WriteToken(jsontext.String("x"))
1066 default:
1067 return fmt.Errorf("invalid value: %q", v)
1068 }
1069 })),
1070 jsontext.AllowDuplicateNames(true),
1071 },
1072 in: map[namedString]map[string]int{"X": {"a": 1, "b": 1}},
1073
1074
1075 want: `{"X":{"x":1,"x":1}}`,
1076 }, {
1077 name: jsontest.Name("Maps/RecursiveMap"),
1078 in: recursiveMap{
1079 "fizz": {
1080 "foo": {},
1081 "bar": nil,
1082 },
1083 "buzz": nil,
1084 },
1085 canonicalize: true,
1086 want: `{"buzz":{},"fizz":{"bar":{},"foo":{}}}`,
1087 }, {
1088 name: jsontest.Name("Maps/CyclicMap"),
1089 in: func() recursiveMap {
1090 m := recursiveMap{"k": nil}
1091 m["k"] = m
1092 return m
1093 }(),
1094 want: strings.Repeat(`{"k":`, startDetectingCyclesAfter) + `{"k"`,
1095 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"k":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/k", startDetectingCyclesAfter+1))).withType(0, T[recursiveMap]()),
1096 }, {
1097 name: jsontest.Name("Maps/IgnoreInvalidFormat"),
1098 opts: []Options{invalidFormatOption},
1099 in: map[string]string{},
1100 want: `{}`,
1101 }, {
1102 name: jsontest.Name("Structs/Empty"),
1103 in: structEmpty{},
1104 want: `{}`,
1105 }, {
1106 name: jsontest.Name("Structs/UnexportedIgnored"),
1107 in: structUnexportedIgnored{ignored: "ignored"},
1108 want: `{}`,
1109 }, {
1110 name: jsontest.Name("Structs/IgnoredUnexportedEmbedded"),
1111 in: structIgnoredUnexportedEmbedded{namedString: "ignored"},
1112 want: `{}`,
1113 }, {
1114 name: jsontest.Name("Structs/WeirdNames"),
1115 in: structWeirdNames{Empty: "empty", Comma: "comma", Quote: "quote"},
1116 want: `{"":"empty",",":"comma","\"":"quote"}`,
1117 }, {
1118 name: jsontest.Name("Structs/EscapedNames"),
1119 opts: []Options{jsontext.EscapeForHTML(true), jsontext.EscapeForJS(true)},
1120 in: struct {
1121 S string "json:\"'abc<>&\u2028\u2029xyz'\""
1122 M any
1123 I structInlineTextValue
1124 }{
1125 S: "abc<>&\u2028\u2029xyz",
1126 M: map[string]string{"abc<>&\u2028\u2029xyz": "abc<>&\u2028\u2029xyz"},
1127 I: structInlineTextValue{X: jsontext.Value(`{"abc<>&` + "\u2028\u2029" + `xyz":"abc<>&` + "\u2028\u2029" + `xyz"}`)},
1128 },
1129 want: `{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz","M":{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz"},"I":{"abc\u003c\u003e\u0026\u2028\u2029xyz":"abc\u003c\u003e\u0026\u2028\u2029xyz"}}`,
1130 }, {
1131 name: jsontest.Name("Structs/NoCase"),
1132 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1133 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1134 }, {
1135 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames"),
1136 opts: []Options{MatchCaseInsensitiveNames(true)},
1137 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1138 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1139 }, {
1140 name: jsontest.Name("Structs/NoCase/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
1141 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
1142 in: structNoCase{AaA: "AaA", AAa: "AAa", Aaa: "Aaa", AAA: "AAA", AA_A: "AA_A"},
1143 want: `{"Aaa":"Aaa","AA_A":"AA_A","AaA":"AaA","AAa":"AAa","AAA":"AAA"}`,
1144 }, {
1145 name: jsontest.Name("Structs/Normal"),
1146 opts: []Options{jsontext.Multiline(true)},
1147 in: structAll{
1148 Bool: true,
1149 String: "hello",
1150 Bytes: []byte{1, 2, 3},
1151 Int: -64,
1152 Uint: +64,
1153 Float: 3.14159,
1154 Map: map[string]string{"key": "value"},
1155 StructScalars: structScalars{
1156 Bool: true,
1157 String: "hello",
1158 Bytes: []byte{1, 2, 3},
1159 Int: -64,
1160 Uint: +64,
1161 Float: 3.14159,
1162 },
1163 StructMaps: structMaps{
1164 MapBool: map[string]bool{"": true},
1165 MapString: map[string]string{"": "hello"},
1166 MapBytes: map[string][]byte{"": {1, 2, 3}},
1167 MapInt: map[string]int64{"": -64},
1168 MapUint: map[string]uint64{"": +64},
1169 MapFloat: map[string]float64{"": 3.14159},
1170 },
1171 StructSlices: structSlices{
1172 SliceBool: []bool{true},
1173 SliceString: []string{"hello"},
1174 SliceBytes: [][]byte{{1, 2, 3}},
1175 SliceInt: []int64{-64},
1176 SliceUint: []uint64{+64},
1177 SliceFloat: []float64{3.14159},
1178 },
1179 Slice: []string{"fizz", "buzz"},
1180 Array: [1]string{"goodbye"},
1181 Pointer: new(structAll),
1182 Interface: (*structAll)(nil),
1183 },
1184 want: `{
1185 "Bool": true,
1186 "String": "hello",
1187 "Bytes": "AQID",
1188 "Int": -64,
1189 "Uint": 64,
1190 "Float": 3.14159,
1191 "Map": {
1192 "key": "value"
1193 },
1194 "StructScalars": {
1195 "Bool": true,
1196 "String": "hello",
1197 "Bytes": "AQID",
1198 "Int": -64,
1199 "Uint": 64,
1200 "Float": 3.14159
1201 },
1202 "StructMaps": {
1203 "MapBool": {
1204 "": true
1205 },
1206 "MapString": {
1207 "": "hello"
1208 },
1209 "MapBytes": {
1210 "": "AQID"
1211 },
1212 "MapInt": {
1213 "": -64
1214 },
1215 "MapUint": {
1216 "": 64
1217 },
1218 "MapFloat": {
1219 "": 3.14159
1220 }
1221 },
1222 "StructSlices": {
1223 "SliceBool": [
1224 true
1225 ],
1226 "SliceString": [
1227 "hello"
1228 ],
1229 "SliceBytes": [
1230 "AQID"
1231 ],
1232 "SliceInt": [
1233 -64
1234 ],
1235 "SliceUint": [
1236 64
1237 ],
1238 "SliceFloat": [
1239 3.14159
1240 ]
1241 },
1242 "Slice": [
1243 "fizz",
1244 "buzz"
1245 ],
1246 "Array": [
1247 "goodbye"
1248 ],
1249 "Pointer": {
1250 "Bool": false,
1251 "String": "",
1252 "Bytes": "",
1253 "Int": 0,
1254 "Uint": 0,
1255 "Float": 0,
1256 "Map": {},
1257 "StructScalars": {
1258 "Bool": false,
1259 "String": "",
1260 "Bytes": "",
1261 "Int": 0,
1262 "Uint": 0,
1263 "Float": 0
1264 },
1265 "StructMaps": {
1266 "MapBool": {},
1267 "MapString": {},
1268 "MapBytes": {},
1269 "MapInt": {},
1270 "MapUint": {},
1271 "MapFloat": {}
1272 },
1273 "StructSlices": {
1274 "SliceBool": [],
1275 "SliceString": [],
1276 "SliceBytes": [],
1277 "SliceInt": [],
1278 "SliceUint": [],
1279 "SliceFloat": []
1280 },
1281 "Slice": [],
1282 "Array": [
1283 ""
1284 ],
1285 "Pointer": null,
1286 "Interface": null
1287 },
1288 "Interface": null
1289 }`,
1290 }, {
1291 name: jsontest.Name("Structs/SpaceAfterColonAndComma"),
1292 opts: []Options{jsontext.SpaceAfterColon(true), jsontext.SpaceAfterComma(true)},
1293 in: structOmitZeroAll{Int: 1, Uint: 1},
1294 want: `{"Int": 1, "Uint": 1}`,
1295 }, {
1296 name: jsontest.Name("Structs/SpaceAfterColon"),
1297 opts: []Options{jsontext.SpaceAfterColon(true)},
1298 in: structOmitZeroAll{Int: 1, Uint: 1},
1299 want: `{"Int": 1,"Uint": 1}`,
1300 }, {
1301 name: jsontest.Name("Structs/SpaceAfterComma"),
1302 opts: []Options{jsontext.SpaceAfterComma(true)},
1303 in: structOmitZeroAll{Int: 1, Uint: 1, Slice: []string{"a", "b"}},
1304 want: `{"Int":1, "Uint":1, "Slice":["a", "b"]}`,
1305 }, {
1306 name: jsontest.Name("Structs/Stringified"),
1307 opts: []Options{jsontext.Multiline(true)},
1308 in: structStringifiedAll{
1309 Bool: true,
1310 String: "hello",
1311 Bytes: []byte{1, 2, 3},
1312 Int: -64,
1313 Uint: +64,
1314 Float: 3.14159,
1315 Map: map[string]string{"key": "value"},
1316 StructScalars: structScalars{
1317 Bool: true,
1318 String: "hello",
1319 Bytes: []byte{1, 2, 3},
1320 Int: -64,
1321 Uint: +64,
1322 Float: 3.14159,
1323 },
1324 StructMaps: structMaps{
1325 MapBool: map[string]bool{"": true},
1326 MapString: map[string]string{"": "hello"},
1327 MapBytes: map[string][]byte{"": {1, 2, 3}},
1328 MapInt: map[string]int64{"": -64},
1329 MapUint: map[string]uint64{"": +64},
1330 MapFloat: map[string]float64{"": 3.14159},
1331 },
1332 StructSlices: structSlices{
1333 SliceBool: []bool{true},
1334 SliceString: []string{"hello"},
1335 SliceBytes: [][]byte{{1, 2, 3}},
1336 SliceInt: []int64{-64},
1337 SliceUint: []uint64{+64},
1338 SliceFloat: []float64{3.14159},
1339 },
1340 Slice: []string{"fizz", "buzz"},
1341 Array: [1]string{"goodbye"},
1342 Pointer: new(structStringifiedAll),
1343 Interface: (*structStringifiedAll)(nil),
1344 },
1345 want: `{
1346 "Bool": true,
1347 "String": "hello",
1348 "Bytes": "AQID",
1349 "Int": "-64",
1350 "Uint": "64",
1351 "Float": "3.14159",
1352 "Map": {
1353 "key": "value"
1354 },
1355 "StructScalars": {
1356 "Bool": true,
1357 "String": "hello",
1358 "Bytes": "AQID",
1359 "Int": "-64",
1360 "Uint": "64",
1361 "Float": "3.14159"
1362 },
1363 "StructMaps": {
1364 "MapBool": {
1365 "": true
1366 },
1367 "MapString": {
1368 "": "hello"
1369 },
1370 "MapBytes": {
1371 "": "AQID"
1372 },
1373 "MapInt": {
1374 "": "-64"
1375 },
1376 "MapUint": {
1377 "": "64"
1378 },
1379 "MapFloat": {
1380 "": "3.14159"
1381 }
1382 },
1383 "StructSlices": {
1384 "SliceBool": [
1385 true
1386 ],
1387 "SliceString": [
1388 "hello"
1389 ],
1390 "SliceBytes": [
1391 "AQID"
1392 ],
1393 "SliceInt": [
1394 "-64"
1395 ],
1396 "SliceUint": [
1397 "64"
1398 ],
1399 "SliceFloat": [
1400 "3.14159"
1401 ]
1402 },
1403 "Slice": [
1404 "fizz",
1405 "buzz"
1406 ],
1407 "Array": [
1408 "goodbye"
1409 ],
1410 "Pointer": {
1411 "Bool": false,
1412 "String": "",
1413 "Bytes": "",
1414 "Int": "0",
1415 "Uint": "0",
1416 "Float": "0",
1417 "Map": {},
1418 "StructScalars": {
1419 "Bool": false,
1420 "String": "",
1421 "Bytes": "",
1422 "Int": "0",
1423 "Uint": "0",
1424 "Float": "0"
1425 },
1426 "StructMaps": {
1427 "MapBool": {},
1428 "MapString": {},
1429 "MapBytes": {},
1430 "MapInt": {},
1431 "MapUint": {},
1432 "MapFloat": {}
1433 },
1434 "StructSlices": {
1435 "SliceBool": [],
1436 "SliceString": [],
1437 "SliceBytes": [],
1438 "SliceInt": [],
1439 "SliceUint": [],
1440 "SliceFloat": []
1441 },
1442 "Slice": [],
1443 "Array": [
1444 ""
1445 ],
1446 "Pointer": null,
1447 "Interface": null
1448 },
1449 "Interface": null
1450 }`,
1451 }, {
1452 name: jsontest.Name("Structs/LegacyStringified"),
1453 opts: []Options{jsontext.Multiline(true), jsonflags.StringifyWithLegacySemantics | 1},
1454 in: structStringifiedAll{
1455 Bool: true,
1456 String: "hello",
1457 Bytes: []byte{1, 2, 3},
1458 Int: -64,
1459 Uint: +64,
1460 Float: 3.14159,
1461 Map: map[string]string{"key": "value"},
1462 StructScalars: structScalars{
1463 Bool: true,
1464 String: "hello",
1465 Bytes: []byte{1, 2, 3},
1466 Int: -64,
1467 Uint: +64,
1468 Float: 3.14159,
1469 },
1470 StructMaps: structMaps{
1471 MapBool: map[string]bool{"": true},
1472 MapString: map[string]string{"": "hello"},
1473 MapBytes: map[string][]byte{"": {1, 2, 3}},
1474 MapInt: map[string]int64{"": -64},
1475 MapUint: map[string]uint64{"": +64},
1476 MapFloat: map[string]float64{"": 3.14159},
1477 },
1478 StructSlices: structSlices{
1479 SliceBool: []bool{true},
1480 SliceString: []string{"hello"},
1481 SliceBytes: [][]byte{{1, 2, 3}},
1482 SliceInt: []int64{-64},
1483 SliceUint: []uint64{+64},
1484 SliceFloat: []float64{3.14159},
1485 },
1486 Slice: []string{"fizz", "buzz"},
1487 Array: [1]string{"goodbye"},
1488 Pointer: new(structStringifiedAll),
1489 Interface: (*structStringifiedAll)(nil),
1490 },
1491 want: `{
1492 "Bool": "true",
1493 "String": "\"hello\"",
1494 "Bytes": "AQID",
1495 "Int": "-64",
1496 "Uint": "64",
1497 "Float": "3.14159",
1498 "Map": {
1499 "key": "value"
1500 },
1501 "StructScalars": {
1502 "Bool": true,
1503 "String": "hello",
1504 "Bytes": "AQID",
1505 "Int": -64,
1506 "Uint": 64,
1507 "Float": 3.14159
1508 },
1509 "StructMaps": {
1510 "MapBool": {
1511 "": true
1512 },
1513 "MapString": {
1514 "": "hello"
1515 },
1516 "MapBytes": {
1517 "": "AQID"
1518 },
1519 "MapInt": {
1520 "": -64
1521 },
1522 "MapUint": {
1523 "": 64
1524 },
1525 "MapFloat": {
1526 "": 3.14159
1527 }
1528 },
1529 "StructSlices": {
1530 "SliceBool": [
1531 true
1532 ],
1533 "SliceString": [
1534 "hello"
1535 ],
1536 "SliceBytes": [
1537 "AQID"
1538 ],
1539 "SliceInt": [
1540 -64
1541 ],
1542 "SliceUint": [
1543 64
1544 ],
1545 "SliceFloat": [
1546 3.14159
1547 ]
1548 },
1549 "Slice": [
1550 "fizz",
1551 "buzz"
1552 ],
1553 "Array": [
1554 "goodbye"
1555 ],
1556 "Pointer": {
1557 "Bool": "false",
1558 "String": "\"\"",
1559 "Bytes": "",
1560 "Int": "0",
1561 "Uint": "0",
1562 "Float": "0",
1563 "Map": {},
1564 "StructScalars": {
1565 "Bool": false,
1566 "String": "",
1567 "Bytes": "",
1568 "Int": 0,
1569 "Uint": 0,
1570 "Float": 0
1571 },
1572 "StructMaps": {
1573 "MapBool": {},
1574 "MapString": {},
1575 "MapBytes": {},
1576 "MapInt": {},
1577 "MapUint": {},
1578 "MapFloat": {}
1579 },
1580 "StructSlices": {
1581 "SliceBool": [],
1582 "SliceString": [],
1583 "SliceBytes": [],
1584 "SliceInt": [],
1585 "SliceUint": [],
1586 "SliceFloat": []
1587 },
1588 "Slice": [],
1589 "Array": [
1590 ""
1591 ],
1592 "Pointer": null,
1593 "Interface": null
1594 },
1595 "Interface": null
1596 }`,
1597 }, {
1598 name: jsontest.Name("Structs/OmitZero/Zero"),
1599 in: structOmitZeroAll{},
1600 want: `{}`,
1601 }, {
1602 name: jsontest.Name("Structs/OmitZeroOption/Zero"),
1603 opts: []Options{OmitZeroStructFields(true)},
1604 in: structAll{},
1605 want: `{}`,
1606 }, {
1607 name: jsontest.Name("Structs/OmitZero/NonZero"),
1608 opts: []Options{jsontext.Multiline(true)},
1609 in: structOmitZeroAll{
1610 Bool: true,
1611 String: " ",
1612 Bytes: []byte{},
1613 Int: 1,
1614 Uint: 1,
1615 Float: math.SmallestNonzeroFloat64,
1616 Map: map[string]string{},
1617 StructScalars: structScalars{unexported: true},
1618 StructSlices: structSlices{Ignored: true},
1619 StructMaps: structMaps{MapBool: map[string]bool{}},
1620 Slice: []string{},
1621 Array: [1]string{" "},
1622 Pointer: new(structOmitZeroAll),
1623 Interface: (*structOmitZeroAll)(nil),
1624 },
1625 want: `{
1626 "Bool": true,
1627 "String": " ",
1628 "Bytes": "",
1629 "Int": 1,
1630 "Uint": 1,
1631 "Float": 5e-324,
1632 "Map": {},
1633 "StructScalars": {
1634 "Bool": false,
1635 "String": "",
1636 "Bytes": "",
1637 "Int": 0,
1638 "Uint": 0,
1639 "Float": 0
1640 },
1641 "StructMaps": {
1642 "MapBool": {},
1643 "MapString": {},
1644 "MapBytes": {},
1645 "MapInt": {},
1646 "MapUint": {},
1647 "MapFloat": {}
1648 },
1649 "StructSlices": {
1650 "SliceBool": [],
1651 "SliceString": [],
1652 "SliceBytes": [],
1653 "SliceInt": [],
1654 "SliceUint": [],
1655 "SliceFloat": []
1656 },
1657 "Slice": [],
1658 "Array": [
1659 " "
1660 ],
1661 "Pointer": {},
1662 "Interface": null
1663 }`,
1664 }, {
1665 name: jsontest.Name("Structs/OmitZeroOption/NonZero"),
1666 opts: []Options{OmitZeroStructFields(true), jsontext.Multiline(true)},
1667 in: structAll{
1668 Bool: true,
1669 String: " ",
1670 Bytes: []byte{},
1671 Int: 1,
1672 Uint: 1,
1673 Float: math.SmallestNonzeroFloat64,
1674 Map: map[string]string{},
1675 StructScalars: structScalars{unexported: true},
1676 StructSlices: structSlices{Ignored: true},
1677 StructMaps: structMaps{MapBool: map[string]bool{}},
1678 Slice: []string{},
1679 Array: [1]string{" "},
1680 Pointer: new(structAll),
1681 Interface: (*structAll)(nil),
1682 },
1683 want: `{
1684 "Bool": true,
1685 "String": " ",
1686 "Bytes": "",
1687 "Int": 1,
1688 "Uint": 1,
1689 "Float": 5e-324,
1690 "Map": {},
1691 "StructScalars": {},
1692 "StructMaps": {
1693 "MapBool": {}
1694 },
1695 "StructSlices": {},
1696 "Slice": [],
1697 "Array": [
1698 " "
1699 ],
1700 "Pointer": {},
1701 "Interface": null
1702 }`,
1703 }, {
1704 name: jsontest.Name("Structs/OmitZeroMethod/Zero"),
1705 in: structOmitZeroMethodAll{},
1706 want: `{"ValueNeverZero":"","PointerNeverZero":""}`,
1707 }, {
1708 name: jsontest.Name("Structs/OmitZeroMethod/NonZero"),
1709 opts: []Options{jsontext.Multiline(true)},
1710 in: structOmitZeroMethodAll{
1711 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1712 ValueNeverZero: valueNeverZero("nonzero"),
1713 PointerAlwaysZero: pointerAlwaysZero("nonzero"),
1714 PointerNeverZero: pointerNeverZero("nonzero"),
1715 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1716 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1717 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1718 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1719 PointerPointerValueAlwaysZero: addr(addr(valueAlwaysZero("nonzero"))),
1720 PointerPointerValueNeverZero: addr(addr(valueNeverZero("nonzero"))),
1721 PointerPointerPointerAlwaysZero: addr(addr(pointerAlwaysZero("nonzero"))),
1722 PointerPointerPointerNeverZero: addr(addr(pointerNeverZero("nonzero"))),
1723 },
1724 want: `{
1725 "ValueNeverZero": "nonzero",
1726 "PointerNeverZero": "nonzero",
1727 "PointerValueNeverZero": "nonzero",
1728 "PointerPointerNeverZero": "nonzero",
1729 "PointerPointerValueAlwaysZero": "nonzero",
1730 "PointerPointerValueNeverZero": "nonzero",
1731 "PointerPointerPointerAlwaysZero": "nonzero",
1732 "PointerPointerPointerNeverZero": "nonzero"
1733 }`,
1734 }, {
1735 name: jsontest.Name("Structs/OmitZeroMethod/Interface/Zero"),
1736 opts: []Options{jsontext.Multiline(true)},
1737 in: structOmitZeroMethodInterfaceAll{},
1738 want: `{}`,
1739 }, {
1740 name: jsontest.Name("Structs/OmitZeroMethod/Interface/PartialZero"),
1741 opts: []Options{jsontext.Multiline(true)},
1742 in: structOmitZeroMethodInterfaceAll{
1743 ValueAlwaysZero: valueAlwaysZero(""),
1744 ValueNeverZero: valueNeverZero(""),
1745 PointerValueAlwaysZero: (*valueAlwaysZero)(nil),
1746 PointerValueNeverZero: (*valueNeverZero)(nil),
1747 PointerPointerAlwaysZero: (*pointerAlwaysZero)(nil),
1748 PointerPointerNeverZero: (*pointerNeverZero)(nil),
1749 },
1750 want: `{
1751 "ValueNeverZero": ""
1752 }`,
1753 }, {
1754 name: jsontest.Name("Structs/OmitZeroMethod/Interface/NonZero"),
1755 opts: []Options{jsontext.Multiline(true)},
1756 in: structOmitZeroMethodInterfaceAll{
1757 ValueAlwaysZero: valueAlwaysZero("nonzero"),
1758 ValueNeverZero: valueNeverZero("nonzero"),
1759 PointerValueAlwaysZero: addr(valueAlwaysZero("nonzero")),
1760 PointerValueNeverZero: addr(valueNeverZero("nonzero")),
1761 PointerPointerAlwaysZero: addr(pointerAlwaysZero("nonzero")),
1762 PointerPointerNeverZero: addr(pointerNeverZero("nonzero")),
1763 },
1764 want: `{
1765 "ValueNeverZero": "nonzero",
1766 "PointerValueNeverZero": "nonzero",
1767 "PointerPointerNeverZero": "nonzero"
1768 }`,
1769 }, {
1770 name: jsontest.Name("Structs/OmitEmpty/Zero"),
1771 opts: []Options{jsontext.Multiline(true)},
1772 in: structOmitEmptyAll{},
1773 want: `{
1774 "Bool": false,
1775 "StringNonEmpty": "value",
1776 "BytesNonEmpty": [
1777 "value"
1778 ],
1779 "Float": 0,
1780 "MapNonEmpty": {
1781 "key": "value"
1782 },
1783 "SliceNonEmpty": [
1784 "value"
1785 ]
1786 }`,
1787 }, {
1788 name: jsontest.Name("Structs/OmitEmpty/EmptyNonZero"),
1789 opts: []Options{jsontext.Multiline(true)},
1790 in: structOmitEmptyAll{
1791 String: string(""),
1792 StringEmpty: stringMarshalEmpty(""),
1793 StringNonEmpty: stringMarshalNonEmpty(""),
1794 PointerString: addr(string("")),
1795 PointerStringEmpty: addr(stringMarshalEmpty("")),
1796 PointerStringNonEmpty: addr(stringMarshalNonEmpty("")),
1797 Bytes: []byte(""),
1798 BytesEmpty: bytesMarshalEmpty([]byte("")),
1799 BytesNonEmpty: bytesMarshalNonEmpty([]byte("")),
1800 PointerBytes: addr([]byte("")),
1801 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte(""))),
1802 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte(""))),
1803 Map: map[string]string{},
1804 MapEmpty: mapMarshalEmpty{},
1805 MapNonEmpty: mapMarshalNonEmpty{},
1806 PointerMap: addr(map[string]string{}),
1807 PointerMapEmpty: addr(mapMarshalEmpty{}),
1808 PointerMapNonEmpty: addr(mapMarshalNonEmpty{}),
1809 Slice: []string{},
1810 SliceEmpty: sliceMarshalEmpty{},
1811 SliceNonEmpty: sliceMarshalNonEmpty{},
1812 PointerSlice: addr([]string{}),
1813 PointerSliceEmpty: addr(sliceMarshalEmpty{}),
1814 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{}),
1815 Pointer: &structOmitZeroEmptyAll{},
1816 Interface: []string{},
1817 },
1818 want: `{
1819 "Bool": false,
1820 "StringNonEmpty": "value",
1821 "PointerStringNonEmpty": "value",
1822 "BytesNonEmpty": [
1823 "value"
1824 ],
1825 "PointerBytesNonEmpty": [
1826 "value"
1827 ],
1828 "Float": 0,
1829 "MapNonEmpty": {
1830 "key": "value"
1831 },
1832 "PointerMapNonEmpty": {
1833 "key": "value"
1834 },
1835 "SliceNonEmpty": [
1836 "value"
1837 ],
1838 "PointerSliceNonEmpty": [
1839 "value"
1840 ]
1841 }`,
1842 }, {
1843 name: jsontest.Name("Structs/OmitEmpty/NonEmpty"),
1844 opts: []Options{jsontext.Multiline(true)},
1845 in: structOmitEmptyAll{
1846 Bool: true,
1847 PointerBool: addr(true),
1848 String: string("value"),
1849 StringEmpty: stringMarshalEmpty("value"),
1850 StringNonEmpty: stringMarshalNonEmpty("value"),
1851 PointerString: addr(string("value")),
1852 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1853 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1854 Bytes: []byte("value"),
1855 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1856 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1857 PointerBytes: addr([]byte("value")),
1858 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1859 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1860 Float: math.Copysign(0, -1),
1861 PointerFloat: addr(math.Copysign(0, -1)),
1862 Map: map[string]string{"": ""},
1863 MapEmpty: mapMarshalEmpty{"key": "value"},
1864 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1865 PointerMap: addr(map[string]string{"": ""}),
1866 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1867 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1868 Slice: []string{""},
1869 SliceEmpty: sliceMarshalEmpty{"value"},
1870 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1871 PointerSlice: addr([]string{""}),
1872 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1873 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1874 Pointer: &structOmitZeroEmptyAll{Float: math.SmallestNonzeroFloat64},
1875 Interface: []string{""},
1876 },
1877 want: `{
1878 "Bool": true,
1879 "PointerBool": true,
1880 "String": "value",
1881 "StringNonEmpty": "value",
1882 "PointerString": "value",
1883 "PointerStringNonEmpty": "value",
1884 "Bytes": "dmFsdWU=",
1885 "BytesNonEmpty": [
1886 "value"
1887 ],
1888 "PointerBytes": "dmFsdWU=",
1889 "PointerBytesNonEmpty": [
1890 "value"
1891 ],
1892 "Float": -0,
1893 "PointerFloat": -0,
1894 "Map": {
1895 "": ""
1896 },
1897 "MapNonEmpty": {
1898 "key": "value"
1899 },
1900 "PointerMap": {
1901 "": ""
1902 },
1903 "PointerMapNonEmpty": {
1904 "key": "value"
1905 },
1906 "Slice": [
1907 ""
1908 ],
1909 "SliceNonEmpty": [
1910 "value"
1911 ],
1912 "PointerSlice": [
1913 ""
1914 ],
1915 "PointerSliceNonEmpty": [
1916 "value"
1917 ],
1918 "Pointer": {
1919 "Float": 5e-324
1920 },
1921 "Interface": [
1922 ""
1923 ]
1924 }`,
1925 }, {
1926 name: jsontest.Name("Structs/OmitEmpty/Legacy/Zero"),
1927 opts: []Options{jsonflags.OmitEmptyWithLegacySemantics | 1},
1928 in: structOmitEmptyAll{},
1929 want: `{}`,
1930 }, {
1931 name: jsontest.Name("Structs/OmitEmpty/Legacy/NonEmpty"),
1932 opts: []Options{jsontext.Multiline(true), jsonflags.OmitEmptyWithLegacySemantics | 1},
1933 in: structOmitEmptyAll{
1934 Bool: true,
1935 PointerBool: addr(true),
1936 String: string("value"),
1937 StringEmpty: stringMarshalEmpty("value"),
1938 StringNonEmpty: stringMarshalNonEmpty("value"),
1939 PointerString: addr(string("value")),
1940 PointerStringEmpty: addr(stringMarshalEmpty("value")),
1941 PointerStringNonEmpty: addr(stringMarshalNonEmpty("value")),
1942 Bytes: []byte("value"),
1943 BytesEmpty: bytesMarshalEmpty([]byte("value")),
1944 BytesNonEmpty: bytesMarshalNonEmpty([]byte("value")),
1945 PointerBytes: addr([]byte("value")),
1946 PointerBytesEmpty: addr(bytesMarshalEmpty([]byte("value"))),
1947 PointerBytesNonEmpty: addr(bytesMarshalNonEmpty([]byte("value"))),
1948 Float: math.Copysign(0, -1),
1949 PointerFloat: addr(math.Copysign(0, -1)),
1950 Map: map[string]string{"": ""},
1951 MapEmpty: mapMarshalEmpty{"key": "value"},
1952 MapNonEmpty: mapMarshalNonEmpty{"key": "value"},
1953 PointerMap: addr(map[string]string{"": ""}),
1954 PointerMapEmpty: addr(mapMarshalEmpty{"key": "value"}),
1955 PointerMapNonEmpty: addr(mapMarshalNonEmpty{"key": "value"}),
1956 Slice: []string{""},
1957 SliceEmpty: sliceMarshalEmpty{"value"},
1958 SliceNonEmpty: sliceMarshalNonEmpty{"value"},
1959 PointerSlice: addr([]string{""}),
1960 PointerSliceEmpty: addr(sliceMarshalEmpty{"value"}),
1961 PointerSliceNonEmpty: addr(sliceMarshalNonEmpty{"value"}),
1962 Pointer: &structOmitZeroEmptyAll{Float: math.Copysign(0, -1)},
1963 Interface: []string{""},
1964 },
1965 want: `{
1966 "Bool": true,
1967 "PointerBool": true,
1968 "String": "value",
1969 "StringEmpty": "",
1970 "StringNonEmpty": "value",
1971 "PointerString": "value",
1972 "PointerStringEmpty": "",
1973 "PointerStringNonEmpty": "value",
1974 "Bytes": "dmFsdWU=",
1975 "BytesEmpty": [],
1976 "BytesNonEmpty": [
1977 "value"
1978 ],
1979 "PointerBytes": "dmFsdWU=",
1980 "PointerBytesEmpty": [],
1981 "PointerBytesNonEmpty": [
1982 "value"
1983 ],
1984 "PointerFloat": -0,
1985 "Map": {
1986 "": ""
1987 },
1988 "MapEmpty": {},
1989 "MapNonEmpty": {
1990 "key": "value"
1991 },
1992 "PointerMap": {
1993 "": ""
1994 },
1995 "PointerMapEmpty": {},
1996 "PointerMapNonEmpty": {
1997 "key": "value"
1998 },
1999 "Slice": [
2000 ""
2001 ],
2002 "SliceEmpty": [],
2003 "SliceNonEmpty": [
2004 "value"
2005 ],
2006 "PointerSlice": [
2007 ""
2008 ],
2009 "PointerSliceEmpty": [],
2010 "PointerSliceNonEmpty": [
2011 "value"
2012 ],
2013 "Pointer": {},
2014 "Interface": [
2015 ""
2016 ]
2017 }`,
2018 }, {
2019 name: jsontest.Name("Structs/OmitEmpty/NonEmptyString"),
2020 in: struct {
2021 X string `json:",omitempty"`
2022 }{`"`},
2023 want: `{"X":"\""}`,
2024 }, {
2025 name: jsontest.Name("Structs/OmitZeroEmpty/Zero"),
2026 in: structOmitZeroEmptyAll{},
2027 want: `{}`,
2028 }, {
2029 name: jsontest.Name("Structs/OmitZeroEmpty/Empty"),
2030 in: structOmitZeroEmptyAll{
2031 Bytes: []byte{},
2032 Map: map[string]string{},
2033 Slice: []string{},
2034 Pointer: &structOmitZeroEmptyAll{},
2035 Interface: []string{},
2036 },
2037 want: `{}`,
2038 }, {
2039 name: jsontest.Name("Structs/OmitEmpty/PathologicalDepth"),
2040 in: func() any {
2041 type X struct {
2042 X *X `json:",omitempty"`
2043 }
2044 var make func(int) *X
2045 make = func(n int) *X {
2046 if n == 0 {
2047 return nil
2048 }
2049 return &X{make(n - 1)}
2050 }
2051 return make(100)
2052 }(),
2053 want: `{}`,
2054 useWriter: true,
2055 }, {
2056 name: jsontest.Name("Structs/OmitEmpty/PathologicalBreadth"),
2057 in: func() any {
2058 var fields []reflect.StructField
2059 for i := range 100 {
2060 fields = append(fields, reflect.StructField{
2061 Name: fmt.Sprintf("X%d", i),
2062 Type: T[stringMarshalEmpty](),
2063 Tag: `json:",omitempty"`,
2064 })
2065 }
2066 return reflect.New(reflect.StructOf(fields)).Interface()
2067 }(),
2068 want: `{}`,
2069 useWriter: true,
2070 }, {
2071 name: jsontest.Name("Structs/OmitEmpty/PathologicalTree"),
2072 in: func() any {
2073 type X struct {
2074 XL, XR *X `json:",omitempty"`
2075 }
2076 var make func(int) *X
2077 make = func(n int) *X {
2078 if n == 0 {
2079 return nil
2080 }
2081 return &X{make(n - 1), make(n - 1)}
2082 }
2083 return make(8)
2084 }(),
2085 want: `{}`,
2086 useWriter: true,
2087 }, {
2088 name: jsontest.Name("Structs/OmitZeroEmpty/NonEmpty"),
2089 in: structOmitZeroEmptyAll{
2090 Bytes: []byte("value"),
2091 Map: map[string]string{"": ""},
2092 Slice: []string{""},
2093 Pointer: &structOmitZeroEmptyAll{Bool: true},
2094 Interface: []string{""},
2095 },
2096 want: `{"Bytes":"dmFsdWU=","Map":{"":""},"Slice":[""],"Pointer":{"Bool":true},"Interface":[""]}`,
2097 }, {
2098 name: jsontest.Name("Structs/Format/Bytes"),
2099 opts: []Options{jsontext.Multiline(true)},
2100 in: structFormatBytes{
2101 Base16: []byte("\x01\x23\x45\x67\x89\xab\xcd\xef"),
2102 Base32: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2103 Base32Hex: []byte("\x00D2\x14\xc7BT\xb65τe:V\xd7\xc6u\xbew\xdf"),
2104 Base64: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"),
2105 Base64URL: []byte("\x00\x10\x83\x10Q\x87 \x92\x8b0ӏA\x14\x93QU\x97a\x96\x9bqן\x82\x18\xa3\x92Y\xa7\xa2\x9a\xab\xb2ۯ\xc3\x1c\xb3\xd3]\xb7㞻\xf3߿"),
2106 Array: []byte{1, 2, 3, 4},
2107 },
2108 want: `{
2109 "Base16": "0123456789abcdef",
2110 "Base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
2111 "Base32Hex": "0123456789ABCDEFGHIJKLMNOPQRSTUV",
2112 "Base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
2113 "Base64URL": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
2114 "Array": [
2115 1,
2116 2,
2117 3,
2118 4
2119 ]
2120 }`}, {
2121 name: jsontest.Name("Structs/Format/ArrayBytes"),
2122 opts: []Options{jsontext.Multiline(true)},
2123 in: structFormatArrayBytes{
2124 Base16: [4]byte{1, 2, 3, 4},
2125 Base32: [4]byte{1, 2, 3, 4},
2126 Base32Hex: [4]byte{1, 2, 3, 4},
2127 Base64: [4]byte{1, 2, 3, 4},
2128 Base64URL: [4]byte{1, 2, 3, 4},
2129 Array: [4]byte{1, 2, 3, 4},
2130 Default: [4]byte{1, 2, 3, 4},
2131 },
2132 want: `{
2133 "Base16": "01020304",
2134 "Base32": "AEBAGBA=",
2135 "Base32Hex": "0410610=",
2136 "Base64": "AQIDBA==",
2137 "Base64URL": "AQIDBA==",
2138 "Array": [
2139 1,
2140 2,
2141 3,
2142 4
2143 ],
2144 "Default": "AQIDBA=="
2145 }`}, {
2146 name: jsontest.Name("Structs/Format/ArrayBytes/Legacy"),
2147 opts: []Options{jsontext.Multiline(true), jsonflags.FormatByteArrayAsArray | jsonflags.FormatBytesWithLegacySemantics | 1},
2148 in: structFormatArrayBytes{
2149 Base16: [4]byte{1, 2, 3, 4},
2150 Base32: [4]byte{1, 2, 3, 4},
2151 Base32Hex: [4]byte{1, 2, 3, 4},
2152 Base64: [4]byte{1, 2, 3, 4},
2153 Base64URL: [4]byte{1, 2, 3, 4},
2154 Array: [4]byte{1, 2, 3, 4},
2155 Default: [4]byte{1, 2, 3, 4},
2156 },
2157 want: `{
2158 "Base16": "01020304",
2159 "Base32": "AEBAGBA=",
2160 "Base32Hex": "0410610=",
2161 "Base64": "AQIDBA==",
2162 "Base64URL": "AQIDBA==",
2163 "Array": [
2164 1,
2165 2,
2166 3,
2167 4
2168 ],
2169 "Default": [
2170 1,
2171 2,
2172 3,
2173 4
2174 ]
2175 }`}, {
2176 name: jsontest.Name("Structs/Format/Bytes/Array"),
2177 opts: []Options{
2178 WithMarshalers(MarshalFunc(func(in byte) ([]byte, error) {
2179 if in > 3 {
2180 return []byte("true"), nil
2181 } else {
2182 return []byte("false"), nil
2183 }
2184 })),
2185 },
2186 in: struct {
2187 Array []byte `json:",format:array"`
2188 }{
2189 Array: []byte{1, 6, 2, 5, 3, 4},
2190 },
2191 want: `{"Array":[false,true,false,true,false,true]}`,
2192 }, {
2193 name: jsontest.Name("Structs/Format/Floats"),
2194 opts: []Options{jsontext.Multiline(true)},
2195 in: []structFormatFloats{
2196 {NonFinite: math.Pi, PointerNonFinite: addr(math.Pi)},
2197 {NonFinite: math.NaN(), PointerNonFinite: addr(math.NaN())},
2198 {NonFinite: math.Inf(-1), PointerNonFinite: addr(math.Inf(-1))},
2199 {NonFinite: math.Inf(+1), PointerNonFinite: addr(math.Inf(+1))},
2200 },
2201 want: `[
2202 {
2203 "NonFinite": 3.141592653589793,
2204 "PointerNonFinite": 3.141592653589793
2205 },
2206 {
2207 "NonFinite": "NaN",
2208 "PointerNonFinite": "NaN"
2209 },
2210 {
2211 "NonFinite": "-Infinity",
2212 "PointerNonFinite": "-Infinity"
2213 },
2214 {
2215 "NonFinite": "Infinity",
2216 "PointerNonFinite": "Infinity"
2217 }
2218 ]`,
2219 }, {
2220 name: jsontest.Name("Structs/Format/Maps"),
2221 opts: []Options{jsontext.Multiline(true)},
2222 in: []structFormatMaps{{
2223 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2224 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2225 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2226 }, {
2227 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2228 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2229 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2230 }, {
2231 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2232 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2233 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2234 }},
2235 want: `[
2236 {
2237 "EmitNull": null,
2238 "PointerEmitNull": null,
2239 "EmitEmpty": {},
2240 "PointerEmitEmpty": {},
2241 "EmitDefault": {},
2242 "PointerEmitDefault": {}
2243 },
2244 {
2245 "EmitNull": {},
2246 "PointerEmitNull": {},
2247 "EmitEmpty": {},
2248 "PointerEmitEmpty": {},
2249 "EmitDefault": {},
2250 "PointerEmitDefault": {}
2251 },
2252 {
2253 "EmitNull": {
2254 "k": "v"
2255 },
2256 "PointerEmitNull": {
2257 "k": "v"
2258 },
2259 "EmitEmpty": {
2260 "k": "v"
2261 },
2262 "PointerEmitEmpty": {
2263 "k": "v"
2264 },
2265 "EmitDefault": {
2266 "k": "v"
2267 },
2268 "PointerEmitDefault": {
2269 "k": "v"
2270 }
2271 }
2272 ]`,
2273 }, {
2274 name: jsontest.Name("Structs/Format/Maps/FormatNilMapAsNull"),
2275 opts: []Options{
2276 FormatNilMapAsNull(true),
2277 jsontext.Multiline(true),
2278 },
2279 in: []structFormatMaps{{
2280 EmitNull: map[string]string(nil), PointerEmitNull: addr(map[string]string(nil)),
2281 EmitEmpty: map[string]string(nil), PointerEmitEmpty: addr(map[string]string(nil)),
2282 EmitDefault: map[string]string(nil), PointerEmitDefault: addr(map[string]string(nil)),
2283 }, {
2284 EmitNull: map[string]string{}, PointerEmitNull: addr(map[string]string{}),
2285 EmitEmpty: map[string]string{}, PointerEmitEmpty: addr(map[string]string{}),
2286 EmitDefault: map[string]string{}, PointerEmitDefault: addr(map[string]string{}),
2287 }, {
2288 EmitNull: map[string]string{"k": "v"}, PointerEmitNull: addr(map[string]string{"k": "v"}),
2289 EmitEmpty: map[string]string{"k": "v"}, PointerEmitEmpty: addr(map[string]string{"k": "v"}),
2290 EmitDefault: map[string]string{"k": "v"}, PointerEmitDefault: addr(map[string]string{"k": "v"}),
2291 }},
2292 want: `[
2293 {
2294 "EmitNull": null,
2295 "PointerEmitNull": null,
2296 "EmitEmpty": {},
2297 "PointerEmitEmpty": {},
2298 "EmitDefault": null,
2299 "PointerEmitDefault": null
2300 },
2301 {
2302 "EmitNull": {},
2303 "PointerEmitNull": {},
2304 "EmitEmpty": {},
2305 "PointerEmitEmpty": {},
2306 "EmitDefault": {},
2307 "PointerEmitDefault": {}
2308 },
2309 {
2310 "EmitNull": {
2311 "k": "v"
2312 },
2313 "PointerEmitNull": {
2314 "k": "v"
2315 },
2316 "EmitEmpty": {
2317 "k": "v"
2318 },
2319 "PointerEmitEmpty": {
2320 "k": "v"
2321 },
2322 "EmitDefault": {
2323 "k": "v"
2324 },
2325 "PointerEmitDefault": {
2326 "k": "v"
2327 }
2328 }
2329 ]`,
2330 }, {
2331 name: jsontest.Name("Structs/Format/Slices"),
2332 opts: []Options{jsontext.Multiline(true)},
2333 in: []structFormatSlices{{
2334 EmitNull: []string(nil), PointerEmitNull: addr([]string(nil)),
2335 EmitEmpty: []string(nil), PointerEmitEmpty: addr([]string(nil)),
2336 EmitDefault: []string(nil), PointerEmitDefault: addr([]string(nil)),
2337 }, {
2338 EmitNull: []string{}, PointerEmitNull: addr([]string{}),
2339 EmitEmpty: []string{}, PointerEmitEmpty: addr([]string{}),
2340 EmitDefault: []string{}, PointerEmitDefault: addr([]string{}),
2341 }, {
2342 EmitNull: []string{"v"}, PointerEmitNull: addr([]string{"v"}),
2343 EmitEmpty: []string{"v"}, PointerEmitEmpty: addr([]string{"v"}),
2344 EmitDefault: []string{"v"}, PointerEmitDefault: addr([]string{"v"}),
2345 }},
2346 want: `[
2347 {
2348 "EmitNull": null,
2349 "PointerEmitNull": null,
2350 "EmitEmpty": [],
2351 "PointerEmitEmpty": [],
2352 "EmitDefault": [],
2353 "PointerEmitDefault": []
2354 },
2355 {
2356 "EmitNull": [],
2357 "PointerEmitNull": [],
2358 "EmitEmpty": [],
2359 "PointerEmitEmpty": [],
2360 "EmitDefault": [],
2361 "PointerEmitDefault": []
2362 },
2363 {
2364 "EmitNull": [
2365 "v"
2366 ],
2367 "PointerEmitNull": [
2368 "v"
2369 ],
2370 "EmitEmpty": [
2371 "v"
2372 ],
2373 "PointerEmitEmpty": [
2374 "v"
2375 ],
2376 "EmitDefault": [
2377 "v"
2378 ],
2379 "PointerEmitDefault": [
2380 "v"
2381 ]
2382 }
2383 ]`,
2384 }, {
2385 name: jsontest.Name("Structs/Format/Invalid/Bool"),
2386 in: structFormatInvalid{Bool: true},
2387 want: `{"Bool"`,
2388 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bool":`, "/Bool").withType(0, boolType),
2389 }, {
2390 name: jsontest.Name("Structs/Format/Invalid/String"),
2391 in: structFormatInvalid{String: "string"},
2392 want: `{"String"`,
2393 wantErr: EM(errInvalidFormatFlag).withPos(`{"String":`, "/String").withType(0, stringType),
2394 }, {
2395 name: jsontest.Name("Structs/Format/Invalid/Bytes"),
2396 in: structFormatInvalid{Bytes: []byte("bytes")},
2397 want: `{"Bytes"`,
2398 wantErr: EM(errInvalidFormatFlag).withPos(`{"Bytes":`, "/Bytes").withType(0, bytesType),
2399 }, {
2400 name: jsontest.Name("Structs/Format/Invalid/Int"),
2401 in: structFormatInvalid{Int: 1},
2402 want: `{"Int"`,
2403 wantErr: EM(errInvalidFormatFlag).withPos(`{"Int":`, "/Int").withType(0, T[int64]()),
2404 }, {
2405 name: jsontest.Name("Structs/Format/Invalid/Uint"),
2406 in: structFormatInvalid{Uint: 1},
2407 want: `{"Uint"`,
2408 wantErr: EM(errInvalidFormatFlag).withPos(`{"Uint":`, "/Uint").withType(0, T[uint64]()),
2409 }, {
2410 name: jsontest.Name("Structs/Format/Invalid/Float"),
2411 in: structFormatInvalid{Float: 1},
2412 want: `{"Float"`,
2413 wantErr: EM(errInvalidFormatFlag).withPos(`{"Float":`, "/Float").withType(0, T[float64]()),
2414 }, {
2415 name: jsontest.Name("Structs/Format/Invalid/Map"),
2416 in: structFormatInvalid{Map: map[string]string{}},
2417 want: `{"Map"`,
2418 wantErr: EM(errInvalidFormatFlag).withPos(`{"Map":`, "/Map").withType(0, T[map[string]string]()),
2419 }, {
2420 name: jsontest.Name("Structs/Format/Invalid/Struct"),
2421 in: structFormatInvalid{Struct: structAll{Bool: true}},
2422 want: `{"Struct"`,
2423 wantErr: EM(errInvalidFormatFlag).withPos(`{"Struct":`, "/Struct").withType(0, T[structAll]()),
2424 }, {
2425 name: jsontest.Name("Structs/Format/Invalid/Slice"),
2426 in: structFormatInvalid{Slice: []string{}},
2427 want: `{"Slice"`,
2428 wantErr: EM(errInvalidFormatFlag).withPos(`{"Slice":`, "/Slice").withType(0, T[[]string]()),
2429 }, {
2430 name: jsontest.Name("Structs/Format/Invalid/Array"),
2431 in: structFormatInvalid{Array: [1]string{"string"}},
2432 want: `{"Array"`,
2433 wantErr: EM(errInvalidFormatFlag).withPos(`{"Array":`, "/Array").withType(0, T[[1]string]()),
2434 }, {
2435 name: jsontest.Name("Structs/Format/Invalid/Interface"),
2436 in: structFormatInvalid{Interface: "anything"},
2437 want: `{"Interface"`,
2438 wantErr: EM(errInvalidFormatFlag).withPos(`{"Interface":`, "/Interface").withType(0, T[any]()),
2439 }, {
2440 name: jsontest.Name("Structs/Inline/Zero"),
2441 in: structInlined{},
2442 want: `{"D":""}`,
2443 }, {
2444 name: jsontest.Name("Structs/Inline/Alloc"),
2445 in: structInlined{
2446 X: structInlinedL1{
2447 X: &structInlinedL2{},
2448 StructEmbed1: StructEmbed1{},
2449 },
2450 StructEmbed2: &StructEmbed2{},
2451 },
2452 want: `{"A":"","B":"","D":"","E":"","F":"","G":""}`,
2453 }, {
2454 name: jsontest.Name("Structs/Inline/NonZero"),
2455 in: structInlined{
2456 X: structInlinedL1{
2457 X: &structInlinedL2{A: "A1", B: "B1", C: "C1"},
2458 StructEmbed1: StructEmbed1{C: "C2", D: "D2", E: "E2"},
2459 },
2460 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
2461 },
2462 want: `{"A":"A1","B":"B1","D":"D2","E":"E3","F":"F3","G":"G3"}`,
2463 }, {
2464 name: jsontest.Name("Structs/Inline/DualCycle"),
2465 in: cyclicA{
2466 B1: cyclicB{F: 1},
2467 B2: cyclicB{F: 2},
2468 },
2469 want: `{}`,
2470 }, {
2471 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nil"),
2472 in: structInlineTextValue{X: jsontext.Value(nil)},
2473 want: `{}`,
2474 }, {
2475 name: jsontest.Name("Structs/InlinedFallback/TextValue/Empty"),
2476 in: structInlineTextValue{X: jsontext.Value("")},
2477 want: `{}`,
2478 }, {
2479 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN1"),
2480 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" } `)},
2481 want: `{"fizz":"buzz"}`,
2482 }, {
2483 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyN2"),
2484 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `)},
2485 want: `{"fizz":"buzz","foo":"bar"}`,
2486 }, {
2487 name: jsontest.Name("Structs/InlinedFallback/TextValue/NonEmptyWithOthers"),
2488 in: structInlineTextValue{
2489 A: 1,
2490 X: jsontext.Value(` { "fizz" : "buzz" , "foo" : "bar" } `),
2491 B: 2,
2492 },
2493
2494 want: `{"A":1,"B":2,"fizz":"buzz","foo":"bar"}`,
2495 }, {
2496 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectDuplicateNames"),
2497 opts: []Options{jsontext.AllowDuplicateNames(false)},
2498 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2499 want: `{"fizz":"buzz"`,
2500 wantErr: newDuplicateNameError("/fizz", nil, len64(`{"fizz":"buzz"`)),
2501 }, {
2502 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowDuplicateNames"),
2503 opts: []Options{jsontext.AllowDuplicateNames(true)},
2504 in: structInlineTextValue{X: jsontext.Value(` { "fizz" : "buzz" , "fizz" : "buzz" } `)},
2505 want: `{"fizz":"buzz","fizz":"buzz"}`,
2506 }, {
2507 name: jsontest.Name("Structs/InlinedFallback/TextValue/RejectInvalidUTF8"),
2508 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2509 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2510 want: `{`,
2511 wantErr: newInvalidUTF8Error(len64(`{"`+"\xde\xad"), ""),
2512 }, {
2513 name: jsontest.Name("Structs/InlinedFallback/TextValue/AllowInvalidUTF8"),
2514 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2515 in: structInlineTextValue{X: jsontext.Value(`{"` + "\xde\xad\xbe\xef" + `":"value"}`)},
2516 want: `{"ޭ��":"value"}`,
2517 }, {
2518 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidWhitespace"),
2519 in: structInlineTextValue{X: jsontext.Value("\n\r\t ")},
2520 want: `{`,
2521 wantErr: EM(io.ErrUnexpectedEOF).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2522 }, {
2523 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObject"),
2524 in: structInlineTextValue{X: jsontext.Value(` true `)},
2525 want: `{`,
2526 wantErr: EM(errRawInlinedNotObject).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2527 }, {
2528 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidObjectName"),
2529 in: structInlineTextValue{X: jsontext.Value(` { true : false } `)},
2530 want: `{`,
2531 wantErr: EM(newNonStringNameError(len64(" { "), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2532 }, {
2533 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidEndObject"),
2534 in: structInlineTextValue{X: jsontext.Value(` { "name" : false , } `)},
2535 want: `{"name":false`,
2536 wantErr: EM(newInvalidCharacterError(",", "at start of value", len64(` { "name" : false `), "")).withPos(`{"name":false,`, "").withType(0, T[jsontext.Value]()),
2537 }, {
2538 name: jsontest.Name("Structs/InlinedFallback/TextValue/InvalidDualObject"),
2539 in: structInlineTextValue{X: jsontext.Value(`{}{}`)},
2540 want: `{`,
2541 wantErr: EM(newInvalidCharacterError("{", "after top-level value", len64(`{}`), "")).withPos(`{`, "").withType(0, T[jsontext.Value]()),
2542 }, {
2543 name: jsontest.Name("Structs/InlinedFallback/TextValue/Nested/Nil"),
2544 in: structInlinePointerInlineTextValue{},
2545 want: `{}`,
2546 }, {
2547 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nil"),
2548 in: structInlinePointerTextValue{},
2549 want: `{}`,
2550 }, {
2551 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/NonEmpty"),
2552 in: structInlinePointerTextValue{X: addr(jsontext.Value(` { "fizz" : "buzz" } `))},
2553 want: `{"fizz":"buzz"}`,
2554 }, {
2555 name: jsontest.Name("Structs/InlinedFallback/PointerTextValue/Nested/Nil"),
2556 in: structInlineInlinePointerTextValue{},
2557 want: `{}`,
2558 }, {
2559 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nil"),
2560 in: structInlineMapStringAny{X: nil},
2561 want: `{}`,
2562 }, {
2563 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Empty"),
2564 in: structInlineMapStringAny{X: make(jsonObject)},
2565 want: `{}`,
2566 }, {
2567 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN1"),
2568 in: structInlineMapStringAny{X: jsonObject{"fizz": nil}},
2569 want: `{"fizz":null}`,
2570 }, {
2571 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyN2"),
2572 in: structInlineMapStringAny{X: jsonObject{"fizz": time.Time{}, "buzz": math.Pi}},
2573 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2574 canonicalize: true,
2575 }, {
2576 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/NonEmptyWithOthers"),
2577 in: structInlineMapStringAny{
2578 A: 1,
2579 X: jsonObject{"fizz": nil},
2580 B: 2,
2581 },
2582
2583 want: `{"A":1,"B":2,"fizz":null}`,
2584 }, {
2585 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/RejectInvalidUTF8"),
2586 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2587 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2588 want: `{`,
2589 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, stringType),
2590 }, {
2591 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/AllowInvalidUTF8"),
2592 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2593 in: structInlineMapStringAny{X: jsonObject{"\xde\xad\xbe\xef": nil}},
2594 want: `{"ޭ��":null}`,
2595 }, {
2596 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/InvalidValue"),
2597 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2598 in: structInlineMapStringAny{X: jsonObject{"name": make(chan string)}},
2599 want: `{"name"`,
2600 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2601 }, {
2602 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/Nested/Nil"),
2603 in: structInlinePointerInlineMapStringAny{},
2604 want: `{}`,
2605 }, {
2606 name: jsontest.Name("Structs/InlinedFallback/MapStringAny/MarshalFunc"),
2607 opts: []Options{
2608 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2609 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2610 })),
2611 },
2612 in: structInlineMapStringAny{X: jsonObject{"fizz": 3.14159}},
2613 want: `{"fizz":"3.14159"}`,
2614 }, {
2615 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nil"),
2616 in: structInlinePointerMapStringAny{X: nil},
2617 want: `{}`,
2618 }, {
2619 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/NonEmpty"),
2620 in: structInlinePointerMapStringAny{X: addr(jsonObject{"name": "value"})},
2621 want: `{"name":"value"}`,
2622 }, {
2623 name: jsontest.Name("Structs/InlinedFallback/PointerMapStringAny/Nested/Nil"),
2624 in: structInlineInlinePointerMapStringAny{},
2625 want: `{}`,
2626 }, {
2627 name: jsontest.Name("Structs/InlinedFallback/MapStringInt"),
2628 in: structInlineMapStringInt{
2629 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2630 },
2631 want: `{"one":1,"two":2,"zero":0}`,
2632 canonicalize: true,
2633 }, {
2634 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic"),
2635 opts: []Options{Deterministic(true)},
2636 in: structInlineMapStringInt{
2637 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2638 },
2639 want: `{"one":1,"two":2,"zero":0}`,
2640 }, {
2641 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+RejectDuplicateNames"),
2642 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(false)},
2643 in: structInlineMapStringInt{
2644 X: map[string]int{"\xff": 0, "\xfe": 1},
2645 },
2646 want: `{"�":1`,
2647 wantErr: newDuplicateNameError("", []byte(`"�"`), len64(`{"�":1`)),
2648 }, {
2649 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/Deterministic+AllowInvalidUTF8+AllowDuplicateNames"),
2650 opts: []Options{Deterministic(true), jsontext.AllowInvalidUTF8(true), jsontext.AllowDuplicateNames(true)},
2651 in: structInlineMapStringInt{
2652 X: map[string]int{"\xff": 0, "\xfe": 1},
2653 },
2654 want: `{"�":1,"�":0}`,
2655 }, {
2656 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/StringifiedNumbers"),
2657 opts: []Options{StringifyNumbers(true)},
2658 in: structInlineMapStringInt{
2659 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2660 },
2661 want: `{"one":"1","two":"2","zero":"0"}`,
2662 canonicalize: true,
2663 }, {
2664 name: jsontest.Name("Structs/InlinedFallback/MapStringInt/MarshalFunc"),
2665 opts: []Options{
2666 WithMarshalers(JoinMarshalers(
2667
2668 MarshalFunc(func(v string) ([]byte, error) {
2669 return []byte(fmt.Sprintf(`"%q"`, strings.ToUpper(v))), nil
2670 }),
2671 MarshalFunc(func(v int) ([]byte, error) {
2672 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2673 }),
2674 )),
2675 },
2676 in: structInlineMapStringInt{
2677 X: map[string]int{"zero": 0, "one": 1, "two": 2},
2678 },
2679 want: `{"one":"1","two":"2","zero":"0"}`,
2680 canonicalize: true,
2681 }, {
2682 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt"),
2683 in: structInlineMapNamedStringInt{
2684 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2685 },
2686 want: `{"one":1,"two":2,"zero":0}`,
2687 canonicalize: true,
2688 }, {
2689 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringInt/Deterministic"),
2690 opts: []Options{Deterministic(true)},
2691 in: structInlineMapNamedStringInt{
2692 X: map[namedString]int{"zero": 0, "one": 1, "two": 2},
2693 },
2694 want: `{"one":1,"two":2,"zero":0}`,
2695 }, {
2696 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Nil"),
2697 in: structInlineMapNamedStringAny{X: nil},
2698 want: `{}`,
2699 }, {
2700 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/Empty"),
2701 in: structInlineMapNamedStringAny{X: make(map[namedString]any)},
2702 want: `{}`,
2703 }, {
2704 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN1"),
2705 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": nil}},
2706 want: `{"fizz":null}`,
2707 }, {
2708 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyN2"),
2709 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": time.Time{}, "buzz": math.Pi}},
2710 want: `{"buzz":3.141592653589793,"fizz":"0001-01-01T00:00:00Z"}`,
2711 canonicalize: true,
2712 }, {
2713 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/NonEmptyWithOthers"),
2714 in: structInlineMapNamedStringAny{
2715 A: 1,
2716 X: map[namedString]any{"fizz": nil},
2717 B: 2,
2718 },
2719
2720 want: `{"A":1,"B":2,"fizz":null}`,
2721 }, {
2722 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/RejectInvalidUTF8"),
2723 opts: []Options{jsontext.AllowInvalidUTF8(false)},
2724 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2725 want: `{`,
2726 wantErr: EM(jsonwire.ErrInvalidUTF8).withPos(`{`, "").withType(0, T[namedString]()),
2727 }, {
2728 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/AllowInvalidUTF8"),
2729 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2730 in: structInlineMapNamedStringAny{X: map[namedString]any{"\xde\xad\xbe\xef": nil}},
2731 want: `{"ޭ��":null}`,
2732 }, {
2733 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/InvalidValue"),
2734 opts: []Options{jsontext.AllowInvalidUTF8(true)},
2735 in: structInlineMapNamedStringAny{X: map[namedString]any{"name": make(chan string)}},
2736 want: `{"name"`,
2737 wantErr: EM(nil).withPos(`{"name":`, "/name").withType(0, T[chan string]()),
2738 }, {
2739 name: jsontest.Name("Structs/InlinedFallback/MapNamedStringAny/MarshalFunc"),
2740 opts: []Options{
2741 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
2742 return []byte(fmt.Sprintf(`"%v"`, v)), nil
2743 })),
2744 },
2745 in: structInlineMapNamedStringAny{X: map[namedString]any{"fizz": 3.14159}},
2746 want: `{"fizz":"3.14159"}`,
2747 }, {
2748 name: jsontest.Name("Structs/InlinedFallback/DiscardUnknownMembers"),
2749 opts: []Options{DiscardUnknownMembers(true)},
2750 in: structInlineTextValue{
2751 A: 1,
2752 X: jsontext.Value(` { "fizz" : "buzz" } `),
2753 B: 2,
2754 },
2755
2756 want: `{"A":1,"B":2,"fizz":"buzz"}`,
2757 }, {
2758 name: jsontest.Name("Structs/UnknownFallback/DiscardUnknownMembers"),
2759 opts: []Options{DiscardUnknownMembers(true)},
2760 in: structUnknownTextValue{
2761 A: 1,
2762 X: jsontext.Value(` { "fizz" : "buzz" } `),
2763 B: 2,
2764 },
2765 want: `{"A":1,"B":2}`,
2766 }, {
2767 name: jsontest.Name("Structs/UnknownFallback"),
2768 in: structUnknownTextValue{
2769 A: 1,
2770 X: jsontext.Value(` { "fizz" : "buzz" } `),
2771 B: 2,
2772 },
2773 want: `{"A":1,"B":2,"fizz":"buzz"}`,
2774 }, {
2775 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other"),
2776 in: structNoCaseInlineTextValue{
2777 X: jsontext.Value(`{"dupe":"","dupe":""}`),
2778 },
2779 want: `{"dupe":""`,
2780 wantErr: newDuplicateNameError("", []byte(`"dupe"`), len64(`{"dupe":""`)),
2781 }, {
2782 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/Other/AllowDuplicateNames"),
2783 opts: []Options{jsontext.AllowDuplicateNames(true)},
2784 in: structNoCaseInlineTextValue{
2785 X: jsontext.Value(`{"dupe": "", "dupe": ""}`),
2786 },
2787 want: `{"dupe":"","dupe":""}`,
2788 }, {
2789 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferent"),
2790 in: structNoCaseInlineTextValue{
2791 X: jsontext.Value(`{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""}`),
2792 },
2793 want: `{"Aaa":"","AaA":"","AAa":"","AAA":""}`,
2794 }, {
2795 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict"),
2796 in: structNoCaseInlineTextValue{
2797 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2798 },
2799 want: `{"Aaa":""`,
2800 wantErr: newDuplicateNameError("", []byte(`"Aaa"`), len64(`{"Aaa":""`)),
2801 }, {
2802 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflict/AllowDuplicateNames"),
2803 opts: []Options{jsontext.AllowDuplicateNames(true)},
2804 in: structNoCaseInlineTextValue{
2805 X: jsontext.Value(`{"Aaa": "", "Aaa": ""}`),
2806 },
2807 want: `{"Aaa":"","Aaa":""}`,
2808 }, {
2809 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict"),
2810 in: structNoCaseInlineTextValue{
2811 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2812 },
2813 want: `{"Aaa":"","AaA":""`,
2814 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"Aaa":"","AaA":""`)),
2815 }, {
2816 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflict/AllowDuplicateNames"),
2817 opts: []Options{jsontext.AllowDuplicateNames(true)},
2818 in: structNoCaseInlineTextValue{
2819 X: jsontext.Value(`{"Aaa": "", "AaA": "", "aaa": ""}`),
2820 },
2821 want: `{"Aaa":"","AaA":"","aaa":""}`,
2822 }, {
2823 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactDifferentWithField"),
2824 in: structNoCaseInlineTextValue{
2825 AAA: "x",
2826 AaA: "x",
2827 X: jsontext.Value(`{"Aaa": ""}`),
2828 },
2829 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2830 }, {
2831 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/ExactConflictWithField"),
2832 in: structNoCaseInlineTextValue{
2833 AAA: "x",
2834 AaA: "x",
2835 X: jsontext.Value(`{"AAA": ""}`),
2836 },
2837 want: `{"AAA":"x","AaA":"x"`,
2838 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2839 }, {
2840 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineTextValue/NoCaseConflictWithField"),
2841 in: structNoCaseInlineTextValue{
2842 AAA: "x",
2843 AaA: "x",
2844 X: jsontext.Value(`{"aaa": ""}`),
2845 },
2846 want: `{"AAA":"x","AaA":"x"`,
2847 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2848 }, {
2849 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveDelimiter"),
2850 in: structNoCaseInlineTextValue{
2851 AaA: "x",
2852 X: jsontext.Value(`{"aa_a": ""}`),
2853 },
2854 want: `{"AaA":"x"`,
2855 wantErr: newDuplicateNameError("", []byte(`"aa_a"`), len64(`{"AaA":"x"`)),
2856 }, {
2857 name: jsontest.Name("Structs/DuplicateName/MatchCaseSensitiveDelimiter"),
2858 opts: []Options{jsonflags.MatchCaseSensitiveDelimiter | 1},
2859 in: structNoCaseInlineTextValue{
2860 AaA: "x",
2861 X: jsontext.Value(`{"aa_a": ""}`),
2862 },
2863 want: `{"AaA":"x","aa_a":""}`,
2864 }, {
2865 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2866 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2867 in: structNoCaseInlineTextValue{
2868 AaA: "x",
2869 X: jsontext.Value(`{"aa_a": ""}`),
2870 },
2871 want: `{"AaA":"x","aa_a":""}`,
2872 }, {
2873 name: jsontest.Name("Structs/DuplicateName/MatchCaseInsensitiveNames+MatchCaseSensitiveDelimiter"),
2874 opts: []Options{MatchCaseInsensitiveNames(true), jsonflags.MatchCaseSensitiveDelimiter | 1},
2875 in: structNoCaseInlineTextValue{
2876 AA_b: "x",
2877 X: jsontext.Value(`{"aa_b": ""}`),
2878 },
2879 want: `{"AA_b":"x"`,
2880 wantErr: newDuplicateNameError("", []byte(`"aa_b"`), len64(`{"AA_b":"x"`)),
2881 }, {
2882 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferent"),
2883 in: structNoCaseInlineMapStringAny{
2884 X: jsonObject{"Aaa": "", "AaA": "", "AAa": "", "AAA": ""},
2885 },
2886 want: `{"AAA":"","AAa":"","AaA":"","Aaa":""}`,
2887 canonicalize: true,
2888 }, {
2889 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactDifferentWithField"),
2890 in: structNoCaseInlineMapStringAny{
2891 AAA: "x",
2892 AaA: "x",
2893 X: jsonObject{"Aaa": ""},
2894 },
2895 want: `{"AAA":"x","AaA":"x","Aaa":""}`,
2896 }, {
2897 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/ExactConflictWithField"),
2898 in: structNoCaseInlineMapStringAny{
2899 AAA: "x",
2900 AaA: "x",
2901 X: jsonObject{"AAA": ""},
2902 },
2903 want: `{"AAA":"x","AaA":"x"`,
2904 wantErr: newDuplicateNameError("", []byte(`"AAA"`), len64(`{"AAA":"x","AaA":"x"`)),
2905 }, {
2906 name: jsontest.Name("Structs/DuplicateName/NoCaseInlineMapStringAny/NoCaseConflictWithField"),
2907 in: structNoCaseInlineMapStringAny{
2908 AAA: "x",
2909 AaA: "x",
2910 X: jsonObject{"aaa": ""},
2911 },
2912 want: `{"AAA":"x","AaA":"x"`,
2913 wantErr: newDuplicateNameError("", []byte(`"aaa"`), len64(`{"AAA":"x","AaA":"x"`)),
2914 }, {
2915 name: jsontest.Name("Structs/Invalid/Conflicting"),
2916 in: structConflicting{},
2917 want: ``,
2918 wantErr: EM(errors.New("Go struct fields A and B conflict over JSON object name \"conflict\"")).withType(0, T[structConflicting]()),
2919 }, {
2920 name: jsontest.Name("Structs/Invalid/NoneExported"),
2921 in: structNoneExported{},
2922 want: ``,
2923 wantErr: EM(errNoExportedFields).withType(0, T[structNoneExported]()),
2924 }, {
2925 name: jsontest.Name("Structs/Invalid/MalformedTag"),
2926 in: structMalformedTag{},
2927 want: ``,
2928 wantErr: EM(errors.New("Go struct field Malformed has malformed `json` tag: invalid character '\"' at start of option (expecting Unicode letter or single quote)")).withType(0, T[structMalformedTag]()),
2929 }, {
2930 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
2931 in: structUnexportedTag{},
2932 want: ``,
2933 wantErr: EM(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType(0, T[structUnexportedTag]()),
2934 }, {
2935 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
2936 in: structExportedEmbedded{"hello"},
2937 want: ``,
2938 wantErr: EM(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structExportedEmbedded]()),
2939 }, {
2940 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
2941 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2942 in: structExportedEmbedded{"hello"},
2943 want: `{"NamedString":"hello"}`,
2944 }, {
2945 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
2946 in: structExportedEmbeddedTag{"hello"},
2947 want: `{"name":"hello"}`,
2948 }, {
2949 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
2950 in: structUnexportedEmbedded{},
2951 want: ``,
2952 wantErr: EM(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType(0, T[structUnexportedEmbedded]()),
2953 }, {
2954 name: jsontest.Name("Structs/Valid/UnexportedEmbedded"),
2955 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2956 in: structUnexportedEmbedded{},
2957 want: `{}`,
2958 }, {
2959 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedTag"),
2960 in: structUnexportedEmbeddedTag{},
2961 wantErr: EM(errors.New("Go struct field namedString is not exported")).withType(0, T[structUnexportedEmbeddedTag]()),
2962 }, {
2963 name: jsontest.Name("Structs/Valid/UnexportedEmbeddedTag"),
2964 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2965 in: structUnexportedEmbeddedTag{},
2966 want: `{}`,
2967 }, {
2968 name: jsontest.Name("Structs/Invalid/UnexportedEmbeddedMethodTag"),
2969 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
2970 in: structUnexportedEmbeddedMethodTag{},
2971 want: `{}`,
2972 }, {
2973 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/Zero"),
2974 in: structUnexportedEmbeddedStruct{},
2975 want: `{"FizzBuzz":0,"Addr":""}`,
2976 }, {
2977 name: jsontest.Name("Structs/UnexportedEmbeddedStruct/NonZero"),
2978 in: structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2979 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2980 }, {
2981 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
2982 in: structUnexportedEmbeddedStructPointer{},
2983 want: `{"FizzBuzz":0}`,
2984 }, {
2985 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Zero"),
2986 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{}, 0, &structNestedAddr{}},
2987 want: `{"FizzBuzz":0,"Addr":""}`,
2988 }, {
2989 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/NonZero"),
2990 in: structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}},
2991 want: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
2992 }, {
2993 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
2994 opts: []Options{invalidFormatOption},
2995 in: struct{}{},
2996 want: `{}`,
2997 }, {
2998 name: jsontest.Name("Slices/Interface"),
2999 in: []any{
3000 false, true,
3001 "hello", []byte("world"),
3002 int32(-32), namedInt64(-64),
3003 uint32(+32), namedUint64(+64),
3004 float32(32.32), namedFloat64(64.64),
3005 },
3006 want: `[false,true,"hello","d29ybGQ=",-32,-64,32,64,32.32,64.64]`,
3007 }, {
3008 name: jsontest.Name("Slices/Invalid/Channel"),
3009 in: [](chan string){nil},
3010 want: `[`,
3011 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3012 }, {
3013 name: jsontest.Name("Slices/RecursiveSlice"),
3014 in: recursiveSlice{
3015 nil,
3016 {},
3017 {nil},
3018 {nil, {}},
3019 },
3020 want: `[[],[],[[]],[[],[]]]`,
3021 }, {
3022 name: jsontest.Name("Slices/CyclicSlice"),
3023 in: func() recursiveSlice {
3024 s := recursiveSlice{{}}
3025 s[0] = s
3026 return s
3027 }(),
3028 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[`,
3029 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat("[", startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/0", startDetectingCyclesAfter+1))).withType(0, T[recursiveSlice]()),
3030 }, {
3031 name: jsontest.Name("Slices/NonCyclicSlice"),
3032 in: func() []any {
3033 v := []any{nil, nil}
3034 v[1] = v[:1]
3035 for i := 1000; i > 0; i-- {
3036 v = []any{v}
3037 }
3038 return v
3039 }(),
3040 want: strings.Repeat(`[`, startDetectingCyclesAfter) + `[null,[null]]` + strings.Repeat(`]`, startDetectingCyclesAfter),
3041 }, {
3042 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
3043 opts: []Options{invalidFormatOption},
3044 in: []string{"hello", "goodbye"},
3045 want: `["hello","goodbye"]`,
3046 }, {
3047 name: jsontest.Name("Arrays/Empty"),
3048 in: [0]struct{}{},
3049 want: `[]`,
3050 }, {
3051 name: jsontest.Name("Arrays/Bool"),
3052 in: [2]bool{false, true},
3053 want: `[false,true]`,
3054 }, {
3055 name: jsontest.Name("Arrays/String"),
3056 in: [2]string{"hello", "goodbye"},
3057 want: `["hello","goodbye"]`,
3058 }, {
3059 name: jsontest.Name("Arrays/Bytes"),
3060 in: [2][]byte{[]byte("hello"), []byte("goodbye")},
3061 want: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
3062 }, {
3063 name: jsontest.Name("Arrays/Int"),
3064 in: [2]int64{math.MinInt64, math.MaxInt64},
3065 want: `[-9223372036854775808,9223372036854775807]`,
3066 }, {
3067 name: jsontest.Name("Arrays/Uint"),
3068 in: [2]uint64{0, math.MaxUint64},
3069 want: `[0,18446744073709551615]`,
3070 }, {
3071 name: jsontest.Name("Arrays/Float"),
3072 in: [2]float64{-math.MaxFloat64, +math.MaxFloat64},
3073 want: `[-1.7976931348623157e+308,1.7976931348623157e+308]`,
3074 }, {
3075 name: jsontest.Name("Arrays/Invalid/Channel"),
3076 in: new([1]chan string),
3077 want: `[`,
3078 wantErr: EM(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
3079 }, {
3080 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
3081 opts: []Options{invalidFormatOption},
3082 in: [2]string{"hello", "goodbye"},
3083 want: `["hello","goodbye"]`,
3084 }, {
3085 name: jsontest.Name("Pointers/NilL0"),
3086 in: (*int)(nil),
3087 want: `null`,
3088 }, {
3089 name: jsontest.Name("Pointers/NilL1"),
3090 in: new(*int),
3091 want: `null`,
3092 }, {
3093 name: jsontest.Name("Pointers/Bool"),
3094 in: addr(addr(bool(true))),
3095 want: `true`,
3096 }, {
3097 name: jsontest.Name("Pointers/String"),
3098 in: addr(addr(string("string"))),
3099 want: `"string"`,
3100 }, {
3101 name: jsontest.Name("Pointers/Bytes"),
3102 in: addr(addr([]byte("bytes"))),
3103 want: `"Ynl0ZXM="`,
3104 }, {
3105 name: jsontest.Name("Pointers/Int"),
3106 in: addr(addr(int(-100))),
3107 want: `-100`,
3108 }, {
3109 name: jsontest.Name("Pointers/Uint"),
3110 in: addr(addr(uint(100))),
3111 want: `100`,
3112 }, {
3113 name: jsontest.Name("Pointers/Float"),
3114 in: addr(addr(float64(3.14159))),
3115 want: `3.14159`,
3116 }, {
3117 name: jsontest.Name("Pointers/CyclicPointer"),
3118 in: func() *recursivePointer {
3119 p := new(recursivePointer)
3120 p.P = p
3121 return p
3122 }(),
3123 want: strings.Repeat(`{"P":`, startDetectingCyclesAfter) + `{"P"`,
3124 wantErr: EM(internal.ErrCycle).withPos(strings.Repeat(`{"P":`, startDetectingCyclesAfter+1), jsontext.Pointer(strings.Repeat("/P", startDetectingCyclesAfter+1))).withType(0, T[*recursivePointer]()),
3125 }, {
3126 name: jsontest.Name("Pointers/IgnoreInvalidFormat"),
3127 opts: []Options{invalidFormatOption},
3128 in: addr(addr(bool(true))),
3129 want: `true`,
3130 }, {
3131 name: jsontest.Name("Interfaces/Nil/Empty"),
3132 in: [1]any{nil},
3133 want: `[null]`,
3134 }, {
3135 name: jsontest.Name("Interfaces/Nil/NonEmpty"),
3136 in: [1]io.Reader{nil},
3137 want: `[null]`,
3138 }, {
3139 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
3140 opts: []Options{invalidFormatOption},
3141 in: [1]io.Reader{nil},
3142 want: `[null]`,
3143 }, {
3144 name: jsontest.Name("Interfaces/Any"),
3145 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}, [8]byte{}}},
3146 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3147 }, {
3148 name: jsontest.Name("Interfaces/Any/Named"),
3149 in: struct{ X namedAny }{[]namedAny{nil, false, "", 0.0, map[string]namedAny{}, []namedAny{}, [8]byte{}}},
3150 want: `{"X":[null,false,"",0,{},[],"AAAAAAAAAAA="]}`,
3151 }, {
3152 name: jsontest.Name("Interfaces/Any/Stringified"),
3153 opts: []Options{StringifyNumbers(true)},
3154 in: struct{ X any }{0.0},
3155 want: `{"X":"0"}`,
3156 }, {
3157 name: jsontest.Name("Interfaces/Any/MarshalFunc/Any"),
3158 opts: []Options{
3159 WithMarshalers(MarshalFunc(func(v any) ([]byte, error) {
3160 return []byte(`"called"`), nil
3161 })),
3162 },
3163 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3164 want: `"called"`,
3165 }, {
3166 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bool"),
3167 opts: []Options{
3168 WithMarshalers(MarshalFunc(func(v bool) ([]byte, error) {
3169 return []byte(`"called"`), nil
3170 })),
3171 },
3172 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3173 want: `{"X":[null,"called","",0,{},[]]}`,
3174 }, {
3175 name: jsontest.Name("Interfaces/Any/MarshalFunc/String"),
3176 opts: []Options{
3177 WithMarshalers(MarshalFunc(func(v string) ([]byte, error) {
3178 return []byte(`"called"`), nil
3179 })),
3180 },
3181 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3182 want: `{"X":[null,false,"called",0,{},[]]}`,
3183 }, {
3184 name: jsontest.Name("Interfaces/Any/MarshalFunc/Float64"),
3185 opts: []Options{
3186 WithMarshalers(MarshalFunc(func(v float64) ([]byte, error) {
3187 return []byte(`"called"`), nil
3188 })),
3189 },
3190 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3191 want: `{"X":[null,false,"","called",{},[]]}`,
3192 }, {
3193 name: jsontest.Name("Interfaces/Any/MarshalFunc/MapStringAny"),
3194 opts: []Options{
3195 WithMarshalers(MarshalFunc(func(v map[string]any) ([]byte, error) {
3196 return []byte(`"called"`), nil
3197 })),
3198 },
3199 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3200 want: `{"X":[null,false,"",0,"called",[]]}`,
3201 }, {
3202 name: jsontest.Name("Interfaces/Any/MarshalFunc/SliceAny"),
3203 opts: []Options{
3204 WithMarshalers(MarshalFunc(func(v []any) ([]byte, error) {
3205 return []byte(`"called"`), nil
3206 })),
3207 },
3208 in: struct{ X any }{[]any{nil, false, "", 0.0, map[string]any{}, []any{}}},
3209 want: `{"X":"called"}`,
3210 }, {
3211 name: jsontest.Name("Interfaces/Any/MarshalFunc/Bytes"),
3212 opts: []Options{
3213 WithMarshalers(MarshalFunc(func(v [8]byte) ([]byte, error) {
3214 return []byte(`"called"`), nil
3215 })),
3216 },
3217 in: struct{ X any }{[8]byte{}},
3218 want: `{"X":"called"}`,
3219 }, {
3220 name: jsontest.Name("Interfaces/Any/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.FormatDurationAsNano | 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.ParseBytesWithLooseRFC4648 | 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: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF},
7142 }, {
7143 name: jsontest.Name("Structs/Invalid/ErrUnexpectedEOF"),
7144 inBuf: " \n\r\t",
7145 inVal: addr(structAll{}),
7146 want: addr(structAll{}),
7147 wantErr: &jsontext.SyntacticError{Err: io.ErrUnexpectedEOF, ByteOffset: len64(" \n\r\t")},
7148 }, {
7149 name: jsontest.Name("Structs/Invalid/NestedErrUnexpectedEOF"),
7150 inBuf: `{"Pointer":`,
7151 inVal: addr(structAll{}),
7152 want: addr(structAll{Pointer: new(structAll)}),
7153 wantErr: &jsontext.SyntacticError{ByteOffset: len64(`{"Pointer":`), JSONPointer: "/Pointer", Err: io.ErrUnexpectedEOF},
7154 }, {
7155 name: jsontest.Name("Structs/Invalid/Conflicting"),
7156 inBuf: `{}`,
7157 inVal: addr(structConflicting{}),
7158 want: addr(structConflicting{}),
7159 wantErr: EU(errors.New(`Go struct fields A and B conflict over JSON object name "conflict"`)).withType('{', T[structConflicting]()),
7160 }, {
7161 name: jsontest.Name("Structs/Invalid/NoneExported"),
7162 inBuf: ` {}`,
7163 inVal: addr(structNoneExported{}),
7164 want: addr(structNoneExported{}),
7165 wantErr: EU(errNoExportedFields).withPos(` `, "").withType('{', T[structNoneExported]()),
7166 }, {
7167 name: jsontest.Name("Structs/Invalid/MalformedTag"),
7168 inBuf: `{}`,
7169 inVal: addr(structMalformedTag{}),
7170 want: addr(structMalformedTag{}),
7171 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]()),
7172 }, {
7173 name: jsontest.Name("Structs/Invalid/UnexportedTag"),
7174 inBuf: `{}`,
7175 inVal: addr(structUnexportedTag{}),
7176 want: addr(structUnexportedTag{}),
7177 wantErr: EU(errors.New("unexported Go struct field unexported cannot have non-ignored `json:\"name\"` tag")).withType('{', T[structUnexportedTag]()),
7178 }, {
7179 name: jsontest.Name("Structs/Invalid/ExportedEmbedded"),
7180 inBuf: `{"NamedString":"hello"}`,
7181 inVal: addr(structExportedEmbedded{}),
7182 want: addr(structExportedEmbedded{}),
7183 wantErr: EU(errors.New("embedded Go struct field NamedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structExportedEmbedded]()),
7184 }, {
7185 name: jsontest.Name("Structs/Valid/ExportedEmbedded"),
7186 opts: []Options{jsonflags.ReportErrorsWithLegacySemantics | 1},
7187 inBuf: `{"NamedString":"hello"}`,
7188 inVal: addr(structExportedEmbedded{}),
7189 want: addr(structExportedEmbedded{"hello"}),
7190 }, {
7191 name: jsontest.Name("Structs/Valid/ExportedEmbeddedTag"),
7192 inBuf: `{"name":"hello"}`,
7193 inVal: addr(structExportedEmbeddedTag{}),
7194 want: addr(structExportedEmbeddedTag{"hello"}),
7195 }, {
7196 name: jsontest.Name("Structs/Invalid/UnexportedEmbedded"),
7197 inBuf: `{}`,
7198 inVal: addr(structUnexportedEmbedded{}),
7199 want: addr(structUnexportedEmbedded{}),
7200 wantErr: EU(errors.New("embedded Go struct field namedString of non-struct type must be explicitly given a JSON name")).withType('{', T[structUnexportedEmbedded]()),
7201 }, {
7202 name: jsontest.Name("Structs/UnexportedEmbeddedStruct"),
7203 inBuf: `{"Bool":true,"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7204 inVal: addr(structUnexportedEmbeddedStruct{}),
7205 want: addr(structUnexportedEmbeddedStruct{structOmitZeroAll{Bool: true}, 5, structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7206 }, {
7207 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7208 inBuf: `{"Bool":true,"FizzBuzz":5}`,
7209 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7210 wantErr: EU(errNilField).withPos(`{"Bool":`, "/Bool").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7211 }, {
7212 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7213 inBuf: `{"FizzBuzz":5,"Addr":"192.168.0.1"}`,
7214 inVal: addr(structUnexportedEmbeddedStructPointer{}),
7215 wantErr: EU(errNilField).withPos(`{"FizzBuzz":5,"Addr":`, "/Addr").withType(0, T[structUnexportedEmbeddedStructPointer]()),
7216 }, {
7217 name: jsontest.Name("Structs/UnexportedEmbeddedStructPointer/Nil"),
7218 inBuf: `{"Bool":true,"FizzBuzz":10,"Addr":"192.168.0.1"}`,
7219 inVal: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Int: 5}, 5, &structNestedAddr{netip.AddrFrom4([4]byte{127, 0, 0, 1})}}),
7220 want: addr(structUnexportedEmbeddedStructPointer{&structOmitZeroAll{Bool: true, Int: 5}, 10, &structNestedAddr{netip.AddrFrom4([4]byte{192, 168, 0, 1})}}),
7221 }, {
7222 name: jsontest.Name("Structs/Unknown"),
7223 inBuf: `{
7224 "object0": {},
7225 "object1": {"key1": "value"},
7226 "object2": {"key1": "value", "key2": "value"},
7227 "objects": {"":{"":{"":{}}}},
7228 "array0": [],
7229 "array1": ["value1"],
7230 "array2": ["value1", "value2"],
7231 "array": [[[]]],
7232 "scalars": [null, false, true, "string", 12.345]
7233 }`,
7234 inVal: addr(struct{}{}),
7235 want: addr(struct{}{}),
7236 }, {
7237 name: jsontest.Name("Structs/IgnoreInvalidFormat"),
7238 opts: []Options{invalidFormatOption},
7239 inBuf: `{"Field":"Value"}`,
7240 inVal: addr(struct{ Field string }{}),
7241 want: addr(struct{ Field string }{"Value"}),
7242 }, {
7243 name: jsontest.Name("Slices/Null"),
7244 inBuf: `null`,
7245 inVal: addr([]string{"something"}),
7246 want: addr([]string(nil)),
7247 }, {
7248 name: jsontest.Name("Slices/Bool"),
7249 inBuf: `[true,false]`,
7250 inVal: new([]bool),
7251 want: addr([]bool{true, false}),
7252 }, {
7253 name: jsontest.Name("Slices/String"),
7254 inBuf: `["hello","goodbye"]`,
7255 inVal: new([]string),
7256 want: addr([]string{"hello", "goodbye"}),
7257 }, {
7258 name: jsontest.Name("Slices/Bytes"),
7259 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7260 inVal: new([][]byte),
7261 want: addr([][]byte{[]byte("hello"), []byte("goodbye")}),
7262 }, {
7263 name: jsontest.Name("Slices/Int"),
7264 inBuf: `[-2,-1,0,1,2]`,
7265 inVal: new([]int),
7266 want: addr([]int{-2, -1, 0, 1, 2}),
7267 }, {
7268 name: jsontest.Name("Slices/Uint"),
7269 inBuf: `[0,1,2,3,4]`,
7270 inVal: new([]uint),
7271 want: addr([]uint{0, 1, 2, 3, 4}),
7272 }, {
7273 name: jsontest.Name("Slices/Float"),
7274 inBuf: `[3.14159,12.34]`,
7275 inVal: new([]float64),
7276 want: addr([]float64{3.14159, 12.34}),
7277 }, {
7278
7279
7280
7281 name: jsontest.Name("Slices/Merge"),
7282 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7283 inVal: addr([]map[string]string{{"k1": "v1"}, {"k2": "v2"}}[:1]),
7284 want: addr([]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7285 }, {
7286 name: jsontest.Name("Slices/Invalid/Channel"),
7287 inBuf: `["hello"]`,
7288 inVal: new([]chan string),
7289 want: addr([]chan string{nil}),
7290 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7291 }, {
7292 name: jsontest.Name("Slices/RecursiveSlice"),
7293 inBuf: `[[],[],[[]],[[],[]]]`,
7294 inVal: new(recursiveSlice),
7295 want: addr(recursiveSlice{
7296 {},
7297 {},
7298 {{}},
7299 {{}, {}},
7300 }),
7301 }, {
7302 name: jsontest.Name("Slices/Invalid/Bool"),
7303 inBuf: `true`,
7304 inVal: addr([]string{"nochange"}),
7305 want: addr([]string{"nochange"}),
7306 wantErr: EU(nil).withType('t', T[[]string]()),
7307 }, {
7308 name: jsontest.Name("Slices/Invalid/String"),
7309 inBuf: `""`,
7310 inVal: addr([]string{"nochange"}),
7311 want: addr([]string{"nochange"}),
7312 wantErr: EU(nil).withType('"', T[[]string]()),
7313 }, {
7314 name: jsontest.Name("Slices/Invalid/Number"),
7315 inBuf: `0`,
7316 inVal: addr([]string{"nochange"}),
7317 want: addr([]string{"nochange"}),
7318 wantErr: EU(nil).withType('0', T[[]string]()),
7319 }, {
7320 name: jsontest.Name("Slices/Invalid/Object"),
7321 inBuf: `{}`,
7322 inVal: addr([]string{"nochange"}),
7323 want: addr([]string{"nochange"}),
7324 wantErr: EU(nil).withType('{', T[[]string]()),
7325 }, {
7326 name: jsontest.Name("Slices/IgnoreInvalidFormat"),
7327 opts: []Options{invalidFormatOption},
7328 inBuf: `[false,true]`,
7329 inVal: addr([]bool{true, false}),
7330 want: addr([]bool{false, true}),
7331 }, {
7332 name: jsontest.Name("Arrays/Null"),
7333 inBuf: `null`,
7334 inVal: addr([1]string{"something"}),
7335 want: addr([1]string{}),
7336 }, {
7337 name: jsontest.Name("Arrays/Bool"),
7338 inBuf: `[true,false]`,
7339 inVal: new([2]bool),
7340 want: addr([2]bool{true, false}),
7341 }, {
7342 name: jsontest.Name("Arrays/String"),
7343 inBuf: `["hello","goodbye"]`,
7344 inVal: new([2]string),
7345 want: addr([2]string{"hello", "goodbye"}),
7346 }, {
7347 name: jsontest.Name("Arrays/Bytes"),
7348 inBuf: `["aGVsbG8=","Z29vZGJ5ZQ=="]`,
7349 inVal: new([2][]byte),
7350 want: addr([2][]byte{[]byte("hello"), []byte("goodbye")}),
7351 }, {
7352 name: jsontest.Name("Arrays/Int"),
7353 inBuf: `[-2,-1,0,1,2]`,
7354 inVal: new([5]int),
7355 want: addr([5]int{-2, -1, 0, 1, 2}),
7356 }, {
7357 name: jsontest.Name("Arrays/Uint"),
7358 inBuf: `[0,1,2,3,4]`,
7359 inVal: new([5]uint),
7360 want: addr([5]uint{0, 1, 2, 3, 4}),
7361 }, {
7362 name: jsontest.Name("Arrays/Float"),
7363 inBuf: `[3.14159,12.34]`,
7364 inVal: new([2]float64),
7365 want: addr([2]float64{3.14159, 12.34}),
7366 }, {
7367
7368
7369 name: jsontest.Name("Arrays/Merge"),
7370 inBuf: `[{"k3":"v3"},{"k4":"v4"}]`,
7371 inVal: addr([2]map[string]string{{"k1": "v1"}, {"k2": "v2"}}),
7372 want: addr([2]map[string]string{{"k3": "v3"}, {"k4": "v4"}}),
7373 }, {
7374 name: jsontest.Name("Arrays/Invalid/Channel"),
7375 inBuf: `["hello"]`,
7376 inVal: new([1]chan string),
7377 want: new([1]chan string),
7378 wantErr: EU(nil).withPos(`[`, "/0").withType(0, T[chan string]()),
7379 }, {
7380 name: jsontest.Name("Arrays/Invalid/Underflow"),
7381 inBuf: `{"F":[ ]}`,
7382 inVal: new(struct{ F [1]string }),
7383 want: addr(struct{ F [1]string }{}),
7384 wantErr: EU(errArrayUnderflow).withPos(`{"F":[ `, "/F").withType(']', T[[1]string]()),
7385 }, {
7386 name: jsontest.Name("Arrays/Invalid/Underflow/UnmarshalArrayFromAnyLength"),
7387 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7388 inBuf: `[-1,-2]`,
7389 inVal: addr([4]int{1, 2, 3, 4}),
7390 want: addr([4]int{-1, -2, 0, 0}),
7391 }, {
7392 name: jsontest.Name("Arrays/Invalid/Overflow"),
7393 inBuf: `["1","2"]`,
7394 inVal: new([1]string),
7395 want: addr([1]string{"1"}),
7396 wantErr: EU(errArrayOverflow).withPos(`["1","2"`, "").withType(']', T[[1]string]()),
7397 }, {
7398 name: jsontest.Name("Arrays/Invalid/Overflow/UnmarshalArrayFromAnyLength"),
7399 opts: []Options{jsonflags.UnmarshalArrayFromAnyLength | 1},
7400 inBuf: `[-1,-2,-3,-4,-5,-6]`,
7401 inVal: addr([4]int{1, 2, 3, 4}),
7402 want: addr([4]int{-1, -2, -3, -4}),
7403 }, {
7404 name: jsontest.Name("Arrays/Invalid/Bool"),
7405 inBuf: `true`,
7406 inVal: addr([1]string{"nochange"}),
7407 want: addr([1]string{"nochange"}),
7408 wantErr: EU(nil).withType('t', T[[1]string]()),
7409 }, {
7410 name: jsontest.Name("Arrays/Invalid/String"),
7411 inBuf: `""`,
7412 inVal: addr([1]string{"nochange"}),
7413 want: addr([1]string{"nochange"}),
7414 wantErr: EU(nil).withType('"', T[[1]string]()),
7415 }, {
7416 name: jsontest.Name("Arrays/Invalid/Number"),
7417 inBuf: `0`,
7418 inVal: addr([1]string{"nochange"}),
7419 want: addr([1]string{"nochange"}),
7420 wantErr: EU(nil).withType('0', T[[1]string]()),
7421 }, {
7422 name: jsontest.Name("Arrays/Invalid/Object"),
7423 inBuf: `{}`,
7424 inVal: addr([1]string{"nochange"}),
7425 want: addr([1]string{"nochange"}),
7426 wantErr: EU(nil).withType('{', T[[1]string]()),
7427 }, {
7428 name: jsontest.Name("Arrays/IgnoreInvalidFormat"),
7429 opts: []Options{invalidFormatOption},
7430 inBuf: `[false,true]`,
7431 inVal: addr([2]bool{true, false}),
7432 want: addr([2]bool{false, true}),
7433 }, {
7434 name: jsontest.Name("Pointers/NullL0"),
7435 inBuf: `null`,
7436 inVal: new(*string),
7437 want: addr((*string)(nil)),
7438 }, {
7439 name: jsontest.Name("Pointers/NullL1"),
7440 inBuf: `null`,
7441 inVal: addr(new(*string)),
7442 want: addr((**string)(nil)),
7443 }, {
7444 name: jsontest.Name("Pointers/Bool"),
7445 inBuf: `true`,
7446 inVal: addr(new(bool)),
7447 want: addr(addr(true)),
7448 }, {
7449 name: jsontest.Name("Pointers/String"),
7450 inBuf: `"hello"`,
7451 inVal: addr(new(string)),
7452 want: addr(addr("hello")),
7453 }, {
7454 name: jsontest.Name("Pointers/Bytes"),
7455 inBuf: `"aGVsbG8="`,
7456 inVal: addr(new([]byte)),
7457 want: addr(addr([]byte("hello"))),
7458 }, {
7459 name: jsontest.Name("Pointers/Int"),
7460 inBuf: `-123`,
7461 inVal: addr(new(int)),
7462 want: addr(addr(int(-123))),
7463 }, {
7464 name: jsontest.Name("Pointers/Uint"),
7465 inBuf: `123`,
7466 inVal: addr(new(int)),
7467 want: addr(addr(int(123))),
7468 }, {
7469 name: jsontest.Name("Pointers/Float"),
7470 inBuf: `123.456`,
7471 inVal: addr(new(float64)),
7472 want: addr(addr(float64(123.456))),
7473 }, {
7474 name: jsontest.Name("Pointers/Allocate"),
7475 inBuf: `"hello"`,
7476 inVal: addr((*string)(nil)),
7477 want: addr(addr("hello")),
7478 }, {
7479 name: jsontest.Name("Points/IgnoreInvalidFormat"),
7480 opts: []Options{invalidFormatOption},
7481 inBuf: `true`,
7482 inVal: addr(new(bool)),
7483 want: addr(addr(true)),
7484 }, {
7485 name: jsontest.Name("Interfaces/Empty/Null"),
7486 inBuf: `null`,
7487 inVal: new(any),
7488 want: new(any),
7489 }, {
7490 name: jsontest.Name("Interfaces/NonEmpty/Null"),
7491 inBuf: `null`,
7492 inVal: new(io.Reader),
7493 want: new(io.Reader),
7494 }, {
7495 name: jsontest.Name("Interfaces/NonEmpty/Invalid"),
7496 inBuf: `"hello"`,
7497 inVal: new(io.Reader),
7498 want: new(io.Reader),
7499 wantErr: EU(internal.ErrNilInterface).withType(0, T[io.Reader]()),
7500 }, {
7501 name: jsontest.Name("Interfaces/Empty/False"),
7502 inBuf: `false`,
7503 inVal: new(any),
7504 want: func() any {
7505 var vi any = false
7506 return &vi
7507 }(),
7508 }, {
7509 name: jsontest.Name("Interfaces/Empty/True"),
7510 inBuf: `true`,
7511 inVal: new(any),
7512 want: func() any {
7513 var vi any = true
7514 return &vi
7515 }(),
7516 }, {
7517 name: jsontest.Name("Interfaces/Empty/String"),
7518 inBuf: `"string"`,
7519 inVal: new(any),
7520 want: func() any {
7521 var vi any = "string"
7522 return &vi
7523 }(),
7524 }, {
7525 name: jsontest.Name("Interfaces/Empty/Number"),
7526 inBuf: `3.14159`,
7527 inVal: new(any),
7528 want: func() any {
7529 var vi any = 3.14159
7530 return &vi
7531 }(),
7532 }, {
7533 name: jsontest.Name("Interfaces/Empty/Object"),
7534 inBuf: `{"k":"v"}`,
7535 inVal: new(any),
7536 want: func() any {
7537 var vi any = map[string]any{"k": "v"}
7538 return &vi
7539 }(),
7540 }, {
7541 name: jsontest.Name("Interfaces/Empty/Array"),
7542 inBuf: `["v"]`,
7543 inVal: new(any),
7544 want: func() any {
7545 var vi any = []any{"v"}
7546 return &vi
7547 }(),
7548 }, {
7549 name: jsontest.Name("Interfaces/NamedAny/String"),
7550 inBuf: `"string"`,
7551 inVal: new(namedAny),
7552 want: func() namedAny {
7553 var vi namedAny = "string"
7554 return &vi
7555 }(),
7556 }, {
7557 name: jsontest.Name("Interfaces/Invalid"),
7558 inBuf: `]`,
7559 inVal: new(any),
7560 want: new(any),
7561 wantErr: newInvalidCharacterError("]", "at start of value", 0, ""),
7562 }, {
7563
7564
7565
7566
7567 name: jsontest.Name("Interfaces/Merge/Map"),
7568 inBuf: `{"k2":"v2"}`,
7569 inVal: func() any {
7570 var vi any = map[string]string{"k1": "v1"}
7571 return &vi
7572 }(),
7573 want: func() any {
7574 var vi any = map[string]string{"k1": "v1", "k2": "v2"}
7575 return &vi
7576 }(),
7577 }, {
7578 name: jsontest.Name("Interfaces/Merge/Struct"),
7579 inBuf: `{"Array":["goodbye"]}`,
7580 inVal: func() any {
7581 var vi any = structAll{String: "hello"}
7582 return &vi
7583 }(),
7584 want: func() any {
7585 var vi any = structAll{String: "hello", Array: [1]string{"goodbye"}}
7586 return &vi
7587 }(),
7588 }, {
7589 name: jsontest.Name("Interfaces/Merge/NamedInt"),
7590 inBuf: `64`,
7591 inVal: func() any {
7592 var vi any = namedInt64(-64)
7593 return &vi
7594 }(),
7595 want: func() any {
7596 var vi any = namedInt64(+64)
7597 return &vi
7598 }(),
7599 }, {
7600 name: jsontest.Name("Interfaces/IgnoreInvalidFormat"),
7601 opts: []Options{invalidFormatOption},
7602 inBuf: `true`,
7603 inVal: new(any),
7604 want: func() any {
7605 var vi any = true
7606 return &vi
7607 }(),
7608 }, {
7609 name: jsontest.Name("Interfaces/Any"),
7610 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7611 inVal: new(struct{ X any }),
7612 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7613 }, {
7614 name: jsontest.Name("Interfaces/Any/Named"),
7615 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7616 inVal: new(struct{ X namedAny }),
7617 want: addr(struct{ X namedAny }{[]any{nil, false, true, "", 0.0, map[string]any{}, []any{}}}),
7618 }, {
7619 name: jsontest.Name("Interfaces/Any/Stringified"),
7620 opts: []Options{StringifyNumbers(true)},
7621 inBuf: `{"X":"0"}`,
7622 inVal: new(struct{ X any }),
7623 want: addr(struct{ X any }{"0"}),
7624 }, {
7625 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Any"),
7626 opts: []Options{
7627 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *any) error {
7628 *v = "called"
7629 return nil
7630 })),
7631 },
7632 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7633 inVal: new(struct{ X any }),
7634 want: addr(struct{ X any }{"called"}),
7635 }, {
7636 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Bool"),
7637 opts: []Options{
7638 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *bool) error {
7639 *v = string(b) != "true"
7640 return nil
7641 })),
7642 },
7643 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7644 inVal: new(struct{ X any }),
7645 want: addr(struct{ X any }{[]any{nil, true, false, "", 0.0, map[string]any{}, []any{}}}),
7646 }, {
7647 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/String"),
7648 opts: []Options{
7649 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7650 *v = "called"
7651 return nil
7652 })),
7653 },
7654 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7655 inVal: new(struct{ X any }),
7656 want: addr(struct{ X any }{[]any{nil, false, true, "called", 0.0, map[string]any{}, []any{}}}),
7657 }, {
7658 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/Float64"),
7659 opts: []Options{
7660 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *float64) error {
7661 *v = 3.14159
7662 return nil
7663 })),
7664 },
7665 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7666 inVal: new(struct{ X any }),
7667 want: addr(struct{ X any }{[]any{nil, false, true, "", 3.14159, map[string]any{}, []any{}}}),
7668 }, {
7669 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/MapStringAny"),
7670 opts: []Options{
7671 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *map[string]any) error {
7672 *v = map[string]any{"called": nil}
7673 return nil
7674 })),
7675 },
7676 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7677 inVal: new(struct{ X any }),
7678 want: addr(struct{ X any }{[]any{nil, false, true, "", 0.0, map[string]any{"called": nil}, []any{}}}),
7679 }, {
7680 name: jsontest.Name("Interfaces/Any/UnmarshalFunc/SliceAny"),
7681 opts: []Options{
7682 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *[]any) error {
7683 *v = []any{"called"}
7684 return nil
7685 })),
7686 },
7687 inBuf: `{"X":[null,false,true,"",0,{},[]]}`,
7688 inVal: new(struct{ X any }),
7689 want: addr(struct{ X any }{[]any{"called"}}),
7690 }, {
7691 name: jsontest.Name("Interfaces/Any/Maps/NonEmpty"),
7692 inBuf: `{"X":{"fizz":"buzz"}}`,
7693 inVal: new(struct{ X any }),
7694 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7695 }, {
7696 name: jsontest.Name("Interfaces/Any/Maps/RejectDuplicateNames"),
7697 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7698 inVal: new(struct{ X any }),
7699 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7700 wantErr: newDuplicateNameError("/X", []byte(`"fizz"`), len64(`{"X":{"fizz":"buzz",`)),
7701 }, {
7702 name: jsontest.Name("Interfaces/Any/Maps/AllowDuplicateNames"),
7703 opts: []Options{jsontext.AllowDuplicateNames(true)},
7704 inBuf: `{"X":{"fizz":"buzz","fizz":true}}`,
7705 inVal: new(struct{ X any }),
7706 want: addr(struct{ X any }{map[string]any{"fizz": "buzz"}}),
7707 wantErr: EU(nil).withPos(`{"X":{"fizz":"buzz","fizz":`, "/X/fizz").withType('t', T[string]()),
7708 }, {
7709 name: jsontest.Name("Interfaces/Any/Slices/NonEmpty"),
7710 inBuf: `{"X":["fizz","buzz"]}`,
7711 inVal: new(struct{ X any }),
7712 want: addr(struct{ X any }{[]any{"fizz", "buzz"}}),
7713 }, {
7714 name: jsontest.Name("Methods/NilPointer/Null"),
7715 inBuf: `{"X":null}`,
7716 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7717 want: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7718 }, {
7719 name: jsontest.Name("Methods/NilPointer/Value"),
7720 inBuf: `{"X":"value"}`,
7721 inVal: addr(struct{ X *allMethods }{X: (*allMethods)(nil)}),
7722 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7723 }, {
7724 name: jsontest.Name("Methods/NilInterface/Null"),
7725 inBuf: `{"X":null}`,
7726 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7727 want: addr(struct{ X MarshalerTo }{X: nil}),
7728 }, {
7729 name: jsontest.Name("Methods/NilInterface/Value"),
7730 inBuf: `{"X":"value"}`,
7731 inVal: addr(struct{ X MarshalerTo }{X: (*allMethods)(nil)}),
7732 want: addr(struct{ X MarshalerTo }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"value"`)}}),
7733 }, {
7734 name: jsontest.Name("Methods/AllMethods"),
7735 inBuf: `{"X":"hello"}`,
7736 inVal: new(struct{ X *allMethods }),
7737 want: addr(struct{ X *allMethods }{X: &allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}),
7738 }, {
7739 name: jsontest.Name("Methods/AllMethodsExceptJSONv2"),
7740 inBuf: `{"X":"hello"}`,
7741 inVal: new(struct{ X *allMethodsExceptJSONv2 }),
7742 want: addr(struct{ X *allMethodsExceptJSONv2 }{X: &allMethodsExceptJSONv2{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7743 }, {
7744 name: jsontest.Name("Methods/AllMethodsExceptJSONv1"),
7745 inBuf: `{"X":"hello"}`,
7746 inVal: new(struct{ X *allMethodsExceptJSONv1 }),
7747 want: addr(struct{ X *allMethodsExceptJSONv1 }{X: &allMethodsExceptJSONv1{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7748 }, {
7749 name: jsontest.Name("Methods/AllMethodsExceptText"),
7750 inBuf: `{"X":"hello"}`,
7751 inVal: new(struct{ X *allMethodsExceptText }),
7752 want: addr(struct{ X *allMethodsExceptText }{X: &allMethodsExceptText{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7753 }, {
7754 name: jsontest.Name("Methods/OnlyMethodJSONv2"),
7755 inBuf: `{"X":"hello"}`,
7756 inVal: new(struct{ X *onlyMethodJSONv2 }),
7757 want: addr(struct{ X *onlyMethodJSONv2 }{X: &onlyMethodJSONv2{allMethods: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7758 }, {
7759 name: jsontest.Name("Methods/OnlyMethodJSONv1"),
7760 inBuf: `{"X":"hello"}`,
7761 inVal: new(struct{ X *onlyMethodJSONv1 }),
7762 want: addr(struct{ X *onlyMethodJSONv1 }{X: &onlyMethodJSONv1{allMethods: allMethods{method: "UnmarshalJSON", value: []byte(`"hello"`)}}}),
7763 }, {
7764 name: jsontest.Name("Methods/OnlyMethodText"),
7765 inBuf: `{"X":"hello"}`,
7766 inVal: new(struct{ X *onlyMethodText }),
7767 want: addr(struct{ X *onlyMethodText }{X: &onlyMethodText{allMethods: allMethods{method: "UnmarshalText", value: []byte(`hello`)}}}),
7768 }, {
7769 name: jsontest.Name("Methods/Text/Null"),
7770 inBuf: `{"X":null}`,
7771 inVal: addr(struct{ X unmarshalTextFunc }{unmarshalTextFunc(func(b []byte) error {
7772 return errMustNotCall
7773 })}),
7774 want: addr(struct{ X unmarshalTextFunc }{nil}),
7775 }, {
7776 name: jsontest.Name("Methods/IP"),
7777 inBuf: `"192.168.0.100"`,
7778 inVal: new(net.IP),
7779 want: addr(net.IPv4(192, 168, 0, 100)),
7780 }, {
7781
7782 name: jsontest.Name("Methods/Anonymous"),
7783 inBuf: `{"X":"hello"}`,
7784 inVal: new(struct{ X struct{ allMethods } }),
7785 want: addr(struct{ X struct{ allMethods } }{X: struct{ allMethods }{allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}}}),
7786 }, {
7787
7788 name: jsontest.Name("Methods/Addressable"),
7789 inBuf: `{"V":"hello","M":{"K":"hello"},"I":"hello"}`,
7790 inVal: addr(struct {
7791 V allMethods
7792 M map[string]allMethods
7793 I any
7794 }{
7795 I: allMethods{},
7796 }),
7797 want: addr(struct {
7798 V allMethods
7799 M map[string]allMethods
7800 I any
7801 }{
7802 V: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7803 M: map[string]allMethods{"K": {method: "UnmarshalJSONFrom", value: []byte(`"hello"`)}},
7804 I: allMethods{method: "UnmarshalJSONFrom", value: []byte(`"hello"`)},
7805 }),
7806 }, {
7807
7808 name: jsontest.Name("Methods/MapKey/JSONv2"),
7809 inBuf: `{"k1":"v1b","k2":"v2"}`,
7810 inVal: addr(map[structMethodJSONv2]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7811 want: addr(map[structMethodJSONv2]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7812 }, {
7813
7814 name: jsontest.Name("Methods/MapKey/JSONv1"),
7815 inBuf: `{"k1":"v1b","k2":"v2"}`,
7816 inVal: addr(map[structMethodJSONv1]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7817 want: addr(map[structMethodJSONv1]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7818 }, {
7819 name: jsontest.Name("Methods/MapKey/Text"),
7820 inBuf: `{"k1":"v1b","k2":"v2"}`,
7821 inVal: addr(map[structMethodText]string{{"k1"}: "v1a", {"k3"}: "v3"}),
7822 want: addr(map[structMethodText]string{{"k1"}: "v1b", {"k2"}: "v2", {"k3"}: "v3"}),
7823 }, {
7824 name: jsontest.Name("Methods/Invalid/JSONv2/Error"),
7825 inBuf: `{}`,
7826 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7827 return errSomeError
7828 })),
7829 wantErr: EU(errSomeError).withType(0, T[unmarshalJSONv2Func]()),
7830 }, {
7831 name: jsontest.Name("Methods/Invalid/JSONv2/TooFew"),
7832 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7833 return nil
7834 })),
7835 wantErr: EU(errNonSingularValue).withType(0, T[unmarshalJSONv2Func]()),
7836 }, {
7837 name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"),
7838 inBuf: `{}{}`,
7839 inVal: addr(unmarshalJSONv2Func(func(dec *jsontext.Decoder) error {
7840 dec.ReadValue()
7841 dec.ReadValue()
7842 return nil
7843 })),
7844 wantErr: EU(errNonSingularValue).withPos(`{}`, "").withType(0, T[unmarshalJSONv2Func]()),
7845 }, {
7846 name: jsontest.Name("Methods/Invalid/JSONv2/SkipFunc"),
7847 inBuf: `{}`,
7848 inVal: addr(unmarshalJSONv2Func(func(*jsontext.Decoder) error {
7849 return SkipFunc
7850 })),
7851 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType(0, T[unmarshalJSONv2Func]()),
7852 }, {
7853 name: jsontest.Name("Methods/Invalid/JSONv1/Error"),
7854 inBuf: `{}`,
7855 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7856 return errSomeError
7857 })),
7858 wantErr: EU(errSomeError).withType('{', T[unmarshalJSONv1Func]()),
7859 }, {
7860 name: jsontest.Name("Methods/Invalid/JSONv1/SkipFunc"),
7861 inBuf: `{}`,
7862 inVal: addr(unmarshalJSONv1Func(func([]byte) error {
7863 return SkipFunc
7864 })),
7865 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType('{', T[unmarshalJSONv1Func]()),
7866 }, {
7867 name: jsontest.Name("Methods/Invalid/Text/Error"),
7868 inBuf: `"value"`,
7869 inVal: addr(unmarshalTextFunc(func([]byte) error {
7870 return errSomeError
7871 })),
7872 wantErr: EU(errSomeError).withType('"', T[unmarshalTextFunc]()),
7873 }, {
7874 name: jsontest.Name("Methods/Invalid/Text/Syntax"),
7875 inBuf: `{}`,
7876 inVal: addr(unmarshalTextFunc(func([]byte) error {
7877 panic("should not be called")
7878 })),
7879 wantErr: EU(errNonStringValue).withType('{', T[unmarshalTextFunc]()),
7880 }, {
7881 name: jsontest.Name("Methods/Invalid/Text/SkipFunc"),
7882 inBuf: `"value"`,
7883 inVal: addr(unmarshalTextFunc(func([]byte) error {
7884 return SkipFunc
7885 })),
7886 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal method")).withType('"', T[unmarshalTextFunc]()),
7887 }, {
7888 name: jsontest.Name("Functions/String/V1"),
7889 opts: []Options{
7890 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
7891 if string(b) != `""` {
7892 return fmt.Errorf("got %s, want %s", b, `""`)
7893 }
7894 *v = "called"
7895 return nil
7896 })),
7897 },
7898 inBuf: `""`,
7899 inVal: addr(""),
7900 want: addr("called"),
7901 }, {
7902 name: jsontest.Name("Functions/String/Empty"),
7903 opts: []Options{WithUnmarshalers(nil)},
7904 inBuf: `"hello"`,
7905 inVal: addr(""),
7906 want: addr("hello"),
7907 }, {
7908 name: jsontest.Name("Functions/NamedString/V1/NoMatch"),
7909 opts: []Options{
7910 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7911 panic("should not be called")
7912 })),
7913 },
7914 inBuf: `""`,
7915 inVal: addr(""),
7916 want: addr(""),
7917 }, {
7918 name: jsontest.Name("Functions/NamedString/V1/Match"),
7919 opts: []Options{
7920 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *namedString) error {
7921 if string(b) != `""` {
7922 return fmt.Errorf("got %s, want %s", b, `""`)
7923 }
7924 *v = "called"
7925 return nil
7926 })),
7927 },
7928 inBuf: `""`,
7929 inVal: addr(namedString("")),
7930 want: addr(namedString("called")),
7931 }, {
7932 name: jsontest.Name("Functions/String/V2"),
7933 opts: []Options{
7934 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
7935 switch b, err := dec.ReadValue(); {
7936 case err != nil:
7937 return err
7938 case string(b) != `""`:
7939 return fmt.Errorf("got %s, want %s", b, `""`)
7940 }
7941 *v = "called"
7942 return nil
7943 })),
7944 },
7945 inBuf: `""`,
7946 inVal: addr(""),
7947 want: addr("called"),
7948 }, {
7949 name: jsontest.Name("Functions/NamedString/V2/NoMatch"),
7950 opts: []Options{
7951 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7952 panic("should not be called")
7953 })),
7954 },
7955 inBuf: `""`,
7956 inVal: addr(""),
7957 want: addr(""),
7958 }, {
7959 name: jsontest.Name("Functions/NamedString/V2/Match"),
7960 opts: []Options{
7961 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedString) error {
7962 switch t, err := dec.ReadToken(); {
7963 case err != nil:
7964 return err
7965 case t.String() != ``:
7966 return fmt.Errorf("got %q, want %q", t, ``)
7967 }
7968 *v = "called"
7969 return nil
7970 })),
7971 },
7972 inBuf: `""`,
7973 inVal: addr(namedString("")),
7974 want: addr(namedString("called")),
7975 }, {
7976 name: jsontest.Name("Functions/String/Empty1/NoMatch"),
7977 opts: []Options{
7978 WithUnmarshalers(new(Unmarshalers)),
7979 },
7980 inBuf: `""`,
7981 inVal: addr(""),
7982 want: addr(""),
7983 }, {
7984 name: jsontest.Name("Functions/String/Empty2/NoMatch"),
7985 opts: []Options{
7986 WithUnmarshalers(JoinUnmarshalers()),
7987 },
7988 inBuf: `""`,
7989 inVal: addr(""),
7990 want: addr(""),
7991 }, {
7992 name: jsontest.Name("Functions/String/V1/DirectError"),
7993 opts: []Options{
7994 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
7995 return errSomeError
7996 })),
7997 },
7998 inBuf: `""`,
7999 inVal: addr(""),
8000 want: addr(""),
8001 wantErr: EU(errSomeError).withType('"', reflect.PointerTo(stringType)),
8002 }, {
8003 name: jsontest.Name("Functions/String/V1/SkipError"),
8004 opts: []Options{
8005 WithUnmarshalers(UnmarshalFunc(func([]byte, *string) error {
8006 return SkipFunc
8007 })),
8008 },
8009 inBuf: `""`,
8010 inVal: addr(""),
8011 want: addr(""),
8012 wantErr: EU(wrapSkipFunc(SkipFunc, "unmarshal function of type func([]byte, T) error")).withType('"', reflect.PointerTo(stringType)),
8013 }, {
8014 name: jsontest.Name("Functions/String/V2/DirectError"),
8015 opts: []Options{
8016 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8017 return errSomeError
8018 })),
8019 },
8020 inBuf: `""`,
8021 inVal: addr(""),
8022 want: addr(""),
8023 wantErr: EU(errSomeError).withType(0, reflect.PointerTo(stringType)),
8024 }, {
8025 name: jsontest.Name("Functions/String/V2/TooFew"),
8026 opts: []Options{
8027 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8028 return nil
8029 })),
8030 },
8031 inBuf: `""`,
8032 inVal: addr(""),
8033 want: addr(""),
8034 wantErr: EU(errNonSingularValue).withType(0, reflect.PointerTo(stringType)),
8035 }, {
8036 name: jsontest.Name("Functions/String/V2/TooMany"),
8037 opts: []Options{
8038 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8039 if _, err := dec.ReadValue(); err != nil {
8040 return err
8041 }
8042 if _, err := dec.ReadValue(); err != nil {
8043 return err
8044 }
8045 return nil
8046 })),
8047 },
8048 inBuf: `{"X":["",""]}`,
8049 inVal: addr(struct{ X []string }{}),
8050 want: addr(struct{ X []string }{[]string{""}}),
8051 wantErr: EU(errNonSingularValue).withPos(`{"X":["",`, "/X").withType(0, reflect.PointerTo(stringType)),
8052 }, {
8053 name: jsontest.Name("Functions/String/V2/Skipped"),
8054 opts: []Options{
8055 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8056 return SkipFunc
8057 })),
8058 },
8059 inBuf: `""`,
8060 inVal: addr(""),
8061 want: addr(""),
8062 }, {
8063 name: jsontest.Name("Functions/String/V2/ProcessBeforeSkip"),
8064 opts: []Options{
8065 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8066 if _, err := dec.ReadValue(); err != nil {
8067 return err
8068 }
8069 return SkipFunc
8070 })),
8071 },
8072 inBuf: `""`,
8073 inVal: addr(""),
8074 want: addr(""),
8075 wantErr: EU(errSkipMutation).withType(0, reflect.PointerTo(stringType)),
8076 }, {
8077 name: jsontest.Name("Functions/String/V2/WrappedSkipError"),
8078 opts: []Options{
8079 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8080 return fmt.Errorf("wrap: %w", SkipFunc)
8081 })),
8082 },
8083 inBuf: `""`,
8084 inVal: addr(""),
8085 want: addr(""),
8086 wantErr: EU(fmt.Errorf("wrap: %w", SkipFunc)).withType(0, reflect.PointerTo(stringType)),
8087 }, {
8088 name: jsontest.Name("Functions/Map/Key/NoCaseString/V1"),
8089 opts: []Options{
8090 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8091 if string(b) != `"hello"` {
8092 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8093 }
8094 *v = "called"
8095 return nil
8096 })),
8097 },
8098 inBuf: `{"hello":"world"}`,
8099 inVal: addr(map[nocaseString]string{}),
8100 want: addr(map[nocaseString]string{"called": "world"}),
8101 }, {
8102 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V1"),
8103 opts: []Options{
8104 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8105 if string(b) != `"hello"` {
8106 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8107 }
8108 *v.(*nocaseString) = "called"
8109 return nil
8110 })),
8111 },
8112 inBuf: `{"hello":"world"}`,
8113 inVal: addr(map[nocaseString]string{}),
8114 want: addr(map[nocaseString]string{"called": "world"}),
8115 }, {
8116 name: jsontest.Name("Functions/Map/Key/NoCaseString/V2"),
8117 opts: []Options{
8118 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8119 switch t, err := dec.ReadToken(); {
8120 case err != nil:
8121 return err
8122 case t.String() != "hello":
8123 return fmt.Errorf("got %q, want %q", t, "hello")
8124 }
8125 *v = "called"
8126 return nil
8127 })),
8128 },
8129 inBuf: `{"hello":"world"}`,
8130 inVal: addr(map[nocaseString]string{}),
8131 want: addr(map[nocaseString]string{"called": "world"}),
8132 }, {
8133 name: jsontest.Name("Functions/Map/Key/TextMarshaler/V2"),
8134 opts: []Options{
8135 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8136 switch b, err := dec.ReadValue(); {
8137 case err != nil:
8138 return err
8139 case string(b) != `"hello"`:
8140 return fmt.Errorf("got %s, want %s", b, `"hello"`)
8141 }
8142 *v.(*nocaseString) = "called"
8143 return nil
8144 })),
8145 },
8146 inBuf: `{"hello":"world"}`,
8147 inVal: addr(map[nocaseString]string{}),
8148 want: addr(map[nocaseString]string{"called": "world"}),
8149 }, {
8150 name: jsontest.Name("Functions/Map/Key/String/V1/DuplicateName"),
8151 opts: []Options{
8152 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8153 if _, err := dec.ReadValue(); err != nil {
8154 return err
8155 }
8156 xd := export.Decoder(dec)
8157 *v = fmt.Sprintf("%d-%d", len(xd.Tokens.Stack), xd.Tokens.Last.Length())
8158 return nil
8159 })),
8160 },
8161 inBuf: `{"name":"value","name":"value"}`,
8162 inVal: addr(map[string]string{}),
8163 want: addr(map[string]string{"1-1": "1-2"}),
8164 wantErr: newDuplicateNameError("", []byte(`"name"`), len64(`{"name":"value",`)),
8165 }, {
8166 name: jsontest.Name("Functions/Map/Value/NoCaseString/V1"),
8167 opts: []Options{
8168 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *nocaseString) error {
8169 if string(b) != `"world"` {
8170 return fmt.Errorf("got %s, want %s", b, `"world"`)
8171 }
8172 *v = "called"
8173 return nil
8174 })),
8175 },
8176 inBuf: `{"hello":"world"}`,
8177 inVal: addr(map[string]nocaseString{}),
8178 want: addr(map[string]nocaseString{"hello": "called"}),
8179 }, {
8180 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V1"),
8181 opts: []Options{
8182 WithUnmarshalers(UnmarshalFunc(func(b []byte, v encoding.TextMarshaler) error {
8183 if string(b) != `"world"` {
8184 return fmt.Errorf("got %s, want %s", b, `"world"`)
8185 }
8186 *v.(*nocaseString) = "called"
8187 return nil
8188 })),
8189 },
8190 inBuf: `{"hello":"world"}`,
8191 inVal: addr(map[string]nocaseString{}),
8192 want: addr(map[string]nocaseString{"hello": "called"}),
8193 }, {
8194 name: jsontest.Name("Functions/Map/Value/NoCaseString/V2"),
8195 opts: []Options{
8196 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *nocaseString) error {
8197 switch t, err := dec.ReadToken(); {
8198 case err != nil:
8199 return err
8200 case t.String() != "world":
8201 return fmt.Errorf("got %q, want %q", t, "world")
8202 }
8203 *v = "called"
8204 return nil
8205 })),
8206 },
8207 inBuf: `{"hello":"world"}`,
8208 inVal: addr(map[string]nocaseString{}),
8209 want: addr(map[string]nocaseString{"hello": "called"}),
8210 }, {
8211 name: jsontest.Name("Functions/Map/Value/TextMarshaler/V2"),
8212 opts: []Options{
8213 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v encoding.TextMarshaler) error {
8214 switch b, err := dec.ReadValue(); {
8215 case err != nil:
8216 return err
8217 case string(b) != `"world"`:
8218 return fmt.Errorf("got %s, want %s", b, `"world"`)
8219 }
8220 *v.(*nocaseString) = "called"
8221 return nil
8222 })),
8223 },
8224 inBuf: `{"hello":"world"}`,
8225 inVal: addr(map[string]nocaseString{}),
8226 want: addr(map[string]nocaseString{"hello": "called"}),
8227 }, {
8228 name: jsontest.Name("Funtions/Struct/Fields"),
8229 opts: []Options{
8230 WithUnmarshalers(JoinUnmarshalers(
8231 UnmarshalFunc(func(b []byte, v *bool) error {
8232 if string(b) != `"called1"` {
8233 return fmt.Errorf("got %s, want %s", b, `"called1"`)
8234 }
8235 *v = true
8236 return nil
8237 }),
8238 UnmarshalFunc(func(b []byte, v *string) error {
8239 if string(b) != `"called2"` {
8240 return fmt.Errorf("got %s, want %s", b, `"called2"`)
8241 }
8242 *v = "called2"
8243 return nil
8244 }),
8245 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[]byte) error {
8246 switch t, err := dec.ReadToken(); {
8247 case err != nil:
8248 return err
8249 case t.String() != "called3":
8250 return fmt.Errorf("got %q, want %q", t, "called3")
8251 }
8252 *v = []byte("called3")
8253 return nil
8254 }),
8255 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *int64) error {
8256 switch b, err := dec.ReadValue(); {
8257 case err != nil:
8258 return err
8259 case string(b) != `"called4"`:
8260 return fmt.Errorf("got %s, want %s", b, `"called4"`)
8261 }
8262 *v = 123
8263 return nil
8264 }),
8265 )),
8266 },
8267 inBuf: `{"Bool":"called1","String":"called2","Bytes":"called3","Int":"called4","Uint":456,"Float":789}`,
8268 inVal: addr(structScalars{}),
8269 want: addr(structScalars{Bool: true, String: "called2", Bytes: []byte("called3"), Int: 123, Uint: 456, Float: 789}),
8270 }, {
8271 name: jsontest.Name("Functions/Struct/Inlined"),
8272 opts: []Options{
8273 WithUnmarshalers(JoinUnmarshalers(
8274 UnmarshalFunc(func([]byte, *structInlinedL1) error {
8275 panic("should not be called")
8276 }),
8277 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *StructEmbed2) error {
8278 panic("should not be called")
8279 }),
8280 )),
8281 },
8282 inBuf: `{"E":"E3","F":"F3","G":"G3","A":"A1","B":"B1","D":"D2"}`,
8283 inVal: new(structInlined),
8284 want: addr(structInlined{
8285 X: structInlinedL1{
8286 X: &structInlinedL2{A: "A1", B: "B1" },
8287 StructEmbed1: StructEmbed1{ D: "D2" },
8288 },
8289 StructEmbed2: &StructEmbed2{E: "E3", F: "F3", G: "G3"},
8290 }),
8291 }, {
8292 name: jsontest.Name("Functions/Slice/Elem"),
8293 opts: []Options{
8294 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8295 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8296 return nil
8297 })),
8298 },
8299 inBuf: `["hello","World"]`,
8300 inVal: addr([]string{}),
8301 want: addr([]string{"HELLO", "WORLD"}),
8302 }, {
8303 name: jsontest.Name("Functions/Array/Elem"),
8304 opts: []Options{
8305 WithUnmarshalers(UnmarshalFunc(func(b []byte, v *string) error {
8306 *v = strings.Trim(strings.ToUpper(string(b)), `"`)
8307 return nil
8308 })),
8309 },
8310 inBuf: `["hello","World"]`,
8311 inVal: addr([2]string{}),
8312 want: addr([2]string{"HELLO", "WORLD"}),
8313 }, {
8314 name: jsontest.Name("Functions/Pointer/Nil"),
8315 opts: []Options{
8316 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8317 t, err := dec.ReadToken()
8318 *v = strings.ToUpper(t.String())
8319 return err
8320 })),
8321 },
8322 inBuf: `{"X":"hello"}`,
8323 inVal: addr(struct{ X *string }{nil}),
8324 want: addr(struct{ X *string }{addr("HELLO")}),
8325 }, {
8326 name: jsontest.Name("Functions/Pointer/NonNil"),
8327 opts: []Options{
8328 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8329 t, err := dec.ReadToken()
8330 *v = strings.ToUpper(t.String())
8331 return err
8332 })),
8333 },
8334 inBuf: `{"X":"hello"}`,
8335 inVal: addr(struct{ X *string }{addr("")}),
8336 want: addr(struct{ X *string }{addr("HELLO")}),
8337 }, {
8338 name: jsontest.Name("Functions/Interface/Nil"),
8339 opts: []Options{
8340 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v fmt.Stringer) error {
8341 panic("should not be called")
8342 })),
8343 },
8344 inBuf: `{"X":"hello"}`,
8345 inVal: addr(struct{ X fmt.Stringer }{nil}),
8346 want: addr(struct{ X fmt.Stringer }{nil}),
8347 wantErr: EU(internal.ErrNilInterface).withPos(`{"X":`, "/X").withType(0, T[fmt.Stringer]()),
8348 }, {
8349 name: jsontest.Name("Functions/Interface/NetIP"),
8350 opts: []Options{
8351 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8352 *v = net.IP{}
8353 return SkipFunc
8354 })),
8355 },
8356 inBuf: `{"X":"1.1.1.1"}`,
8357 inVal: addr(struct{ X fmt.Stringer }{nil}),
8358 want: addr(struct{ X fmt.Stringer }{net.IPv4(1, 1, 1, 1)}),
8359 }, {
8360 name: jsontest.Name("Functions/Interface/NewPointerNetIP"),
8361 opts: []Options{
8362 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8363 *v = new(net.IP)
8364 return SkipFunc
8365 })),
8366 },
8367 inBuf: `{"X":"1.1.1.1"}`,
8368 inVal: addr(struct{ X fmt.Stringer }{nil}),
8369 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}),
8370 }, {
8371 name: jsontest.Name("Functions/Interface/NilPointerNetIP"),
8372 opts: []Options{
8373 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8374 *v = (*net.IP)(nil)
8375 return SkipFunc
8376 })),
8377 },
8378 inBuf: `{"X":"1.1.1.1"}`,
8379 inVal: addr(struct{ X fmt.Stringer }{nil}),
8380 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(1, 1, 1, 1))}),
8381 }, {
8382 name: jsontest.Name("Functions/Interface/NilPointerNetIP/Override"),
8383 opts: []Options{
8384 WithUnmarshalers(JoinUnmarshalers(
8385 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *fmt.Stringer) error {
8386 *v = (*net.IP)(nil)
8387 return SkipFunc
8388 }),
8389 UnmarshalFunc(func(b []byte, v *net.IP) error {
8390 b = bytes.ReplaceAll(b, []byte(`1`), []byte(`8`))
8391 return v.UnmarshalText(bytes.Trim(b, `"`))
8392 }),
8393 )),
8394 },
8395 inBuf: `{"X":"1.1.1.1"}`,
8396 inVal: addr(struct{ X fmt.Stringer }{nil}),
8397 want: addr(struct{ X fmt.Stringer }{addr(net.IPv4(8, 8, 8, 8))}),
8398 }, {
8399 name: jsontest.Name("Functions/Interface/Any"),
8400 inBuf: `[null,{},{},{},{},{},{},{},{},{},{},{},{},"LAST"]`,
8401 inVal: addr([...]any{
8402 nil,
8403 valueStringer{},
8404 (*valueStringer)(nil),
8405 addr(valueStringer{}),
8406 (**valueStringer)(nil),
8407 addr((*valueStringer)(nil)),
8408 addr(addr(valueStringer{})),
8409 pointerStringer{},
8410 (*pointerStringer)(nil),
8411 addr(pointerStringer{}),
8412 (**pointerStringer)(nil),
8413 addr((*pointerStringer)(nil)),
8414 addr(addr(pointerStringer{})),
8415 "LAST",
8416 }),
8417 opts: []Options{
8418 WithUnmarshalers(func() *Unmarshalers {
8419 type P struct {
8420 D int
8421 N int64
8422 }
8423 type PV struct {
8424 P P
8425 V any
8426 }
8427
8428 var lastChecks []func() error
8429 checkLast := func() error {
8430 for _, fn := range lastChecks {
8431 if err := fn(); err != nil {
8432 return err
8433 }
8434 }
8435 return SkipFunc
8436 }
8437 makeValueChecker := func(name string, want []PV) func(d *jsontext.Decoder, v any) error {
8438 checkNext := func(d *jsontext.Decoder, v any) error {
8439 xd := export.Decoder(d)
8440 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8441 rv := reflect.ValueOf(v)
8442 pv := PV{p, v}
8443 switch {
8444 case len(want) == 0:
8445 return fmt.Errorf("%s: %v: got more values than expected", name, p)
8446 case !rv.IsValid() || rv.Kind() != reflect.Pointer || rv.IsNil():
8447 return fmt.Errorf("%s: %v: got %#v, want non-nil pointer type", name, p, v)
8448 case !reflect.DeepEqual(pv, want[0]):
8449 return fmt.Errorf("%s:\n\tgot %#v\n\twant %#v", name, pv, want[0])
8450 default:
8451 want = want[1:]
8452 return SkipFunc
8453 }
8454 }
8455 lastChecks = append(lastChecks, func() error {
8456 if len(want) > 0 {
8457 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8458 }
8459 return nil
8460 })
8461 return checkNext
8462 }
8463 makePositionChecker := func(name string, want []P) func(d *jsontext.Decoder, v any) error {
8464 checkNext := func(d *jsontext.Decoder, v any) error {
8465 xd := export.Decoder(d)
8466 p := P{len(xd.Tokens.Stack), xd.Tokens.Last.Length()}
8467 switch {
8468 case len(want) == 0:
8469 return fmt.Errorf("%s: %v: got more values than wanted", name, p)
8470 case p != want[0]:
8471 return fmt.Errorf("%s: got %v, want %v", name, p, want[0])
8472 default:
8473 want = want[1:]
8474 return SkipFunc
8475 }
8476 }
8477 lastChecks = append(lastChecks, func() error {
8478 if len(want) > 0 {
8479 return fmt.Errorf("%s: did not get enough values, want %d more", name, len(want))
8480 }
8481 return nil
8482 })
8483 return checkNext
8484 }
8485
8486
8487
8488 wantAny := []PV{
8489 {P{1, 0}, addr(any(nil))},
8490 {P{1, 1}, addr(any(valueStringer{}))},
8491 {P{1, 1}, addr(valueStringer{})},
8492 {P{1, 2}, addr(any((*valueStringer)(nil)))},
8493 {P{1, 2}, addr((*valueStringer)(nil))},
8494 {P{1, 2}, addr(valueStringer{})},
8495 {P{1, 3}, addr(any(addr(valueStringer{})))},
8496 {P{1, 3}, addr(addr(valueStringer{}))},
8497 {P{1, 3}, addr(valueStringer{})},
8498 {P{1, 4}, addr(any((**valueStringer)(nil)))},
8499 {P{1, 4}, addr((**valueStringer)(nil))},
8500 {P{1, 4}, addr((*valueStringer)(nil))},
8501 {P{1, 4}, addr(valueStringer{})},
8502 {P{1, 5}, addr(any(addr((*valueStringer)(nil))))},
8503 {P{1, 5}, addr(addr((*valueStringer)(nil)))},
8504 {P{1, 5}, addr((*valueStringer)(nil))},
8505 {P{1, 5}, addr(valueStringer{})},
8506 {P{1, 6}, addr(any(addr(addr(valueStringer{}))))},
8507 {P{1, 6}, addr(addr(addr(valueStringer{})))},
8508 {P{1, 6}, addr(addr(valueStringer{}))},
8509 {P{1, 6}, addr(valueStringer{})},
8510 {P{1, 7}, addr(any(pointerStringer{}))},
8511 {P{1, 7}, addr(pointerStringer{})},
8512 {P{1, 8}, addr(any((*pointerStringer)(nil)))},
8513 {P{1, 8}, addr((*pointerStringer)(nil))},
8514 {P{1, 8}, addr(pointerStringer{})},
8515 {P{1, 9}, addr(any(addr(pointerStringer{})))},
8516 {P{1, 9}, addr(addr(pointerStringer{}))},
8517 {P{1, 9}, addr(pointerStringer{})},
8518 {P{1, 10}, addr(any((**pointerStringer)(nil)))},
8519 {P{1, 10}, addr((**pointerStringer)(nil))},
8520 {P{1, 10}, addr((*pointerStringer)(nil))},
8521 {P{1, 10}, addr(pointerStringer{})},
8522 {P{1, 11}, addr(any(addr((*pointerStringer)(nil))))},
8523 {P{1, 11}, addr(addr((*pointerStringer)(nil)))},
8524 {P{1, 11}, addr((*pointerStringer)(nil))},
8525 {P{1, 11}, addr(pointerStringer{})},
8526 {P{1, 12}, addr(any(addr(addr(pointerStringer{}))))},
8527 {P{1, 12}, addr(addr(addr(pointerStringer{})))},
8528 {P{1, 12}, addr(addr(pointerStringer{}))},
8529 {P{1, 12}, addr(pointerStringer{})},
8530 {P{1, 13}, addr(any("LAST"))},
8531 {P{1, 13}, addr("LAST")},
8532 }
8533 checkAny := makeValueChecker("any", wantAny)
8534 anyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v any) error {
8535 return checkAny(dec, v)
8536 })
8537
8538 var wantPointerAny []PV
8539 for _, v := range wantAny {
8540 if _, ok := v.V.(*any); ok {
8541 wantPointerAny = append(wantPointerAny, v)
8542 }
8543 }
8544 checkPointerAny := makeValueChecker("*any", wantPointerAny)
8545 pointerAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *any) error {
8546 return checkPointerAny(dec, v)
8547 })
8548
8549 checkNamedAny := makeValueChecker("namedAny", wantAny)
8550 namedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v namedAny) error {
8551 return checkNamedAny(dec, v)
8552 })
8553
8554 checkPointerNamedAny := makeValueChecker("*namedAny", nil)
8555 pointerNamedAnyUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *namedAny) error {
8556 return checkPointerNamedAny(dec, v)
8557 })
8558
8559 type stringer = fmt.Stringer
8560 var wantStringer []PV
8561 for _, v := range wantAny {
8562 if _, ok := v.V.(stringer); ok {
8563 wantStringer = append(wantStringer, v)
8564 }
8565 }
8566 checkStringer := makeValueChecker("stringer", wantStringer)
8567 stringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v stringer) error {
8568 return checkStringer(dec, v)
8569 })
8570
8571 checkPointerStringer := makeValueChecker("*stringer", nil)
8572 pointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *stringer) error {
8573 return checkPointerStringer(dec, v)
8574 })
8575
8576 wantValueStringer := []P{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}}
8577 checkPointerValueStringer := makePositionChecker("*valueStringer", wantValueStringer)
8578 pointerValueStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *valueStringer) error {
8579 return checkPointerValueStringer(dec, v)
8580 })
8581
8582 wantPointerStringer := []P{{1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}}
8583 checkPointerPointerStringer := makePositionChecker("*pointerStringer", wantPointerStringer)
8584 pointerPointerStringerUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *pointerStringer) error {
8585 return checkPointerPointerStringer(dec, v)
8586 })
8587
8588 lastUnmarshaler := UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8589 return checkLast()
8590 })
8591
8592 return JoinUnmarshalers(
8593
8594
8595 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *[14]any) error {
8596 if _, err := dec.ReadToken(); err != nil {
8597 return err
8598 }
8599 for i := range len(*v) {
8600 if err := UnmarshalDecode(dec, &(*v)[i]); err != nil {
8601 return err
8602 }
8603 }
8604 if _, err := dec.ReadToken(); err != nil {
8605 return err
8606 }
8607 return nil
8608 }),
8609
8610 anyUnmarshaler,
8611 pointerAnyUnmarshaler,
8612 namedAnyUnmarshaler,
8613 pointerNamedAnyUnmarshaler,
8614 stringerUnmarshaler,
8615 pointerStringerUnmarshaler,
8616 pointerValueStringerUnmarshaler,
8617 pointerPointerStringerUnmarshaler,
8618 lastUnmarshaler,
8619 )
8620 }()),
8621 },
8622 }, {
8623 name: jsontest.Name("Functions/Precedence/V1First"),
8624 opts: []Options{
8625 WithUnmarshalers(JoinUnmarshalers(
8626 UnmarshalFunc(func(b []byte, v *string) error {
8627 if string(b) != `"called"` {
8628 return fmt.Errorf("got %s, want %s", b, `"called"`)
8629 }
8630 *v = "called"
8631 return nil
8632 }),
8633 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8634 panic("should not be called")
8635 }),
8636 )),
8637 },
8638 inBuf: `"called"`,
8639 inVal: addr(""),
8640 want: addr("called"),
8641 }, {
8642 name: jsontest.Name("Functions/Precedence/V2First"),
8643 opts: []Options{
8644 WithUnmarshalers(JoinUnmarshalers(
8645 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8646 switch t, err := dec.ReadToken(); {
8647 case err != nil:
8648 return err
8649 case t.String() != "called":
8650 return fmt.Errorf("got %q, want %q", t, "called")
8651 }
8652 *v = "called"
8653 return nil
8654 }),
8655 UnmarshalFunc(func([]byte, *string) error {
8656 panic("should not be called")
8657 }),
8658 )),
8659 },
8660 inBuf: `"called"`,
8661 inVal: addr(""),
8662 want: addr("called"),
8663 }, {
8664 name: jsontest.Name("Functions/Precedence/V2Skipped"),
8665 opts: []Options{
8666 WithUnmarshalers(JoinUnmarshalers(
8667 UnmarshalFromFunc(func(dec *jsontext.Decoder, v *string) error {
8668 return SkipFunc
8669 }),
8670 UnmarshalFunc(func(b []byte, v *string) error {
8671 if string(b) != `"called"` {
8672 return fmt.Errorf("got %s, want %s", b, `"called"`)
8673 }
8674 *v = "called"
8675 return nil
8676 }),
8677 )),
8678 },
8679 inBuf: `"called"`,
8680 inVal: addr(""),
8681 want: addr("called"),
8682 }, {
8683 name: jsontest.Name("Functions/Precedence/NestedFirst"),
8684 opts: []Options{
8685 WithUnmarshalers(JoinUnmarshalers(
8686 JoinUnmarshalers(
8687 UnmarshalFunc(func(b []byte, v *string) error {
8688 if string(b) != `"called"` {
8689 return fmt.Errorf("got %s, want %s", b, `"called"`)
8690 }
8691 *v = "called"
8692 return nil
8693 }),
8694 ),
8695 UnmarshalFunc(func([]byte, *string) error {
8696 panic("should not be called")
8697 }),
8698 )),
8699 },
8700 inBuf: `"called"`,
8701 inVal: addr(""),
8702 want: addr("called"),
8703 }, {
8704 name: jsontest.Name("Functions/Precedence/NestedLast"),
8705 opts: []Options{
8706 WithUnmarshalers(JoinUnmarshalers(
8707 UnmarshalFunc(func(b []byte, v *string) error {
8708 if string(b) != `"called"` {
8709 return fmt.Errorf("got %s, want %s", b, `"called"`)
8710 }
8711 *v = "called"
8712 return nil
8713 }),
8714 JoinUnmarshalers(
8715 UnmarshalFunc(func([]byte, *string) error {
8716 panic("should not be called")
8717 }),
8718 ),
8719 )),
8720 },
8721 inBuf: `"called"`,
8722 inVal: addr(""),
8723 want: addr("called"),
8724 }, {
8725 name: jsontest.Name("Duration/Null"),
8726 inBuf: `{"D1":null,"D2":null}`,
8727 inVal: addr(struct {
8728 D1 time.Duration `json:",format:units"`
8729 D2 time.Duration `json:",format:nano"`
8730 }{1, 1}),
8731 want: addr(struct {
8732 D1 time.Duration `json:",format:units"`
8733 D2 time.Duration `json:",format:nano"`
8734 }{0, 0}),
8735 }, {
8736 name: jsontest.Name("Duration/Zero"),
8737 inBuf: `{"D1":"0s","D2":0}`,
8738 inVal: addr(struct {
8739 D1 time.Duration `json:",format:units"`
8740 D2 time.Duration `json:",format:nano"`
8741 }{1, 1}),
8742 want: addr(struct {
8743 D1 time.Duration `json:",format:units"`
8744 D2 time.Duration `json:",format:nano"`
8745 }{0, 0}),
8746 }, {
8747 name: jsontest.Name("Duration/Positive"),
8748 inBuf: `{"D1":"34293h33m9.123456789s","D2":123456789123456789}`,
8749 inVal: new(struct {
8750 D1 time.Duration `json:",format:units"`
8751 D2 time.Duration `json:",format:nano"`
8752 }),
8753 want: addr(struct {
8754 D1 time.Duration `json:",format:units"`
8755 D2 time.Duration `json:",format:nano"`
8756 }{
8757 123456789123456789,
8758 123456789123456789,
8759 }),
8760 }, {
8761 name: jsontest.Name("Duration/Negative"),
8762 inBuf: `{"D1":"-34293h33m9.123456789s","D2":-123456789123456789}`,
8763 inVal: new(struct {
8764 D1 time.Duration `json:",format:units"`
8765 D2 time.Duration `json:",format:nano"`
8766 }),
8767 want: addr(struct {
8768 D1 time.Duration `json:",format:units"`
8769 D2 time.Duration `json:",format:nano"`
8770 }{
8771 -123456789123456789,
8772 -123456789123456789,
8773 }),
8774 }, {
8775 name: jsontest.Name("Duration/Nanos/String"),
8776 inBuf: `{"D":"12345"}`,
8777 inVal: addr(struct {
8778 D time.Duration `json:",string,format:nano"`
8779 }{1}),
8780 want: addr(struct {
8781 D time.Duration `json:",string,format:nano"`
8782 }{12345}),
8783 }, {
8784 name: jsontest.Name("Duration/Nanos/String/Invalid"),
8785 inBuf: `{"D":"+12345"}`,
8786 inVal: addr(struct {
8787 D time.Duration `json:",string,format:nano"`
8788 }{1}),
8789 want: addr(struct {
8790 D time.Duration `json:",string,format:nano"`
8791 }{1}),
8792 wantErr: EU(fmt.Errorf(`invalid duration "+12345": %w`, strconv.ErrSyntax)).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8793 }, {
8794 name: jsontest.Name("Duration/Nanos/Mismatch"),
8795 inBuf: `{"D":"34293h33m9.123456789s"}`,
8796 inVal: addr(struct {
8797 D time.Duration `json:",format:nano"`
8798 }{1}),
8799 want: addr(struct {
8800 D time.Duration `json:",format:nano"`
8801 }{1}),
8802 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8803 }, {
8804 name: jsontest.Name("Duration/Nanos"),
8805 inBuf: `{"D":1.324}`,
8806 inVal: addr(struct {
8807 D time.Duration `json:",format:nano"`
8808 }{-1}),
8809 want: addr(struct {
8810 D time.Duration `json:",format:nano"`
8811 }{1}),
8812 }, {
8813 name: jsontest.Name("Duration/String/Mismatch"),
8814 inBuf: `{"D":-123456789123456789}`,
8815 inVal: addr(struct {
8816 D time.Duration `json:",format:units"`
8817 }{1}),
8818 want: addr(struct {
8819 D time.Duration `json:",format:units"`
8820 }{1}),
8821 wantErr: EU(nil).withPos(`{"D":`, "/D").withType('0', timeDurationType),
8822 }, {
8823 name: jsontest.Name("Duration/String/Invalid"),
8824 inBuf: `{"D":"5minkutes"}`,
8825 inVal: addr(struct {
8826 D time.Duration `json:",format:units"`
8827 }{1}),
8828 want: addr(struct {
8829 D time.Duration `json:",format:units"`
8830 }{1}),
8831 wantErr: EU(func() error {
8832 _, err := time.ParseDuration("5minkutes")
8833 return err
8834 }()).withPos(`{"D":`, "/D").withType('"', timeDurationType),
8835 }, {
8836 name: jsontest.Name("Duration/Syntax/Invalid"),
8837 inBuf: `{"D":x}`,
8838 inVal: addr(struct {
8839 D time.Duration `json:",format:units"`
8840 }{1}),
8841 want: addr(struct {
8842 D time.Duration `json:",format:units"`
8843 }{1}),
8844 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"D":`), "/D"),
8845 }, {
8846 name: jsontest.Name("Duration/Format"),
8847 inBuf: `{
8848 "D1": "12h34m56.078090012s",
8849 "D2": "12h34m56.078090012s",
8850 "D3": 45296.078090012,
8851 "D4": "45296.078090012",
8852 "D5": 45296078.090012,
8853 "D6": "45296078.090012",
8854 "D7": 45296078090.012,
8855 "D8": "45296078090.012",
8856 "D9": 45296078090012,
8857 "D10": "45296078090012",
8858 "D11": "PT12H34M56.078090012S"
8859 }`,
8860 inVal: new(structDurationFormat),
8861 want: addr(structDurationFormat{
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 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8868 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8869 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8870 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8871 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8872 12*time.Hour + 34*time.Minute + 56*time.Second + 78*time.Millisecond + 90*time.Microsecond + 12*time.Nanosecond,
8873 }),
8874 }, {
8875 name: jsontest.Name("Duration/Format/Invalid"),
8876 inBuf: `{"D":"0s"}`,
8877 inVal: addr(struct {
8878 D time.Duration `json:",format:invalid"`
8879 }{1}),
8880 want: addr(struct {
8881 D time.Duration `json:",format:invalid"`
8882 }{1}),
8883 wantErr: EU(errInvalidFormatFlag).withPos(`{"D":`, "/D").withType(0, timeDurationType),
8884 }, {
8885
8895
8901 name: jsontest.Name("Duration/MapKey/Legacy"),
8902 opts: []Options{jsonflags.FormatDurationAsNano | 1},
8903 inBuf: `{"1000000000":""}`,
8904 inVal: new(map[time.Duration]string),
8905 want: addr(map[time.Duration]string{time.Second: ""}),
8906 }, {
8907
8914 name: jsontest.Name("Time/Zero"),
8915 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"}`,
8916 inVal: new(struct {
8917 T1 time.Time
8918 T2 time.Time `json:",format:RFC822"`
8919 T3 time.Time `json:",format:'2006-01-02'"`
8920 T4 time.Time `json:",omitzero"`
8921 T5 time.Time `json:",omitempty"`
8922 }),
8923 want: addr(struct {
8924 T1 time.Time
8925 T2 time.Time `json:",format:RFC822"`
8926 T3 time.Time `json:",format:'2006-01-02'"`
8927 T4 time.Time `json:",omitzero"`
8928 T5 time.Time `json:",omitempty"`
8929 }{
8930 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8931 mustParseTime(time.RFC822, "01 Jan 01 00:00 UTC"),
8932 mustParseTime("2006-01-02", "0001-01-01"),
8933 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8934 mustParseTime(time.RFC3339Nano, "0001-01-01T00:00:00Z"),
8935 }),
8936 }, {
8937 name: jsontest.Name("Time/Format"),
8938 inBuf: `{
8939 "T1": "1234-01-02T03:04:05.000000006Z",
8940 "T2": "Mon Jan 2 03:04:05 1234",
8941 "T3": "Mon Jan 2 03:04:05 UTC 1234",
8942 "T4": "Mon Jan 02 03:04:05 +0000 1234",
8943 "T5": "02 Jan 34 03:04 UTC",
8944 "T6": "02 Jan 34 03:04 +0000",
8945 "T7": "Monday, 02-Jan-34 03:04:05 UTC",
8946 "T8": "Mon, 02 Jan 1234 03:04:05 UTC",
8947 "T9": "Mon, 02 Jan 1234 03:04:05 +0000",
8948 "T10": "1234-01-02T03:04:05Z",
8949 "T11": "1234-01-02T03:04:05.000000006Z",
8950 "T12": "3:04AM",
8951 "T13": "Jan 2 03:04:05",
8952 "T14": "Jan 2 03:04:05.000",
8953 "T15": "Jan 2 03:04:05.000000",
8954 "T16": "Jan 2 03:04:05.000000006",
8955 "T17": "1234-01-02 03:04:05",
8956 "T18": "1234-01-02",
8957 "T19": "03:04:05",
8958 "T20": "1234-01-02",
8959 "T21": "\"weird\"1234",
8960 "T22": -23225777754.999999994,
8961 "T23": "-23225777754.999999994",
8962 "T24": -23225777754999.999994,
8963 "T25": "-23225777754999.999994",
8964 "T26": -23225777754999999.994,
8965 "T27": "-23225777754999999.994",
8966 "T28": -23225777754999999994,
8967 "T29": "-23225777754999999994"
8968 }`,
8969 inVal: new(structTimeFormat),
8970 want: addr(structTimeFormat{
8971 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8972 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
8973 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
8974 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
8975 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
8976 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
8977 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
8978 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
8979 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
8980 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
8981 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
8982 mustParseTime(time.Kitchen, "3:04AM"),
8983 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
8984 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
8985 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
8986 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
8987 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
8988 mustParseTime(time.DateOnly, "1234-01-02"),
8989 mustParseTime(time.TimeOnly, "03:04:05"),
8990 mustParseTime("2006-01-02", "1234-01-02"),
8991 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
8992 time.Unix(-23225777755, 6).UTC(),
8993 time.Unix(-23225777755, 6).UTC(),
8994 time.Unix(-23225777755, 6).UTC(),
8995 time.Unix(-23225777755, 6).UTC(),
8996 time.Unix(-23225777755, 6).UTC(),
8997 time.Unix(-23225777755, 6).UTC(),
8998 time.Unix(-23225777755, 6).UTC(),
8999 time.Unix(-23225777755, 6).UTC(),
9000 }),
9001 }, {
9002 name: jsontest.Name("Time/Format/UnixString/InvalidNumber"),
9003 inBuf: `{
9004 "T23": -23225777754.999999994,
9005 "T25": -23225777754999.999994,
9006 "T27": -23225777754999999.994,
9007 "T29": -23225777754999999994
9008 }`,
9009 inVal: new(structTimeFormat),
9010 want: new(structTimeFormat),
9011 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T23": `, "/T23").withType('0', timeTimeType),
9012 }, {
9013 name: jsontest.Name("Time/Format/UnixString/InvalidString"),
9014 inBuf: `{
9015 "T22": "-23225777754.999999994",
9016 "T24": "-23225777754999.999994",
9017 "T26": "-23225777754999999.994",
9018 "T28": "-23225777754999999994"
9019 }`,
9020 inVal: new(structTimeFormat),
9021 want: new(structTimeFormat),
9022 wantErr: EU(nil).withPos(`{`+"\n\t\t\t"+`"T22": `, "/T22").withType('"', timeTimeType),
9023 }, {
9024 name: jsontest.Name("Time/Format/Null"),
9025 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}`,
9026 inVal: addr(structTimeFormat{
9027 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9028 mustParseTime(time.ANSIC, "Mon Jan 2 03:04:05 1234"),
9029 mustParseTime(time.UnixDate, "Mon Jan 2 03:04:05 UTC 1234"),
9030 mustParseTime(time.RubyDate, "Mon Jan 02 03:04:05 +0000 1234"),
9031 mustParseTime(time.RFC822, "02 Jan 34 03:04 UTC"),
9032 mustParseTime(time.RFC822Z, "02 Jan 34 03:04 +0000"),
9033 mustParseTime(time.RFC850, "Monday, 02-Jan-34 03:04:05 UTC"),
9034 mustParseTime(time.RFC1123, "Mon, 02 Jan 1234 03:04:05 UTC"),
9035 mustParseTime(time.RFC1123Z, "Mon, 02 Jan 1234 03:04:05 +0000"),
9036 mustParseTime(time.RFC3339, "1234-01-02T03:04:05Z"),
9037 mustParseTime(time.RFC3339Nano, "1234-01-02T03:04:05.000000006Z"),
9038 mustParseTime(time.Kitchen, "3:04AM"),
9039 mustParseTime(time.Stamp, "Jan 2 03:04:05"),
9040 mustParseTime(time.StampMilli, "Jan 2 03:04:05.000"),
9041 mustParseTime(time.StampMicro, "Jan 2 03:04:05.000000"),
9042 mustParseTime(time.StampNano, "Jan 2 03:04:05.000000006"),
9043 mustParseTime(time.DateTime, "1234-01-02 03:04:05"),
9044 mustParseTime(time.DateOnly, "1234-01-02"),
9045 mustParseTime(time.TimeOnly, "03:04:05"),
9046 mustParseTime("2006-01-02", "1234-01-02"),
9047 mustParseTime(`\"weird\"2006`, `\"weird\"1234`),
9048 time.Unix(-23225777755, 6).UTC(),
9049 time.Unix(-23225777755, 6).UTC(),
9050 time.Unix(-23225777755, 6).UTC(),
9051 time.Unix(-23225777755, 6).UTC(),
9052 time.Unix(-23225777755, 6).UTC(),
9053 time.Unix(-23225777755, 6).UTC(),
9054 time.Unix(-23225777755, 6).UTC(),
9055 time.Unix(-23225777755, 6).UTC(),
9056 }),
9057 want: new(structTimeFormat),
9058 }, {
9059 name: jsontest.Name("Time/RFC3339/Mismatch"),
9060 inBuf: `{"T":1234}`,
9061 inVal: new(struct {
9062 T time.Time
9063 }),
9064 wantErr: EU(nil).withPos(`{"T":`, "/T").withType('0', timeTimeType),
9065 }, {
9066 name: jsontest.Name("Time/RFC3339/ParseError"),
9067 inBuf: `{"T":"2021-09-29T12:44:52"}`,
9068 inVal: new(struct {
9069 T time.Time
9070 }),
9071 wantErr: EU(func() error {
9072 _, err := time.Parse(time.RFC3339, "2021-09-29T12:44:52")
9073 return err
9074 }()).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9075 }, {
9076 name: jsontest.Name("Time/Format/Invalid"),
9077 inBuf: `{"T":""}`,
9078 inVal: new(struct {
9079 T time.Time `json:",format:UndefinedConstant"`
9080 }),
9081 wantErr: EU(errors.New(`invalid format flag "UndefinedConstant"`)).withPos(`{"T":`, "/T").withType(0, timeTimeType),
9082 }, {
9083 name: jsontest.Name("Time/Format/SingleDigitHour"),
9084 inBuf: `{"T":"2000-01-01T1:12:34Z"}`,
9085 inVal: new(struct{ T time.Time }),
9086 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T1:12:34Z", "15", "1", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9087 }, {
9088 name: jsontest.Name("Time/Format/SubsecondComma"),
9089 inBuf: `{"T":"2000-01-01T00:00:00,000Z"}`,
9090 inVal: new(struct{ T time.Time }),
9091 wantErr: EU(newParseTimeError(time.RFC3339, "2000-01-01T00:00:00,000Z", ".", ",", "")).withPos(`{"T":`, "/T").withType('"', timeTimeType),
9092 }, {
9093 name: jsontest.Name("Time/Format/TimezoneHourOverflow"),
9094 inBuf: `{"T":"2000-01-01T00:00:00+24:00"}`,
9095 inVal: new(struct{ T time.Time }),
9096 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),
9097 }, {
9098 name: jsontest.Name("Time/Format/TimezoneMinuteOverflow"),
9099 inBuf: `{"T":"2000-01-01T00:00:00+00:60"}`,
9100 inVal: new(struct{ T time.Time }),
9101 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),
9102 }, {
9103 name: jsontest.Name("Time/Syntax/Invalid"),
9104 inBuf: `{"T":x}`,
9105 inVal: new(struct {
9106 T time.Time
9107 }),
9108 wantErr: newInvalidCharacterError("x", "at start of value", len64(`{"T":`), "/T"),
9109 }, {
9110 name: jsontest.Name("Time/IgnoreInvalidFormat"),
9111 opts: []Options{invalidFormatOption},
9112 inBuf: `"2000-01-01T00:00:00Z"`,
9113 inVal: addr(time.Time{}),
9114 want: addr(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)),
9115 }}
9116
9117 for _, tt := range tests {
9118 t.Run(tt.name.Name, func(t *testing.T) {
9119 got := tt.inVal
9120 gotErr := Unmarshal([]byte(tt.inBuf), got, tt.opts...)
9121 if !reflect.DeepEqual(got, tt.want) && tt.want != nil {
9122 t.Errorf("%s: Unmarshal output mismatch:\ngot %v\nwant %v", tt.name.Where, got, tt.want)
9123 }
9124 if !reflect.DeepEqual(gotErr, tt.wantErr) {
9125 t.Errorf("%s: Unmarshal error mismatch:\ngot %v\nwant %v", tt.name.Where, gotErr, tt.wantErr)
9126 }
9127 })
9128 }
9129 }
9130
9131 func TestMarshalInvalidNamespace(t *testing.T) {
9132 tests := []struct {
9133 name jsontest.CaseName
9134 val any
9135 }{
9136 {jsontest.Name("Map"), map[string]string{"X": "\xde\xad\xbe\xef"}},
9137 {jsontest.Name("Struct"), struct{ X string }{"\xde\xad\xbe\xef"}},
9138 }
9139 for _, tt := range tests {
9140 t.Run(tt.name.Name, func(t *testing.T) {
9141 enc := jsontext.NewEncoder(new(bytes.Buffer))
9142 if err := MarshalEncode(enc, tt.val); err == nil {
9143 t.Fatalf("%s: MarshalEncode error is nil, want non-nil", tt.name.Where)
9144 }
9145 for _, tok := range []jsontext.Token{
9146 jsontext.Null, jsontext.String(""), jsontext.Int(0), jsontext.BeginObject, jsontext.EndObject, jsontext.BeginArray, jsontext.EndArray,
9147 } {
9148 if err := enc.WriteToken(tok); err == nil {
9149 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9150 }
9151 }
9152 for _, val := range []string{`null`, `""`, `0`, `{}`, `[]`} {
9153 if err := enc.WriteValue([]byte(val)); err == nil {
9154 t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where)
9155 }
9156 }
9157 })
9158 }
9159 }
9160
9161 func TestUnmarshalInvalidNamespace(t *testing.T) {
9162 tests := []struct {
9163 name jsontest.CaseName
9164 val any
9165 }{
9166 {jsontest.Name("Map"), addr(map[string]int{})},
9167 {jsontest.Name("Struct"), addr(struct{ X int }{})},
9168 }
9169 for _, tt := range tests {
9170 t.Run(tt.name.Name, func(t *testing.T) {
9171 dec := jsontext.NewDecoder(strings.NewReader(`{"X":""}`))
9172 if err := UnmarshalDecode(dec, tt.val); err == nil {
9173 t.Fatalf("%s: UnmarshalDecode error is nil, want non-nil", tt.name.Where)
9174 }
9175 if _, err := dec.ReadToken(); err == nil {
9176 t.Fatalf("%s: ReadToken error is nil, want non-nil", tt.name.Where)
9177 }
9178 if _, err := dec.ReadValue(); err == nil {
9179 t.Fatalf("%s: ReadValue error is nil, want non-nil", tt.name.Where)
9180 }
9181 })
9182 }
9183 }
9184
9185 func TestUnmarshalReuse(t *testing.T) {
9186 t.Run("Bytes", func(t *testing.T) {
9187 in := make([]byte, 3)
9188 want := &in[0]
9189 if err := Unmarshal([]byte(`"AQID"`), &in); err != nil {
9190 t.Fatalf("Unmarshal error: %v", err)
9191 }
9192 got := &in[0]
9193 if got != want {
9194 t.Errorf("input buffer was not reused")
9195 }
9196 })
9197 t.Run("Slices", func(t *testing.T) {
9198 in := make([]int, 3)
9199 want := &in[0]
9200 if err := Unmarshal([]byte(`[0,1,2]`), &in); err != nil {
9201 t.Fatalf("Unmarshal error: %v", err)
9202 }
9203 got := &in[0]
9204 if got != want {
9205 t.Errorf("input slice was not reused")
9206 }
9207 })
9208 t.Run("Maps", func(t *testing.T) {
9209 in := make(map[string]string)
9210 want := reflect.ValueOf(in).Pointer()
9211 if err := Unmarshal([]byte(`{"key":"value"}`), &in); err != nil {
9212 t.Fatalf("Unmarshal error: %v", err)
9213 }
9214 got := reflect.ValueOf(in).Pointer()
9215 if got != want {
9216 t.Errorf("input map was not reused")
9217 }
9218 })
9219 t.Run("Pointers", func(t *testing.T) {
9220 in := addr(addr(addr("hello")))
9221 want := **in
9222 if err := Unmarshal([]byte(`"goodbye"`), &in); err != nil {
9223 t.Fatalf("Unmarshal error: %v", err)
9224 }
9225 got := **in
9226 if got != want {
9227 t.Errorf("input pointer was not reused")
9228 }
9229 })
9230 }
9231
9232 type ReaderFunc func([]byte) (int, error)
9233
9234 func (f ReaderFunc) Read(b []byte) (int, error) { return f(b) }
9235
9236 type WriterFunc func([]byte) (int, error)
9237
9238 func (f WriterFunc) Write(b []byte) (int, error) { return f(b) }
9239
9240 func TestCoderBufferGrowth(t *testing.T) {
9241
9242
9243 checkGrowth := func(ns []int) {
9244 t.Helper()
9245 var sumBytes, sumRates, numGrows float64
9246 prev := ns[0]
9247 for i := 1; i < len(ns)-1; i++ {
9248 n := ns[i]
9249 if n != prev {
9250 sumRates += float64(n) / float64(prev)
9251 numGrows++
9252 prev = n
9253 }
9254 if n > 1<<20 {
9255 t.Fatalf("single Read/Write too large: %d", n)
9256 }
9257 sumBytes += float64(n)
9258 }
9259 if mean := sumBytes / float64(len(ns)); mean < 1<<10 {
9260 t.Fatalf("average Read/Write too small: %0.1f", mean)
9261 }
9262 switch mean := sumRates / numGrows; {
9263 case mean < 1.25:
9264 t.Fatalf("average growth rate too slow: %0.3f", mean)
9265 case mean > 2.00:
9266 t.Fatalf("average growth rate too fast: %0.3f", mean)
9267 }
9268 }
9269
9270
9271
9272 bb := struct{ *bytes.Buffer }{new(bytes.Buffer)}
9273
9274 var writeSizes []int
9275 if err := MarshalWrite(WriterFunc(func(b []byte) (int, error) {
9276 n, err := bb.Write(b)
9277 writeSizes = append(writeSizes, n)
9278 return n, err
9279 }), make([]struct{}, 1e6)); err != nil {
9280 t.Fatalf("MarshalWrite error: %v", err)
9281 }
9282 checkGrowth(writeSizes)
9283
9284 var readSizes []int
9285 if err := UnmarshalRead(ReaderFunc(func(b []byte) (int, error) {
9286 n, err := bb.Read(b)
9287 readSizes = append(readSizes, n)
9288 return n, err
9289 }), new([]struct{})); err != nil {
9290 t.Fatalf("UnmarshalRead error: %v", err)
9291 }
9292 checkGrowth(readSizes)
9293 }
9294
9295 func TestUintSet(t *testing.T) {
9296 type operation any
9297 type has struct {
9298 in uint
9299 want bool
9300 }
9301 type insert struct {
9302 in uint
9303 want bool
9304 }
9305
9306
9307 ops := []operation{
9308 has{0, false},
9309 has{63, false},
9310 has{64, false},
9311 has{1234, false},
9312 insert{3, true},
9313 has{2, false},
9314 has{3, true},
9315 has{4, false},
9316 has{63, false},
9317 insert{3, false},
9318 insert{63, true},
9319 has{63, true},
9320 insert{64, true},
9321 insert{64, false},
9322 has{64, true},
9323 insert{3264, true},
9324 has{3264, true},
9325 insert{3, false},
9326 has{3, true},
9327 }
9328
9329 var us uintSet
9330 for i, op := range ops {
9331 switch op := op.(type) {
9332 case has:
9333 if got := us.has(op.in); got != op.want {
9334 t.Fatalf("%d: uintSet.has(%v) = %v, want %v", i, op.in, got, op.want)
9335 }
9336 case insert:
9337 if got := us.insert(op.in); got != op.want {
9338 t.Fatalf("%d: uintSet.insert(%v) = %v, want %v", i, op.in, got, op.want)
9339 }
9340 default:
9341 panic(fmt.Sprintf("unknown operation: %T", op))
9342 }
9343 }
9344 }
9345
9346 func TestUnmarshalDecodeOptions(t *testing.T) {
9347 var calledFuncs int
9348 var calledOptions Options
9349 in := strings.NewReader(strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9350 dec := jsontext.NewDecoder(in,
9351 jsontext.AllowInvalidUTF8(true),
9352 WithUnmarshalers(UnmarshalFromFunc(func(dec *jsontext.Decoder, _ any) error {
9353 opts := dec.Options()
9354 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9355 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9356 }
9357 calledFuncs++
9358 calledOptions = opts
9359 return SkipFunc
9360 })),
9361 )
9362
9363 if err := UnmarshalDecode(dec, new(string)); err != nil {
9364 t.Fatalf("UnmarshalDecode: %v", err)
9365 }
9366 if calledFuncs != 1 {
9367 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9368 }
9369 if err := UnmarshalDecode(dec, new(string), calledOptions); err != nil {
9370 t.Fatalf("UnmarshalDecode: %v", err)
9371 }
9372 if calledFuncs != 2 {
9373 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9374 }
9375 if err := UnmarshalDecode(dec, new(string),
9376 jsontext.AllowInvalidUTF8(false),
9377 WithUnmarshalers(nil),
9378 ); err != nil {
9379 t.Fatalf("UnmarshalDecode: %v", err)
9380 }
9381 if calledFuncs != 2 {
9382 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9383 }
9384 if err := UnmarshalDecode(dec, new(string)); err != nil {
9385 t.Fatalf("UnmarshalDecode: %v", err)
9386 }
9387 if calledFuncs != 3 {
9388 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9389 }
9390 if err := UnmarshalDecode(dec, new(string), JoinOptions(
9391 jsontext.AllowInvalidUTF8(false),
9392 WithUnmarshalers(UnmarshalFromFunc(func(_ *jsontext.Decoder, _ any) error {
9393 opts := dec.Options()
9394 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9395 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9396 }
9397 calledFuncs = math.MaxInt
9398 return SkipFunc
9399 })),
9400 )); err != nil {
9401 t.Fatalf("UnmarshalDecode: %v", err)
9402 }
9403 if calledFuncs != math.MaxInt {
9404 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9405 }
9406
9407
9408
9409 opts := dec.Options()
9410 dec.Reset(in, jsontext.AllowInvalidUTF8(false), opts)
9411 if v, _ := GetOption(dec.Options(), jsontext.AllowInvalidUTF8); v == false {
9412 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9413 }
9414 }
9415
9416
9417
9418 func BenchmarkUnmarshalDecodeOptions(b *testing.B) {
9419 var i int
9420 in := new(bytes.Buffer)
9421 dec := jsontext.NewDecoder(in)
9422 makeBench := func(opts ...Options) func(*testing.B) {
9423 return func(b *testing.B) {
9424 for range b.N {
9425 in.WriteString("0 ")
9426 }
9427 dec.Reset(in)
9428 b.ResetTimer()
9429 for range b.N {
9430 UnmarshalDecode(dec, &i, opts...)
9431 }
9432 }
9433 }
9434 b.Run("None", makeBench())
9435 b.Run("Same", makeBench(&export.Decoder(dec).Struct))
9436 b.Run("New", makeBench(DefaultOptionsV2()))
9437 }
9438
9439 func TestMarshalEncodeOptions(t *testing.T) {
9440 var calledFuncs int
9441 var calledOptions Options
9442 out := new(bytes.Buffer)
9443 enc := jsontext.NewEncoder(
9444 out,
9445 jsontext.AllowInvalidUTF8(true),
9446 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9447 opts := enc.Options()
9448 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9449 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9450 }
9451 calledFuncs++
9452 calledOptions = opts
9453 return SkipFunc
9454 })),
9455 )
9456
9457 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9458 t.Fatalf("MarshalEncode: %v", err)
9459 }
9460 if calledFuncs != 1 {
9461 t.Fatalf("calledFuncs = %d, want 1", calledFuncs)
9462 }
9463 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", calledOptions); err != nil {
9464 t.Fatalf("MarshalEncode: %v", err)
9465 }
9466 if calledFuncs != 2 {
9467 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9468 }
9469 if err := MarshalEncode(enc, "\xde\xad\xbe\xef",
9470 jsontext.AllowInvalidUTF8(false),
9471 WithMarshalers(nil),
9472 ); err != nil {
9473 t.Fatalf("MarshalEncode: %v", err)
9474 }
9475 if calledFuncs != 2 {
9476 t.Fatalf("calledFuncs = %d, want 2", calledFuncs)
9477 }
9478 if err := MarshalEncode(enc, "\xde\xad\xbe\xef"); err != nil {
9479 t.Fatalf("MarshalEncode: %v", err)
9480 }
9481 if calledFuncs != 3 {
9482 t.Fatalf("calledFuncs = %d, want 3", calledFuncs)
9483 }
9484 if err := MarshalEncode(enc, "\xde\xad\xbe\xef", JoinOptions(
9485 jsontext.AllowInvalidUTF8(false),
9486 WithMarshalers(MarshalToFunc(func(enc *jsontext.Encoder, _ any) error {
9487 opts := enc.Options()
9488 if v, _ := GetOption(opts, jsontext.AllowInvalidUTF8); !v {
9489 t.Errorf("nested Options.AllowInvalidUTF8 = false, want true")
9490 }
9491 calledFuncs = math.MaxInt
9492 return SkipFunc
9493 })),
9494 )); err != nil {
9495 t.Fatalf("MarshalEncode: %v", err)
9496 }
9497 if calledFuncs != math.MaxInt {
9498 t.Fatalf("calledFuncs = %d, want %d", calledFuncs, math.MaxInt)
9499 }
9500 if out.String() != strings.Repeat("\"\xde\xad\ufffd\ufffd\"\n", 5) {
9501 t.Fatalf("output mismatch:\n\tgot: %s\n\twant: %s", out.String(), strings.Repeat("\"\xde\xad\xbe\xef\"\n", 5))
9502 }
9503
9504
9505
9506 opts := enc.Options()
9507 enc.Reset(out, jsontext.AllowInvalidUTF8(false), opts)
9508 if v, _ := GetOption(enc.Options(), jsontext.AllowInvalidUTF8); v == false {
9509 t.Errorf("Options.AllowInvalidUTF8 = false, want true")
9510 }
9511 }
9512
9513
9514
9515 func BenchmarkMarshalEncodeOptions(b *testing.B) {
9516 var i int
9517 out := new(bytes.Buffer)
9518 enc := jsontext.NewEncoder(out)
9519 makeBench := func(opts ...Options) func(*testing.B) {
9520 return func(b *testing.B) {
9521 out.Reset()
9522 enc.Reset(out)
9523 b.ResetTimer()
9524 for range b.N {
9525 MarshalEncode(enc, &i, opts...)
9526 }
9527 }
9528 }
9529 b.Run("None", makeBench())
9530 b.Run("Same", makeBench(&export.Encoder(enc).Struct))
9531 b.Run("New", makeBench(DefaultOptionsV2()))
9532 }
9533
View as plain text