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