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