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