reflect_struct_encoder.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package jsoniter
  2. import (
  3. "fmt"
  4. "github.com/modern-go/reflect2"
  5. "io"
  6. "reflect"
  7. "unsafe"
  8. )
  9. func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder {
  10. type bindingTo struct {
  11. binding *Binding
  12. toName string
  13. ignored bool
  14. }
  15. orderedBindings := []*bindingTo{}
  16. structDescriptor := describeStruct(ctx, typ)
  17. for _, binding := range structDescriptor.Fields {
  18. for _, toName := range binding.ToNames {
  19. new := &bindingTo{
  20. binding: binding,
  21. toName: toName,
  22. }
  23. for _, old := range orderedBindings {
  24. if old.toName != toName {
  25. continue
  26. }
  27. old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding)
  28. }
  29. orderedBindings = append(orderedBindings, new)
  30. }
  31. }
  32. if len(orderedBindings) == 0 {
  33. return &emptyStructEncoder{}
  34. }
  35. finalOrderedFields := []structFieldTo{}
  36. for _, bindingTo := range orderedBindings {
  37. if !bindingTo.ignored {
  38. finalOrderedFields = append(finalOrderedFields, structFieldTo{
  39. encoder: bindingTo.binding.Encoder.(*structFieldEncoder),
  40. toName: bindingTo.toName,
  41. })
  42. }
  43. }
  44. return &structEncoder{typ, finalOrderedFields}
  45. }
  46. func createCheckIsEmpty(ctx *ctx, typ reflect2.Type) checkIsEmpty {
  47. encoder := createEncoderOfNative(ctx, typ)
  48. if encoder != nil {
  49. return encoder
  50. }
  51. kind := typ.Kind()
  52. switch kind {
  53. case reflect.Interface:
  54. return &dynamicEncoder{typ}
  55. case reflect.Struct:
  56. return &structEncoder{typ: typ}
  57. case reflect.Array:
  58. return &arrayEncoder{}
  59. case reflect.Slice:
  60. return &sliceEncoder{}
  61. case reflect.Map:
  62. return encoderOfMap(ctx, typ)
  63. case reflect.Ptr:
  64. return &OptionalEncoder{}
  65. default:
  66. return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)}
  67. }
  68. }
  69. func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) {
  70. newTagged := new.Field.Tag().Get(cfg.getTagKey()) != ""
  71. oldTagged := old.Field.Tag().Get(cfg.getTagKey()) != ""
  72. if newTagged {
  73. if oldTagged {
  74. if len(old.levels) > len(new.levels) {
  75. return true, false
  76. } else if len(new.levels) > len(old.levels) {
  77. return false, true
  78. } else {
  79. return true, true
  80. }
  81. } else {
  82. return true, false
  83. }
  84. } else {
  85. if oldTagged {
  86. return true, false
  87. }
  88. if len(old.levels) > len(new.levels) {
  89. return true, false
  90. } else if len(new.levels) > len(old.levels) {
  91. return false, true
  92. } else {
  93. return true, true
  94. }
  95. }
  96. }
  97. type structFieldEncoder struct {
  98. field reflect2.StructField
  99. fieldEncoder ValEncoder
  100. omitempty bool
  101. }
  102. func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  103. fieldPtr := encoder.field.UnsafeGet(ptr)
  104. encoder.fieldEncoder.Encode(fieldPtr, stream)
  105. if stream.Error != nil && stream.Error != io.EOF {
  106. stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error())
  107. }
  108. }
  109. func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  110. fieldPtr := encoder.field.UnsafeGet(ptr)
  111. return encoder.fieldEncoder.IsEmpty(fieldPtr)
  112. }
  113. func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
  114. isEmbeddedPtrNil, converted := encoder.fieldEncoder.(IsEmbeddedPtrNil)
  115. if !converted {
  116. return false
  117. }
  118. fieldPtr := encoder.field.UnsafeGet(ptr)
  119. return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
  120. }
  121. type IsEmbeddedPtrNil interface {
  122. IsEmbeddedPtrNil(ptr unsafe.Pointer) bool
  123. }
  124. type structEncoder struct {
  125. typ reflect2.Type
  126. fields []structFieldTo
  127. }
  128. type structFieldTo struct {
  129. encoder *structFieldEncoder
  130. toName string
  131. }
  132. func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  133. stream.WriteObjectStart()
  134. isNotFirst := false
  135. for _, field := range encoder.fields {
  136. if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
  137. continue
  138. }
  139. if field.encoder.IsEmbeddedPtrNil(ptr) {
  140. continue
  141. }
  142. if isNotFirst {
  143. stream.WriteMore()
  144. }
  145. stream.WriteObjectField(field.toName)
  146. field.encoder.Encode(ptr, stream)
  147. isNotFirst = true
  148. }
  149. stream.WriteObjectEnd()
  150. if stream.Error != nil && stream.Error != io.EOF {
  151. stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error())
  152. }
  153. }
  154. func (encoder *structEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  155. return false
  156. }
  157. type emptyStructEncoder struct {
  158. }
  159. func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  160. stream.WriteEmptyObject()
  161. }
  162. func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  163. return false
  164. }
  165. type stringModeNumberEncoder struct {
  166. elemEncoder ValEncoder
  167. }
  168. func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  169. stream.writeByte('"')
  170. encoder.elemEncoder.Encode(ptr, stream)
  171. stream.writeByte('"')
  172. }
  173. func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  174. return encoder.elemEncoder.IsEmpty(ptr)
  175. }
  176. type stringModeStringEncoder struct {
  177. elemEncoder ValEncoder
  178. cfg *frozenConfig
  179. }
  180. func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  181. tempStream := encoder.cfg.BorrowStream(nil)
  182. tempStream.Attachment = stream.Attachment
  183. defer encoder.cfg.ReturnStream(tempStream)
  184. encoder.elemEncoder.Encode(ptr, tempStream)
  185. stream.WriteString(string(tempStream.Buffer()))
  186. }
  187. func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  188. return encoder.elemEncoder.IsEmpty(ptr)
  189. }