1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 package json
46
47 import (
48 "bytes"
49 "cmp"
50 "encoding"
51 "encoding/base64"
52 "fmt"
53 "math"
54 "reflect"
55 "slices"
56 "strconv"
57 "strings"
58 "sync"
59 "unicode"
60 "unicode/utf8"
61 )
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 func Marshal(v any) ([]byte, error) {
205 e := newEncodeState()
206 defer encodeStatePool.Put(e)
207
208 err := e.marshal(v, encOpts{escapeHTML: true})
209 if err != nil {
210 return nil, err
211 }
212 buf := append([]byte(nil), e.Bytes()...)
213
214 return buf, nil
215 }
216
217
218
219
220 func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
221 b, err := Marshal(v)
222 if err != nil {
223 return nil, err
224 }
225 b2 := make([]byte, 0, indentGrowthFactor*len(b))
226 b2, err = appendIndent(b2, b, prefix, indent)
227 if err != nil {
228 return nil, err
229 }
230 return b2, nil
231 }
232
233
234
235 type Marshaler interface {
236 MarshalJSON() ([]byte, error)
237 }
238
239
240
241 type UnsupportedTypeError struct {
242 Type reflect.Type
243 }
244
245 func (e *UnsupportedTypeError) Error() string {
246 return "json: unsupported type: " + e.Type.String()
247 }
248
249
250
251 type UnsupportedValueError struct {
252 Value reflect.Value
253 Str string
254 }
255
256 func (e *UnsupportedValueError) Error() string {
257 return "json: unsupported value: " + e.Str
258 }
259
260
261
262
263
264
265
266 type InvalidUTF8Error struct {
267 S string
268 }
269
270 func (e *InvalidUTF8Error) Error() string {
271 return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
272 }
273
274
275
276 type MarshalerError struct {
277 Type reflect.Type
278 Err error
279 sourceFunc string
280 }
281
282 func (e *MarshalerError) Error() string {
283 srcFunc := e.sourceFunc
284 if srcFunc == "" {
285 srcFunc = "MarshalJSON"
286 }
287 return "json: error calling " + srcFunc +
288 " for type " + e.Type.String() +
289 ": " + e.Err.Error()
290 }
291
292
293 func (e *MarshalerError) Unwrap() error { return e.Err }
294
295 const hex = "0123456789abcdef"
296
297
298 type encodeState struct {
299 bytes.Buffer
300
301
302
303
304
305
306 ptrLevel uint
307 ptrSeen map[any]struct{}
308 }
309
310 const startDetectingCyclesAfter = 1000
311
312 var encodeStatePool sync.Pool
313
314 func newEncodeState() *encodeState {
315 if v := encodeStatePool.Get(); v != nil {
316 e := v.(*encodeState)
317 e.Reset()
318 if len(e.ptrSeen) > 0 {
319 panic("ptrEncoder.encode should have emptied ptrSeen via defers")
320 }
321 e.ptrLevel = 0
322 return e
323 }
324 return &encodeState{ptrSeen: make(map[any]struct{})}
325 }
326
327
328
329
330 type jsonError struct{ error }
331
332 func (e *encodeState) marshal(v any, opts encOpts) (err error) {
333 defer func() {
334 if r := recover(); r != nil {
335 if je, ok := r.(jsonError); ok {
336 err = je.error
337 } else {
338 panic(r)
339 }
340 }
341 }()
342 e.reflectValue(reflect.ValueOf(v), opts)
343 return nil
344 }
345
346
347 func (e *encodeState) error(err error) {
348 panic(jsonError{err})
349 }
350
351 func isEmptyValue(v reflect.Value) bool {
352 switch v.Kind() {
353 case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
354 return v.Len() == 0
355 case reflect.Bool,
356 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
357 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
358 reflect.Float32, reflect.Float64,
359 reflect.Interface, reflect.Pointer:
360 return v.IsZero()
361 }
362 return false
363 }
364
365 func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
366 valueEncoder(v)(e, v, opts)
367 }
368
369 type encOpts struct {
370
371 quoted bool
372
373 escapeHTML bool
374 }
375
376 type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
377
378 var encoderCache sync.Map
379
380 func valueEncoder(v reflect.Value) encoderFunc {
381 if !v.IsValid() {
382 return invalidValueEncoder
383 }
384 return typeEncoder(v.Type())
385 }
386
387 func typeEncoder(t reflect.Type) encoderFunc {
388 if fi, ok := encoderCache.Load(t); ok {
389 return fi.(encoderFunc)
390 }
391
392
393
394
395
396
397
398 indirect := sync.OnceValue(func() encoderFunc {
399 return newTypeEncoder(t, true)
400 })
401 fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
402 indirect()(e, v, opts)
403 }))
404 if loaded {
405 return fi.(encoderFunc)
406 }
407
408 f := indirect()
409 encoderCache.Store(t, f)
410 return f
411 }
412
413 var (
414 marshalerType = reflect.TypeFor[Marshaler]()
415 textMarshalerType = reflect.TypeFor[encoding.TextMarshaler]()
416 )
417
418
419
420 func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
421
422
423
424
425 if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
426 return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
427 }
428 if t.Implements(marshalerType) {
429 return marshalerEncoder
430 }
431 if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
432 return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
433 }
434 if t.Implements(textMarshalerType) {
435 return textMarshalerEncoder
436 }
437
438 switch t.Kind() {
439 case reflect.Bool:
440 return boolEncoder
441 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
442 return intEncoder
443 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
444 return uintEncoder
445 case reflect.Float32:
446 return float32Encoder
447 case reflect.Float64:
448 return float64Encoder
449 case reflect.String:
450 return stringEncoder
451 case reflect.Interface:
452 return interfaceEncoder
453 case reflect.Struct:
454 return newStructEncoder(t)
455 case reflect.Map:
456 return newMapEncoder(t)
457 case reflect.Slice:
458 return newSliceEncoder(t)
459 case reflect.Array:
460 return newArrayEncoder(t)
461 case reflect.Pointer:
462 return newPtrEncoder(t)
463 default:
464 return unsupportedTypeEncoder
465 }
466 }
467
468 func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
469 e.WriteString("null")
470 }
471
472 func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
473 if v.Kind() == reflect.Pointer && v.IsNil() {
474 e.WriteString("null")
475 return
476 }
477 m, ok := reflect.TypeAssert[Marshaler](v)
478 if !ok {
479 e.WriteString("null")
480 return
481 }
482 b, err := m.MarshalJSON()
483 if err == nil {
484 e.Grow(len(b))
485 out := e.AvailableBuffer()
486 out, err = appendCompact(out, b, opts.escapeHTML)
487 e.Buffer.Write(out)
488 }
489 if err != nil {
490 e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
491 }
492 }
493
494 func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
495 va := v.Addr()
496 if va.IsNil() {
497 e.WriteString("null")
498 return
499 }
500 m, _ := reflect.TypeAssert[Marshaler](va)
501 b, err := m.MarshalJSON()
502 if err == nil {
503 e.Grow(len(b))
504 out := e.AvailableBuffer()
505 out, err = appendCompact(out, b, opts.escapeHTML)
506 e.Buffer.Write(out)
507 }
508 if err != nil {
509 e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
510 }
511 }
512
513 func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
514 if v.Kind() == reflect.Pointer && v.IsNil() {
515 e.WriteString("null")
516 return
517 }
518 m, ok := reflect.TypeAssert[encoding.TextMarshaler](v)
519 if !ok {
520 e.WriteString("null")
521 return
522 }
523 b, err := m.MarshalText()
524 if err != nil {
525 e.error(&MarshalerError{v.Type(), err, "MarshalText"})
526 }
527 e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
528 }
529
530 func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
531 va := v.Addr()
532 if va.IsNil() {
533 e.WriteString("null")
534 return
535 }
536 m, _ := reflect.TypeAssert[encoding.TextMarshaler](va)
537 b, err := m.MarshalText()
538 if err != nil {
539 e.error(&MarshalerError{v.Type(), err, "MarshalText"})
540 }
541 e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
542 }
543
544 func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) {
545 b := e.AvailableBuffer()
546 b = mayAppendQuote(b, opts.quoted)
547 b = strconv.AppendBool(b, v.Bool())
548 b = mayAppendQuote(b, opts.quoted)
549 e.Write(b)
550 }
551
552 func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
553 b := e.AvailableBuffer()
554 b = mayAppendQuote(b, opts.quoted)
555 b = strconv.AppendInt(b, v.Int(), 10)
556 b = mayAppendQuote(b, opts.quoted)
557 e.Write(b)
558 }
559
560 func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) {
561 b := e.AvailableBuffer()
562 b = mayAppendQuote(b, opts.quoted)
563 b = strconv.AppendUint(b, v.Uint(), 10)
564 b = mayAppendQuote(b, opts.quoted)
565 e.Write(b)
566 }
567
568 type floatEncoder int
569
570 func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
571 f := v.Float()
572 if math.IsInf(f, 0) || math.IsNaN(f) {
573 e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
574 }
575
576
577
578
579
580
581 b := e.AvailableBuffer()
582 b = mayAppendQuote(b, opts.quoted)
583 abs := math.Abs(f)
584 fmt := byte('f')
585
586 if abs != 0 {
587 if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
588 fmt = 'e'
589 }
590 }
591 b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
592 if fmt == 'e' {
593
594 n := len(b)
595 if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
596 b[n-2] = b[n-1]
597 b = b[:n-1]
598 }
599 }
600 b = mayAppendQuote(b, opts.quoted)
601 e.Write(b)
602 }
603
604 var (
605 float32Encoder = (floatEncoder(32)).encode
606 float64Encoder = (floatEncoder(64)).encode
607 )
608
609 func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
610 if v.Type() == numberType {
611 numStr := v.String()
612
613
614 if numStr == "" {
615 numStr = "0"
616 }
617 if !isValidNumber(numStr) {
618 e.error(fmt.Errorf("json: invalid number literal %q", numStr))
619 }
620 b := e.AvailableBuffer()
621 b = mayAppendQuote(b, opts.quoted)
622 b = append(b, numStr...)
623 b = mayAppendQuote(b, opts.quoted)
624 e.Write(b)
625 return
626 }
627 if opts.quoted {
628 b := appendString(nil, v.String(), opts.escapeHTML)
629 e.Write(appendString(e.AvailableBuffer(), b, false))
630 } else {
631 e.Write(appendString(e.AvailableBuffer(), v.String(), opts.escapeHTML))
632 }
633 }
634
635 func isValidNumber(s string) bool {
636
637
638
639
640 if s == "" {
641 return false
642 }
643
644
645 if s[0] == '-' {
646 s = s[1:]
647 if s == "" {
648 return false
649 }
650 }
651
652
653 switch {
654 default:
655 return false
656
657 case s[0] == '0':
658 s = s[1:]
659
660 case '1' <= s[0] && s[0] <= '9':
661 s = s[1:]
662 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
663 s = s[1:]
664 }
665 }
666
667
668 if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
669 s = s[2:]
670 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
671 s = s[1:]
672 }
673 }
674
675
676
677 if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
678 s = s[1:]
679 if s[0] == '+' || s[0] == '-' {
680 s = s[1:]
681 if s == "" {
682 return false
683 }
684 }
685 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
686 s = s[1:]
687 }
688 }
689
690
691 return s == ""
692 }
693
694 func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
695 if v.IsNil() {
696 e.WriteString("null")
697 return
698 }
699 e.reflectValue(v.Elem(), opts)
700 }
701
702 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
703 e.error(&UnsupportedTypeError{v.Type()})
704 }
705
706 type structEncoder struct {
707 fields structFields
708 }
709
710 type structFields struct {
711 list []field
712 byExactName map[string]*field
713 byFoldedName map[string]*field
714 }
715
716 func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
717 next := byte('{')
718 FieldLoop:
719 for i := range se.fields.list {
720 f := &se.fields.list[i]
721
722
723 fv := v
724 for _, i := range f.index {
725 if fv.Kind() == reflect.Pointer {
726 if fv.IsNil() {
727 continue FieldLoop
728 }
729 fv = fv.Elem()
730 }
731 fv = fv.Field(i)
732 }
733
734 if (f.omitEmpty && isEmptyValue(fv)) ||
735 (f.omitZero && (f.isZero == nil && fv.IsZero() || (f.isZero != nil && f.isZero(fv)))) {
736 continue
737 }
738 e.WriteByte(next)
739 next = ','
740 if opts.escapeHTML {
741 e.WriteString(f.nameEscHTML)
742 } else {
743 e.WriteString(f.nameNonEsc)
744 }
745 opts.quoted = f.quoted
746 f.encoder(e, fv, opts)
747 }
748 if next == '{' {
749 e.WriteString("{}")
750 } else {
751 e.WriteByte('}')
752 }
753 }
754
755 func newStructEncoder(t reflect.Type) encoderFunc {
756 se := structEncoder{fields: cachedTypeFields(t)}
757 return se.encode
758 }
759
760 type mapEncoder struct {
761 elemEnc encoderFunc
762 }
763
764 func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
765 if v.IsNil() {
766 e.WriteString("null")
767 return
768 }
769 if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
770
771
772 ptr := v.UnsafePointer()
773 if _, ok := e.ptrSeen[ptr]; ok {
774 e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
775 }
776 e.ptrSeen[ptr] = struct{}{}
777 defer delete(e.ptrSeen, ptr)
778 }
779 e.WriteByte('{')
780
781
782 var (
783 sv = make([]reflectWithString, v.Len())
784 mi = v.MapRange()
785 err error
786 )
787 for i := 0; mi.Next(); i++ {
788 if sv[i].ks, err = resolveKeyName(mi.Key()); err != nil {
789 e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
790 }
791 sv[i].v = mi.Value()
792 }
793 slices.SortFunc(sv, func(i, j reflectWithString) int {
794 return strings.Compare(i.ks, j.ks)
795 })
796
797 for i, kv := range sv {
798 if i > 0 {
799 e.WriteByte(',')
800 }
801 e.Write(appendString(e.AvailableBuffer(), kv.ks, opts.escapeHTML))
802 e.WriteByte(':')
803 me.elemEnc(e, kv.v, opts)
804 }
805 e.WriteByte('}')
806 e.ptrLevel--
807 }
808
809 func newMapEncoder(t reflect.Type) encoderFunc {
810 switch t.Key().Kind() {
811 case reflect.String,
812 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
813 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
814 default:
815 if !t.Key().Implements(textMarshalerType) {
816 return unsupportedTypeEncoder
817 }
818 }
819 me := mapEncoder{typeEncoder(t.Elem())}
820 return me.encode
821 }
822
823 func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
824 if v.IsNil() {
825 e.WriteString("null")
826 return
827 }
828
829 s := v.Bytes()
830 b := e.AvailableBuffer()
831 b = append(b, '"')
832 b = base64.StdEncoding.AppendEncode(b, s)
833 b = append(b, '"')
834 e.Write(b)
835 }
836
837
838 type sliceEncoder struct {
839 arrayEnc encoderFunc
840 }
841
842 func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
843 if v.IsNil() {
844 e.WriteString("null")
845 return
846 }
847 if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
848
849
850
851
852 ptr := struct {
853 ptr any
854 len int
855 }{v.UnsafePointer(), v.Len()}
856 if _, ok := e.ptrSeen[ptr]; ok {
857 e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
858 }
859 e.ptrSeen[ptr] = struct{}{}
860 defer delete(e.ptrSeen, ptr)
861 }
862 se.arrayEnc(e, v, opts)
863 e.ptrLevel--
864 }
865
866 func newSliceEncoder(t reflect.Type) encoderFunc {
867
868 if t.Elem().Kind() == reflect.Uint8 {
869 p := reflect.PointerTo(t.Elem())
870 if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
871 return encodeByteSlice
872 }
873 }
874 enc := sliceEncoder{newArrayEncoder(t)}
875 return enc.encode
876 }
877
878 type arrayEncoder struct {
879 elemEnc encoderFunc
880 }
881
882 func (ae arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
883 e.WriteByte('[')
884 n := v.Len()
885 for i := 0; i < n; i++ {
886 if i > 0 {
887 e.WriteByte(',')
888 }
889 ae.elemEnc(e, v.Index(i), opts)
890 }
891 e.WriteByte(']')
892 }
893
894 func newArrayEncoder(t reflect.Type) encoderFunc {
895 enc := arrayEncoder{typeEncoder(t.Elem())}
896 return enc.encode
897 }
898
899 type ptrEncoder struct {
900 elemEnc encoderFunc
901 }
902
903 func (pe ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
904 if v.IsNil() {
905 e.WriteString("null")
906 return
907 }
908 if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
909
910
911 ptr := v.Interface()
912 if _, ok := e.ptrSeen[ptr]; ok {
913 e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
914 }
915 e.ptrSeen[ptr] = struct{}{}
916 defer delete(e.ptrSeen, ptr)
917 }
918 pe.elemEnc(e, v.Elem(), opts)
919 e.ptrLevel--
920 }
921
922 func newPtrEncoder(t reflect.Type) encoderFunc {
923 enc := ptrEncoder{typeEncoder(t.Elem())}
924 return enc.encode
925 }
926
927 type condAddrEncoder struct {
928 canAddrEnc, elseEnc encoderFunc
929 }
930
931 func (ce condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
932 if v.CanAddr() {
933 ce.canAddrEnc(e, v, opts)
934 } else {
935 ce.elseEnc(e, v, opts)
936 }
937 }
938
939
940
941 func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
942 enc := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
943 return enc.encode
944 }
945
946 func isValidTag(s string) bool {
947 if s == "" {
948 return false
949 }
950 for _, c := range s {
951 switch {
952 case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
953
954
955
956 case !unicode.IsLetter(c) && !unicode.IsDigit(c):
957 return false
958 }
959 }
960 return true
961 }
962
963 func typeByIndex(t reflect.Type, index []int) reflect.Type {
964 for _, i := range index {
965 if t.Kind() == reflect.Pointer {
966 t = t.Elem()
967 }
968 t = t.Field(i).Type
969 }
970 return t
971 }
972
973 type reflectWithString struct {
974 v reflect.Value
975 ks string
976 }
977
978 func resolveKeyName(k reflect.Value) (string, error) {
979 if k.Kind() == reflect.String {
980 return k.String(), nil
981 }
982 if tm, ok := reflect.TypeAssert[encoding.TextMarshaler](k); ok {
983 if k.Kind() == reflect.Pointer && k.IsNil() {
984 return "", nil
985 }
986 buf, err := tm.MarshalText()
987 return string(buf), err
988 }
989 switch k.Kind() {
990 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
991 return strconv.FormatInt(k.Int(), 10), nil
992 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
993 return strconv.FormatUint(k.Uint(), 10), nil
994 }
995 panic("unexpected map key type")
996 }
997
998 func appendString[Bytes []byte | string](dst []byte, src Bytes, escapeHTML bool) []byte {
999 dst = append(dst, '"')
1000 start := 0
1001 for i := 0; i < len(src); {
1002 if b := src[i]; b < utf8.RuneSelf {
1003 if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
1004 i++
1005 continue
1006 }
1007 dst = append(dst, src[start:i]...)
1008 switch b {
1009 case '\\', '"':
1010 dst = append(dst, '\\', b)
1011 case '\b':
1012 dst = append(dst, '\\', 'b')
1013 case '\f':
1014 dst = append(dst, '\\', 'f')
1015 case '\n':
1016 dst = append(dst, '\\', 'n')
1017 case '\r':
1018 dst = append(dst, '\\', 'r')
1019 case '\t':
1020 dst = append(dst, '\\', 't')
1021 default:
1022
1023
1024
1025
1026
1027 dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
1028 }
1029 i++
1030 start = i
1031 continue
1032 }
1033
1034
1035
1036
1037 n := min(len(src)-i, utf8.UTFMax)
1038 c, size := utf8.DecodeRuneInString(string(src[i : i+n]))
1039 if c == utf8.RuneError && size == 1 {
1040 dst = append(dst, src[start:i]...)
1041 dst = append(dst, `\ufffd`...)
1042 i += size
1043 start = i
1044 continue
1045 }
1046
1047
1048
1049
1050
1051
1052
1053 if c == '\u2028' || c == '\u2029' {
1054 dst = append(dst, src[start:i]...)
1055 dst = append(dst, '\\', 'u', '2', '0', '2', hex[c&0xF])
1056 i += size
1057 start = i
1058 continue
1059 }
1060 i += size
1061 }
1062 dst = append(dst, src[start:]...)
1063 dst = append(dst, '"')
1064 return dst
1065 }
1066
1067
1068 type field struct {
1069 name string
1070 nameBytes []byte
1071
1072 nameNonEsc string
1073 nameEscHTML string
1074
1075 tag bool
1076 index []int
1077 typ reflect.Type
1078 omitEmpty bool
1079 omitZero bool
1080 isZero func(reflect.Value) bool
1081 quoted bool
1082
1083 encoder encoderFunc
1084 }
1085
1086 type isZeroer interface {
1087 IsZero() bool
1088 }
1089
1090 var isZeroerType = reflect.TypeFor[isZeroer]()
1091
1092 func typeFields(t reflect.Type) structFields {
1093
1094 current := []field{}
1095 next := []field{{typ: t}}
1096
1097
1098 var count, nextCount map[reflect.Type]int
1099
1100
1101 visited := map[reflect.Type]bool{}
1102
1103
1104 var fields []field
1105
1106
1107 var nameEscBuf []byte
1108
1109 for len(next) > 0 {
1110 current, next = next, current[:0]
1111 count, nextCount = nextCount, map[reflect.Type]int{}
1112
1113 for _, f := range current {
1114 if visited[f.typ] {
1115 continue
1116 }
1117 visited[f.typ] = true
1118
1119
1120 for i := 0; i < f.typ.NumField(); i++ {
1121 sf := f.typ.Field(i)
1122 if sf.Anonymous {
1123 t := sf.Type
1124 if t.Kind() == reflect.Pointer {
1125 t = t.Elem()
1126 }
1127 if !sf.IsExported() && t.Kind() != reflect.Struct {
1128
1129 continue
1130 }
1131
1132
1133 } else if !sf.IsExported() {
1134
1135 continue
1136 }
1137 tag := sf.Tag.Get("json")
1138 if tag == "-" {
1139 continue
1140 }
1141 name, opts := parseTag(tag)
1142 if !isValidTag(name) {
1143 name = ""
1144 }
1145 index := make([]int, len(f.index)+1)
1146 copy(index, f.index)
1147 index[len(f.index)] = i
1148
1149 ft := sf.Type
1150 if ft.Name() == "" && ft.Kind() == reflect.Pointer {
1151
1152 ft = ft.Elem()
1153 }
1154
1155
1156 quoted := false
1157 if opts.Contains("string") {
1158 switch ft.Kind() {
1159 case reflect.Bool,
1160 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1161 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
1162 reflect.Float32, reflect.Float64,
1163 reflect.String:
1164 quoted = true
1165 }
1166 }
1167
1168
1169 if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
1170 tagged := name != ""
1171 if name == "" {
1172 name = sf.Name
1173 }
1174 field := field{
1175 name: name,
1176 tag: tagged,
1177 index: index,
1178 typ: ft,
1179 omitEmpty: opts.Contains("omitempty"),
1180 omitZero: opts.Contains("omitzero"),
1181 quoted: quoted,
1182 }
1183 field.nameBytes = []byte(field.name)
1184
1185
1186 nameEscBuf = appendHTMLEscape(nameEscBuf[:0], field.nameBytes)
1187 field.nameEscHTML = `"` + string(nameEscBuf) + `":`
1188 field.nameNonEsc = `"` + field.name + `":`
1189
1190 if field.omitZero {
1191 t := sf.Type
1192
1193 switch {
1194 case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
1195 field.isZero = func(v reflect.Value) bool {
1196
1197
1198 return v.IsNil() ||
1199 (v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
1200 v.Interface().(isZeroer).IsZero()
1201 }
1202 case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
1203 field.isZero = func(v reflect.Value) bool {
1204
1205 return v.IsNil() || v.Interface().(isZeroer).IsZero()
1206 }
1207 case t.Implements(isZeroerType):
1208 field.isZero = func(v reflect.Value) bool {
1209 return v.Interface().(isZeroer).IsZero()
1210 }
1211 case reflect.PointerTo(t).Implements(isZeroerType):
1212 field.isZero = func(v reflect.Value) bool {
1213 if !v.CanAddr() {
1214
1215 v2 := reflect.New(v.Type()).Elem()
1216 v2.Set(v)
1217 v = v2
1218 }
1219 return v.Addr().Interface().(isZeroer).IsZero()
1220 }
1221 }
1222 }
1223
1224 fields = append(fields, field)
1225 if count[f.typ] > 1 {
1226
1227
1228
1229
1230 fields = append(fields, fields[len(fields)-1])
1231 }
1232 continue
1233 }
1234
1235
1236 nextCount[ft]++
1237 if nextCount[ft] == 1 {
1238 next = append(next, field{name: ft.Name(), index: index, typ: ft})
1239 }
1240 }
1241 }
1242 }
1243
1244 slices.SortFunc(fields, func(a, b field) int {
1245
1246
1247
1248 if c := strings.Compare(a.name, b.name); c != 0 {
1249 return c
1250 }
1251 if c := cmp.Compare(len(a.index), len(b.index)); c != 0 {
1252 return c
1253 }
1254 if a.tag != b.tag {
1255 if a.tag {
1256 return -1
1257 }
1258 return +1
1259 }
1260 return slices.Compare(a.index, b.index)
1261 })
1262
1263
1264
1265
1266
1267
1268
1269 out := fields[:0]
1270 for advance, i := 0, 0; i < len(fields); i += advance {
1271
1272
1273 fi := fields[i]
1274 name := fi.name
1275 for advance = 1; i+advance < len(fields); advance++ {
1276 fj := fields[i+advance]
1277 if fj.name != name {
1278 break
1279 }
1280 }
1281 if advance == 1 {
1282 out = append(out, fi)
1283 continue
1284 }
1285 dominant, ok := dominantField(fields[i : i+advance])
1286 if ok {
1287 out = append(out, dominant)
1288 }
1289 }
1290
1291 fields = out
1292 slices.SortFunc(fields, func(i, j field) int {
1293 return slices.Compare(i.index, j.index)
1294 })
1295
1296 for i := range fields {
1297 f := &fields[i]
1298 f.encoder = typeEncoder(typeByIndex(t, f.index))
1299 }
1300 exactNameIndex := make(map[string]*field, len(fields))
1301 foldedNameIndex := make(map[string]*field, len(fields))
1302 for i, field := range fields {
1303 exactNameIndex[field.name] = &fields[i]
1304
1305 if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
1306 foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
1307 }
1308 }
1309 return structFields{fields, exactNameIndex, foldedNameIndex}
1310 }
1311
1312
1313
1314
1315
1316
1317
1318 func dominantField(fields []field) (field, bool) {
1319
1320
1321
1322 if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
1323 return field{}, false
1324 }
1325 return fields[0], true
1326 }
1327
1328 var fieldCache sync.Map
1329
1330
1331 func cachedTypeFields(t reflect.Type) structFields {
1332 if f, ok := fieldCache.Load(t); ok {
1333 return f.(structFields)
1334 }
1335 f, _ := fieldCache.LoadOrStore(t, typeFields(t))
1336 return f.(structFields)
1337 }
1338
1339 func mayAppendQuote(b []byte, quoted bool) []byte {
1340 if quoted {
1341 b = append(b, '"')
1342 }
1343 return b
1344 }
1345
View as plain text