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