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 := len(src) - i
1019 if n > utf8.UTFMax {
1020 n = utf8.UTFMax
1021 }
1022 c, size := utf8.DecodeRuneInString(string(src[i : i+n]))
1023 if c == utf8.RuneError && size == 1 {
1024 dst = append(dst, src[start:i]...)
1025 dst = append(dst, `\ufffd`...)
1026 i += size
1027 start = i
1028 continue
1029 }
1030
1031
1032
1033
1034
1035
1036
1037 if c == '\u2028' || c == '\u2029' {
1038 dst = append(dst, src[start:i]...)
1039 dst = append(dst, '\\', 'u', '2', '0', '2', hex[c&0xF])
1040 i += size
1041 start = i
1042 continue
1043 }
1044 i += size
1045 }
1046 dst = append(dst, src[start:]...)
1047 dst = append(dst, '"')
1048 return dst
1049 }
1050
1051
1052 type field struct {
1053 name string
1054 nameBytes []byte
1055
1056 nameNonEsc string
1057 nameEscHTML string
1058
1059 tag bool
1060 index []int
1061 typ reflect.Type
1062 omitEmpty bool
1063 omitZero bool
1064 isZero func(reflect.Value) bool
1065 quoted bool
1066
1067 encoder encoderFunc
1068 }
1069
1070 type isZeroer interface {
1071 IsZero() bool
1072 }
1073
1074 var isZeroerType = reflect.TypeFor[isZeroer]()
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 func typeFields(t reflect.Type) structFields {
1090
1091 current := []field{}
1092 next := []field{{typ: t}}
1093
1094
1095 var count, nextCount map[reflect.Type]int
1096
1097
1098 visited := map[reflect.Type]bool{}
1099
1100
1101 var fields []field
1102
1103
1104 var nameEscBuf []byte
1105
1106 for len(next) > 0 {
1107 current, next = next, current[:0]
1108 count, nextCount = nextCount, map[reflect.Type]int{}
1109
1110 for _, f := range current {
1111 if visited[f.typ] {
1112 continue
1113 }
1114 visited[f.typ] = true
1115
1116
1117 for i := 0; i < f.typ.NumField(); i++ {
1118 sf := f.typ.Field(i)
1119 if sf.Anonymous {
1120 t := sf.Type
1121 if t.Kind() == reflect.Pointer {
1122 t = t.Elem()
1123 }
1124 if !sf.IsExported() && t.Kind() != reflect.Struct {
1125
1126 continue
1127 }
1128
1129
1130 } else if !sf.IsExported() {
1131
1132 continue
1133 }
1134 tag := sf.Tag.Get("json")
1135 if tag == "-" {
1136 continue
1137 }
1138 name, opts := parseTag(tag)
1139 if !isValidTag(name) {
1140 name = ""
1141 }
1142 index := make([]int, len(f.index)+1)
1143 copy(index, f.index)
1144 index[len(f.index)] = i
1145
1146 ft := sf.Type
1147 if ft.Name() == "" && ft.Kind() == reflect.Pointer {
1148
1149 ft = ft.Elem()
1150 }
1151
1152
1153 quoted := false
1154 if opts.Contains("string") {
1155 switch ft.Kind() {
1156 case reflect.Bool,
1157 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1158 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
1159 reflect.Float32, reflect.Float64,
1160 reflect.String:
1161 quoted = true
1162 }
1163 }
1164
1165
1166 if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
1167 tagged := name != ""
1168 if name == "" {
1169 name = sf.Name
1170 }
1171 field := field{
1172 name: name,
1173 tag: tagged,
1174 index: index,
1175 typ: ft,
1176 omitEmpty: opts.Contains("omitempty"),
1177 omitZero: opts.Contains("omitzero"),
1178 quoted: quoted,
1179 }
1180 field.nameBytes = []byte(field.name)
1181
1182
1183 nameEscBuf = appendHTMLEscape(nameEscBuf[:0], field.nameBytes)
1184 field.nameEscHTML = `"` + string(nameEscBuf) + `":`
1185 field.nameNonEsc = `"` + field.name + `":`
1186
1187 if field.omitZero {
1188 t := sf.Type
1189
1190 switch {
1191 case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
1192 field.isZero = func(v reflect.Value) bool {
1193
1194
1195 return v.IsNil() ||
1196 (v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
1197 v.Interface().(isZeroer).IsZero()
1198 }
1199 case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
1200 field.isZero = func(v reflect.Value) bool {
1201
1202 return v.IsNil() || v.Interface().(isZeroer).IsZero()
1203 }
1204 case t.Implements(isZeroerType):
1205 field.isZero = func(v reflect.Value) bool {
1206 return v.Interface().(isZeroer).IsZero()
1207 }
1208 case reflect.PointerTo(t).Implements(isZeroerType):
1209 field.isZero = func(v reflect.Value) bool {
1210 if !v.CanAddr() {
1211
1212 v2 := reflect.New(v.Type()).Elem()
1213 v2.Set(v)
1214 v = v2
1215 }
1216 return v.Addr().Interface().(isZeroer).IsZero()
1217 }
1218 }
1219 }
1220
1221 fields = append(fields, field)
1222 if count[f.typ] > 1 {
1223
1224
1225
1226
1227 fields = append(fields, fields[len(fields)-1])
1228 }
1229 continue
1230 }
1231
1232
1233 nextCount[ft]++
1234 if nextCount[ft] == 1 {
1235 next = append(next, field{name: ft.Name(), index: index, typ: ft})
1236 }
1237 }
1238 }
1239 }
1240
1241 slices.SortFunc(fields, func(a, b field) int {
1242
1243
1244
1245 if c := strings.Compare(a.name, b.name); c != 0 {
1246 return c
1247 }
1248 if c := cmp.Compare(len(a.index), len(b.index)); c != 0 {
1249 return c
1250 }
1251 if a.tag != b.tag {
1252 if a.tag {
1253 return -1
1254 }
1255 return +1
1256 }
1257 return slices.Compare(a.index, b.index)
1258 })
1259
1260
1261
1262
1263
1264
1265
1266 out := fields[:0]
1267 for advance, i := 0, 0; i < len(fields); i += advance {
1268
1269
1270 fi := fields[i]
1271 name := fi.name
1272 for advance = 1; i+advance < len(fields); advance++ {
1273 fj := fields[i+advance]
1274 if fj.name != name {
1275 break
1276 }
1277 }
1278 if advance == 1 {
1279 out = append(out, fi)
1280 continue
1281 }
1282 dominant, ok := dominantField(fields[i : i+advance])
1283 if ok {
1284 out = append(out, dominant)
1285 }
1286 }
1287
1288 fields = out
1289 slices.SortFunc(fields, func(i, j field) int {
1290 return slices.Compare(i.index, j.index)
1291 })
1292
1293 for i := range fields {
1294 f := &fields[i]
1295 f.encoder = typeEncoder(typeByIndex(t, f.index))
1296 }
1297 exactNameIndex := make(map[string]*field, len(fields))
1298 foldedNameIndex := make(map[string]*field, len(fields))
1299 for i, field := range fields {
1300 exactNameIndex[field.name] = &fields[i]
1301
1302 if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
1303 foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
1304 }
1305 }
1306 return structFields{fields, exactNameIndex, foldedNameIndex}
1307 }
1308
1309
1310
1311
1312
1313
1314
1315 func dominantField(fields []field) (field, bool) {
1316
1317
1318
1319 if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
1320 return field{}, false
1321 }
1322 return fields[0], true
1323 }
1324
1325 var fieldCache sync.Map
1326
1327
1328 func cachedTypeFields(t reflect.Type) structFields {
1329 if f, ok := fieldCache.Load(t); ok {
1330 return f.(structFields)
1331 }
1332 f, _ := fieldCache.LoadOrStore(t, typeFields(t))
1333 return f.(structFields)
1334 }
1335
1336 func mayAppendQuote(b []byte, quoted bool) []byte {
1337 if quoted {
1338 b = append(b, '"')
1339 }
1340 return b
1341 }
1342
View as plain text