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