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