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