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 := reflect.TypeAssert[Marshaler](v)
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, _ := reflect.TypeAssert[Marshaler](va)
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 := reflect.TypeAssert[encoding.TextMarshaler](v)
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, _ := reflect.TypeAssert[encoding.TextMarshaler](va)
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 func isValidNumber(s string) bool {
637
638
639
640
641 if s == "" {
642 return false
643 }
644
645
646 if s[0] == '-' {
647 s = s[1:]
648 if s == "" {
649 return false
650 }
651 }
652
653
654 switch {
655 default:
656 return false
657
658 case s[0] == '0':
659 s = s[1:]
660
661 case '1' <= s[0] && s[0] <= '9':
662 s = s[1:]
663 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
664 s = s[1:]
665 }
666 }
667
668
669 if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
670 s = s[2:]
671 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
672 s = s[1:]
673 }
674 }
675
676
677
678 if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
679 s = s[1:]
680 if s[0] == '+' || s[0] == '-' {
681 s = s[1:]
682 if s == "" {
683 return false
684 }
685 }
686 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
687 s = s[1:]
688 }
689 }
690
691
692 return s == ""
693 }
694
695 func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
696 if v.IsNil() {
697 e.WriteString("null")
698 return
699 }
700 e.reflectValue(v.Elem(), opts)
701 }
702
703 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
704 e.error(&UnsupportedTypeError{v.Type()})
705 }
706
707 type structEncoder struct {
708 fields structFields
709 }
710
711 type structFields struct {
712 list []field
713 byExactName map[string]*field
714 byFoldedName map[string]*field
715 }
716
717 func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
718 next := byte('{')
719 FieldLoop:
720 for i := range se.fields.list {
721 f := &se.fields.list[i]
722
723
724 fv := v
725 for _, i := range f.index {
726 if fv.Kind() == reflect.Pointer {
727 if fv.IsNil() {
728 continue FieldLoop
729 }
730 fv = fv.Elem()
731 }
732 fv = fv.Field(i)
733 }
734
735 if (f.omitEmpty && isEmptyValue(fv)) ||
736 (f.omitZero && (f.isZero == nil && fv.IsZero() || (f.isZero != nil && f.isZero(fv)))) {
737 continue
738 }
739 e.WriteByte(next)
740 next = ','
741 if opts.escapeHTML {
742 e.WriteString(f.nameEscHTML)
743 } else {
744 e.WriteString(f.nameNonEsc)
745 }
746 opts.quoted = f.quoted
747 f.encoder(e, fv, opts)
748 }
749 if next == '{' {
750 e.WriteString("{}")
751 } else {
752 e.WriteByte('}')
753 }
754 }
755
756 func newStructEncoder(t reflect.Type) encoderFunc {
757 se := structEncoder{fields: cachedTypeFields(t)}
758 return se.encode
759 }
760
761 type mapEncoder struct {
762 elemEnc encoderFunc
763 }
764
765 func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
766 if v.IsNil() {
767 e.WriteString("null")
768 return
769 }
770 if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
771
772
773 ptr := v.UnsafePointer()
774 if _, ok := e.ptrSeen[ptr]; ok {
775 e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
776 }
777 e.ptrSeen[ptr] = struct{}{}
778 defer delete(e.ptrSeen, ptr)
779 }
780 e.WriteByte('{')
781
782
783 var (
784 sv = make([]reflectWithString, v.Len())
785 mi = v.MapRange()
786 err error
787 )
788 for i := 0; mi.Next(); i++ {
789 if sv[i].ks, err = resolveKeyName(mi.Key()); err != nil {
790 e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
791 }
792 sv[i].v = mi.Value()
793 }
794 slices.SortFunc(sv, func(i, j reflectWithString) int {
795 return strings.Compare(i.ks, j.ks)
796 })
797
798 for i, kv := range sv {
799 if i > 0 {
800 e.WriteByte(',')
801 }
802 e.Write(appendString(e.AvailableBuffer(), kv.ks, opts.escapeHTML))
803 e.WriteByte(':')
804 me.elemEnc(e, kv.v, opts)
805 }
806 e.WriteByte('}')
807 e.ptrLevel--
808 }
809
810 func newMapEncoder(t reflect.Type) encoderFunc {
811 switch t.Key().Kind() {
812 case reflect.String,
813 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
814 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
815 default:
816 if !t.Key().Implements(textMarshalerType) {
817 return unsupportedTypeEncoder
818 }
819 }
820 me := mapEncoder{typeEncoder(t.Elem())}
821 return me.encode
822 }
823
824 func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
825 if v.IsNil() {
826 e.WriteString("null")
827 return
828 }
829
830 s := v.Bytes()
831 b := e.AvailableBuffer()
832 b = append(b, '"')
833 b = base64.StdEncoding.AppendEncode(b, s)
834 b = append(b, '"')
835 e.Write(b)
836 }
837
838
839 type sliceEncoder struct {
840 arrayEnc encoderFunc
841 }
842
843 func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
844 if v.IsNil() {
845 e.WriteString("null")
846 return
847 }
848 if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
849
850
851
852
853 ptr := struct {
854 ptr any
855 len int
856 }{v.UnsafePointer(), v.Len()}
857 if _, ok := e.ptrSeen[ptr]; ok {
858 e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
859 }
860 e.ptrSeen[ptr] = struct{}{}
861 defer delete(e.ptrSeen, ptr)
862 }
863 se.arrayEnc(e, v, opts)
864 e.ptrLevel--
865 }
866
867 func newSliceEncoder(t reflect.Type) encoderFunc {
868
869 if t.Elem().Kind() == reflect.Uint8 {
870 p := reflect.PointerTo(t.Elem())
871 if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
872 return encodeByteSlice
873 }
874 }
875 enc := sliceEncoder{newArrayEncoder(t)}
876 return enc.encode
877 }
878
879 type arrayEncoder struct {
880 elemEnc encoderFunc
881 }
882
883 func (ae arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
884 e.WriteByte('[')
885 n := v.Len()
886 for i := 0; i < n; i++ {
887 if i > 0 {
888 e.WriteByte(',')
889 }
890 ae.elemEnc(e, v.Index(i), opts)
891 }
892 e.WriteByte(']')
893 }
894
895 func newArrayEncoder(t reflect.Type) encoderFunc {
896 enc := arrayEncoder{typeEncoder(t.Elem())}
897 return enc.encode
898 }
899
900 type ptrEncoder struct {
901 elemEnc encoderFunc
902 }
903
904 func (pe ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
905 if v.IsNil() {
906 e.WriteString("null")
907 return
908 }
909 if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
910
911
912 ptr := v.Interface()
913 if _, ok := e.ptrSeen[ptr]; ok {
914 e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
915 }
916 e.ptrSeen[ptr] = struct{}{}
917 defer delete(e.ptrSeen, ptr)
918 }
919 pe.elemEnc(e, v.Elem(), opts)
920 e.ptrLevel--
921 }
922
923 func newPtrEncoder(t reflect.Type) encoderFunc {
924 enc := ptrEncoder{typeEncoder(t.Elem())}
925 return enc.encode
926 }
927
928 type condAddrEncoder struct {
929 canAddrEnc, elseEnc encoderFunc
930 }
931
932 func (ce condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
933 if v.CanAddr() {
934 ce.canAddrEnc(e, v, opts)
935 } else {
936 ce.elseEnc(e, v, opts)
937 }
938 }
939
940
941
942 func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
943 enc := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
944 return enc.encode
945 }
946
947 func isValidTag(s string) bool {
948 if s == "" {
949 return false
950 }
951 for _, c := range s {
952 switch {
953 case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
954
955
956
957 case !unicode.IsLetter(c) && !unicode.IsDigit(c):
958 return false
959 }
960 }
961 return true
962 }
963
964 func typeByIndex(t reflect.Type, index []int) reflect.Type {
965 for _, i := range index {
966 if t.Kind() == reflect.Pointer {
967 t = t.Elem()
968 }
969 t = t.Field(i).Type
970 }
971 return t
972 }
973
974 type reflectWithString struct {
975 v reflect.Value
976 ks string
977 }
978
979 func resolveKeyName(k reflect.Value) (string, error) {
980 if k.Kind() == reflect.String {
981 return k.String(), nil
982 }
983 if tm, ok := reflect.TypeAssert[encoding.TextMarshaler](k); ok {
984 if k.Kind() == reflect.Pointer && k.IsNil() {
985 return "", nil
986 }
987 buf, err := tm.MarshalText()
988 return string(buf), err
989 }
990 switch k.Kind() {
991 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
992 return strconv.FormatInt(k.Int(), 10), nil
993 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
994 return strconv.FormatUint(k.Uint(), 10), nil
995 }
996 panic("unexpected map key type")
997 }
998
999 func appendString[Bytes []byte | string](dst []byte, src Bytes, escapeHTML bool) []byte {
1000 dst = append(dst, '"')
1001 start := 0
1002 for i := 0; i < len(src); {
1003 if b := src[i]; b < utf8.RuneSelf {
1004 if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
1005 i++
1006 continue
1007 }
1008 dst = append(dst, src[start:i]...)
1009 switch b {
1010 case '\\', '"':
1011 dst = append(dst, '\\', b)
1012 case '\b':
1013 dst = append(dst, '\\', 'b')
1014 case '\f':
1015 dst = append(dst, '\\', 'f')
1016 case '\n':
1017 dst = append(dst, '\\', 'n')
1018 case '\r':
1019 dst = append(dst, '\\', 'r')
1020 case '\t':
1021 dst = append(dst, '\\', 't')
1022 default:
1023
1024
1025
1026
1027
1028 dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
1029 }
1030 i++
1031 start = i
1032 continue
1033 }
1034
1035
1036
1037
1038 n := min(len(src)-i, utf8.UTFMax)
1039 c, size := utf8.DecodeRuneInString(string(src[i : i+n]))
1040 if c == utf8.RuneError && size == 1 {
1041 dst = append(dst, src[start:i]...)
1042 dst = append(dst, `\ufffd`...)
1043 i += size
1044 start = i
1045 continue
1046 }
1047
1048
1049
1050
1051
1052
1053
1054 if c == '\u2028' || c == '\u2029' {
1055 dst = append(dst, src[start:i]...)
1056 dst = append(dst, '\\', 'u', '2', '0', '2', hex[c&0xF])
1057 i += size
1058 start = i
1059 continue
1060 }
1061 i += size
1062 }
1063 dst = append(dst, src[start:]...)
1064 dst = append(dst, '"')
1065 return dst
1066 }
1067
1068
1069 type field struct {
1070 name string
1071 nameBytes []byte
1072
1073 nameNonEsc string
1074 nameEscHTML string
1075
1076 tag bool
1077 index []int
1078 typ reflect.Type
1079 omitEmpty bool
1080 omitZero bool
1081 isZero func(reflect.Value) bool
1082 quoted bool
1083
1084 encoder encoderFunc
1085 }
1086
1087 type isZeroer interface {
1088 IsZero() bool
1089 }
1090
1091 var isZeroerType = reflect.TypeFor[isZeroer]()
1092
1093 func typeFields(t reflect.Type) structFields {
1094
1095 current := []field{}
1096 next := []field{{typ: t}}
1097
1098
1099 var count, nextCount map[reflect.Type]int
1100
1101
1102 visited := map[reflect.Type]bool{}
1103
1104
1105 var fields []field
1106
1107
1108 var nameEscBuf []byte
1109
1110 for len(next) > 0 {
1111 current, next = next, current[:0]
1112 count, nextCount = nextCount, map[reflect.Type]int{}
1113
1114 for _, f := range current {
1115 if visited[f.typ] {
1116 continue
1117 }
1118 visited[f.typ] = true
1119
1120
1121 for i := 0; i < f.typ.NumField(); i++ {
1122 sf := f.typ.Field(i)
1123 if sf.Anonymous {
1124 t := sf.Type
1125 if t.Kind() == reflect.Pointer {
1126 t = t.Elem()
1127 }
1128 if !sf.IsExported() && t.Kind() != reflect.Struct {
1129
1130 continue
1131 }
1132
1133
1134 } else if !sf.IsExported() {
1135
1136 continue
1137 }
1138 tag := sf.Tag.Get("json")
1139 if tag == "-" {
1140 continue
1141 }
1142 name, opts := parseTag(tag)
1143 if !isValidTag(name) {
1144 name = ""
1145 }
1146 index := make([]int, len(f.index)+1)
1147 copy(index, f.index)
1148 index[len(f.index)] = i
1149
1150 ft := sf.Type
1151 if ft.Name() == "" && ft.Kind() == reflect.Pointer {
1152
1153 ft = ft.Elem()
1154 }
1155
1156
1157 quoted := false
1158 if opts.Contains("string") {
1159 switch ft.Kind() {
1160 case reflect.Bool,
1161 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1162 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
1163 reflect.Float32, reflect.Float64,
1164 reflect.String:
1165 quoted = true
1166 }
1167 }
1168
1169
1170 if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
1171 tagged := name != ""
1172 if name == "" {
1173 name = sf.Name
1174 }
1175 field := field{
1176 name: name,
1177 tag: tagged,
1178 index: index,
1179 typ: ft,
1180 omitEmpty: opts.Contains("omitempty"),
1181 omitZero: opts.Contains("omitzero"),
1182 quoted: quoted,
1183 }
1184 field.nameBytes = []byte(field.name)
1185
1186
1187 nameEscBuf = appendHTMLEscape(nameEscBuf[:0], field.nameBytes)
1188 field.nameEscHTML = `"` + string(nameEscBuf) + `":`
1189 field.nameNonEsc = `"` + field.name + `":`
1190
1191 if field.omitZero {
1192 t := sf.Type
1193
1194 switch {
1195 case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
1196 field.isZero = func(v reflect.Value) bool {
1197
1198
1199 return v.IsNil() ||
1200 (v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
1201 v.Interface().(isZeroer).IsZero()
1202 }
1203 case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
1204 field.isZero = func(v reflect.Value) bool {
1205
1206 return v.IsNil() || v.Interface().(isZeroer).IsZero()
1207 }
1208 case t.Implements(isZeroerType):
1209 field.isZero = func(v reflect.Value) bool {
1210 return v.Interface().(isZeroer).IsZero()
1211 }
1212 case reflect.PointerTo(t).Implements(isZeroerType):
1213 field.isZero = func(v reflect.Value) bool {
1214 if !v.CanAddr() {
1215
1216 v2 := reflect.New(v.Type()).Elem()
1217 v2.Set(v)
1218 v = v2
1219 }
1220 return v.Addr().Interface().(isZeroer).IsZero()
1221 }
1222 }
1223 }
1224
1225 fields = append(fields, field)
1226 if count[f.typ] > 1 {
1227
1228
1229
1230
1231 fields = append(fields, fields[len(fields)-1])
1232 }
1233 continue
1234 }
1235
1236
1237 nextCount[ft]++
1238 if nextCount[ft] == 1 {
1239 next = append(next, field{name: ft.Name(), index: index, typ: ft})
1240 }
1241 }
1242 }
1243 }
1244
1245 slices.SortFunc(fields, func(a, b field) int {
1246
1247
1248
1249 if c := strings.Compare(a.name, b.name); c != 0 {
1250 return c
1251 }
1252 if c := cmp.Compare(len(a.index), len(b.index)); c != 0 {
1253 return c
1254 }
1255 if a.tag != b.tag {
1256 if a.tag {
1257 return -1
1258 }
1259 return +1
1260 }
1261 return slices.Compare(a.index, b.index)
1262 })
1263
1264
1265
1266
1267
1268
1269
1270 out := fields[:0]
1271 for advance, i := 0, 0; i < len(fields); i += advance {
1272
1273
1274 fi := fields[i]
1275 name := fi.name
1276 for advance = 1; i+advance < len(fields); advance++ {
1277 fj := fields[i+advance]
1278 if fj.name != name {
1279 break
1280 }
1281 }
1282 if advance == 1 {
1283 out = append(out, fi)
1284 continue
1285 }
1286 dominant, ok := dominantField(fields[i : i+advance])
1287 if ok {
1288 out = append(out, dominant)
1289 }
1290 }
1291
1292 fields = out
1293 slices.SortFunc(fields, func(i, j field) int {
1294 return slices.Compare(i.index, j.index)
1295 })
1296
1297 for i := range fields {
1298 f := &fields[i]
1299 f.encoder = typeEncoder(typeByIndex(t, f.index))
1300 }
1301 exactNameIndex := make(map[string]*field, len(fields))
1302 foldedNameIndex := make(map[string]*field, len(fields))
1303 for i, field := range fields {
1304 exactNameIndex[field.name] = &fields[i]
1305
1306 if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
1307 foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
1308 }
1309 }
1310 return structFields{fields, exactNameIndex, foldedNameIndex}
1311 }
1312
1313
1314
1315
1316
1317
1318
1319 func dominantField(fields []field) (field, bool) {
1320
1321
1322
1323 if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
1324 return field{}, false
1325 }
1326 return fields[0], true
1327 }
1328
1329 var fieldCache sync.Map
1330
1331
1332 func cachedTypeFields(t reflect.Type) structFields {
1333 if f, ok := fieldCache.Load(t); ok {
1334 return f.(structFields)
1335 }
1336 f, _ := fieldCache.LoadOrStore(t, typeFields(t))
1337 return f.(structFields)
1338 }
1339
1340 func mayAppendQuote(b []byte, quoted bool) []byte {
1341 if quoted {
1342 b = append(b, '"')
1343 }
1344 return b
1345 }
1346
View as plain text