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