You've already forked json-iterator
mirror of
https://github.com/json-iterator/go.git
synced 2025-08-13 22:12:45 +02:00
support recursive struct
This commit is contained in:
4
any.go
4
any.go
@@ -247,7 +247,7 @@ func locatePath(iter *Iterator, path []interface{}) Any {
|
||||
|
||||
var anyType = reflect.TypeOf((*Any)(nil)).Elem()
|
||||
|
||||
func createDecoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func createDecoderOfAny(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
if typ == anyType {
|
||||
return &directAnyCodec{}
|
||||
}
|
||||
@@ -259,7 +259,7 @@ func createDecoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValD
|
||||
return nil
|
||||
}
|
||||
|
||||
func createEncoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func createEncoderOfAny(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
if typ == anyType {
|
||||
return &directAnyCodec{}
|
||||
}
|
||||
|
139
reflect.go
139
reflect.go
@@ -33,6 +33,22 @@ type checkIsEmpty interface {
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
}
|
||||
|
||||
type ctx struct {
|
||||
*frozenConfig
|
||||
prefix string
|
||||
encoders map[reflect.Type]ValEncoder
|
||||
decoders map[reflect.Type]ValDecoder
|
||||
}
|
||||
|
||||
func (b *ctx) append(prefix string) *ctx {
|
||||
return &ctx{
|
||||
frozenConfig: b.frozenConfig,
|
||||
prefix: b.prefix + " " + prefix,
|
||||
encoders: b.encoders,
|
||||
decoders: b.decoders,
|
||||
}
|
||||
}
|
||||
|
||||
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
|
||||
func (iter *Iterator) ReadVal(obj interface{}) {
|
||||
typ := reflect.TypeOf(obj)
|
||||
@@ -66,44 +82,62 @@ func (cfg *frozenConfig) DecoderOf(typ reflect.Type) ValDecoder {
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = decoderOfType(cfg, "", typ.Elem())
|
||||
ctx := &ctx{
|
||||
frozenConfig: cfg,
|
||||
prefix: "",
|
||||
decoders: map[reflect.Type]ValDecoder{},
|
||||
encoders: map[reflect.Type]ValEncoder{},
|
||||
}
|
||||
decoder = decoderOfType(ctx, typ.Elem())
|
||||
cfg.addDecoderToCache(cacheKey, decoder)
|
||||
return decoder
|
||||
}
|
||||
|
||||
func decoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
decoder := getTypeDecoderFromExtension(cfg, typ)
|
||||
func decoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
decoder := getTypeDecoderFromExtension(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfType(cfg, prefix, typ)
|
||||
decoder = createDecoderOfType(ctx, typ)
|
||||
for _, extension := range extensions {
|
||||
decoder = extension.DecorateDecoder(typ, decoder)
|
||||
}
|
||||
for _, extension := range cfg.extensions {
|
||||
for _, extension := range ctx.extensions {
|
||||
decoder = extension.DecorateDecoder(typ, decoder)
|
||||
}
|
||||
return decoder
|
||||
}
|
||||
|
||||
func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
decoder := createDecoderOfJsonRawMessage(cfg, prefix, typ)
|
||||
func createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
decoder := ctx.decoders[typ]
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfJsonNumber(cfg, prefix, typ)
|
||||
placeholder := &placeholderDecoder{}
|
||||
ctx.decoders[typ] = placeholder
|
||||
decoder = _createDecoderOfType(ctx, typ)
|
||||
placeholder.decoder = decoder
|
||||
return decoder
|
||||
}
|
||||
|
||||
func _createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
decoder := createDecoderOfJsonRawMessage(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfMarshaler(cfg, prefix, typ)
|
||||
decoder = createDecoderOfJsonNumber(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfAny(cfg, prefix, typ)
|
||||
decoder = createDecoderOfMarshaler(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfNative(cfg, prefix, typ)
|
||||
decoder = createDecoderOfAny(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
decoder = createDecoderOfNative(ctx, typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
@@ -115,17 +149,17 @@ func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val
|
||||
}
|
||||
return &efaceDecoder{}
|
||||
case reflect.Struct:
|
||||
return decoderOfStruct(cfg, prefix, typ)
|
||||
return decoderOfStruct(ctx, typ)
|
||||
case reflect.Array:
|
||||
return decoderOfArray(cfg, prefix, typ)
|
||||
return decoderOfArray(ctx, typ)
|
||||
case reflect.Slice:
|
||||
return decoderOfSlice(cfg, prefix, typ)
|
||||
return decoderOfSlice(ctx, typ)
|
||||
case reflect.Map:
|
||||
return decoderOfMap(cfg, prefix, typ)
|
||||
return decoderOfMap(ctx, typ)
|
||||
case reflect.Ptr:
|
||||
return decoderOfOptional(cfg, prefix, typ)
|
||||
return decoderOfOptional(ctx, typ)
|
||||
default:
|
||||
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
|
||||
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +169,13 @@ func (cfg *frozenConfig) EncoderOf(typ reflect.Type) ValEncoder {
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = encoderOfType(cfg, "", typ)
|
||||
ctx := &ctx{
|
||||
frozenConfig: cfg,
|
||||
prefix: "",
|
||||
decoders: map[reflect.Type]ValDecoder{},
|
||||
encoders: map[reflect.Type]ValEncoder{},
|
||||
}
|
||||
encoder = encoderOfType(ctx, typ)
|
||||
if shouldFixOnePtr(typ) {
|
||||
encoder = &onePtrEncoder{encoder}
|
||||
}
|
||||
@@ -159,39 +199,50 @@ func shouldFixOnePtr(typ reflect.Type) bool {
|
||||
return reflect2.Type2(typ).LikePtr()
|
||||
}
|
||||
|
||||
func encoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
encoder := getTypeEncoderFromExtension(cfg, typ)
|
||||
func encoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
encoder := getTypeEncoderFromExtension(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfType(cfg, prefix, typ)
|
||||
encoder = createEncoderOfType(ctx, typ)
|
||||
for _, extension := range extensions {
|
||||
encoder = extension.DecorateEncoder(typ, encoder)
|
||||
}
|
||||
for _, extension := range cfg.extensions {
|
||||
for _, extension := range ctx.extensions {
|
||||
encoder = extension.DecorateEncoder(typ, encoder)
|
||||
}
|
||||
return encoder
|
||||
}
|
||||
|
||||
func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
encoder := createEncoderOfJsonRawMessage(cfg, prefix, typ)
|
||||
func createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
encoder := ctx.encoders[typ]
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfJsonNumber(cfg, prefix, typ)
|
||||
placeholder := &placeholderEncoder{}
|
||||
ctx.encoders[typ] = placeholder
|
||||
encoder = _createEncoderOfType(ctx, typ)
|
||||
placeholder.encoder = encoder
|
||||
return encoder
|
||||
}
|
||||
func _createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
encoder := createEncoderOfJsonRawMessage(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfMarshaler(cfg, prefix, typ)
|
||||
encoder = createEncoderOfJsonNumber(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfAny(cfg, prefix, typ)
|
||||
encoder = createEncoderOfMarshaler(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfNative(cfg, prefix, typ)
|
||||
encoder = createEncoderOfAny(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
encoder = createEncoderOfNative(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
@@ -200,17 +251,17 @@ func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val
|
||||
case reflect.Interface:
|
||||
return &dynamicEncoder{reflect2.Type2(typ)}
|
||||
case reflect.Struct:
|
||||
return encoderOfStruct(cfg, prefix, typ)
|
||||
return encoderOfStruct(ctx, typ)
|
||||
case reflect.Array:
|
||||
return encoderOfArray(cfg, prefix, typ)
|
||||
return encoderOfArray(ctx, typ)
|
||||
case reflect.Slice:
|
||||
return encoderOfSlice(cfg, prefix, typ)
|
||||
return encoderOfSlice(ctx, typ)
|
||||
case reflect.Map:
|
||||
return encoderOfMap(cfg, prefix, typ)
|
||||
return encoderOfMap(ctx, typ)
|
||||
case reflect.Ptr:
|
||||
return encoderOfOptional(cfg, prefix, typ)
|
||||
return encoderOfOptional(ctx, typ)
|
||||
default:
|
||||
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
|
||||
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,3 +294,23 @@ func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type placeholderDecoder struct {
|
||||
decoder ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
decoder.decoder.Decode(ptr, iter)
|
||||
}
|
||||
|
||||
type placeholderEncoder struct {
|
||||
encoder ValEncoder
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
encoder.encoder.Encode(ptr, stream)
|
||||
}
|
||||
|
||||
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.encoder.IsEmpty(ptr)
|
||||
}
|
||||
|
@@ -7,16 +7,16 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
decoder := decoderOfType(cfg, prefix+"[array]->", typ.Elem())
|
||||
func decoderOfArray(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
decoder := decoderOfType(ctx.append("[arrayElem]"), typ.Elem())
|
||||
return &arrayDecoder{typ, typ.Elem(), decoder}
|
||||
}
|
||||
|
||||
func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func encoderOfArray(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
if typ.Len() == 0 {
|
||||
return emptyArrayEncoder{}
|
||||
}
|
||||
encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem())
|
||||
encoder := encoderOfType(ctx.append("[arrayElem]"), typ.Elem())
|
||||
return &arrayEncoder{typ, typ.Elem(), encoder}
|
||||
}
|
||||
|
||||
|
@@ -208,26 +208,26 @@ func RegisterExtension(extension Extension) {
|
||||
extensions = append(extensions, extension)
|
||||
}
|
||||
|
||||
func getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecoder {
|
||||
decoder := _getTypeDecoderFromExtension(cfg, typ)
|
||||
func getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
decoder := _getTypeDecoderFromExtension(ctx, typ)
|
||||
if decoder != nil {
|
||||
for _, extension := range extensions {
|
||||
decoder = extension.DecorateDecoder(typ, decoder)
|
||||
}
|
||||
for _, extension := range cfg.extensions {
|
||||
for _, extension := range ctx.extensions {
|
||||
decoder = extension.DecorateDecoder(typ, decoder)
|
||||
}
|
||||
}
|
||||
return decoder
|
||||
}
|
||||
func _getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecoder {
|
||||
func _getTypeDecoderFromExtension(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
for _, extension := range extensions {
|
||||
decoder := extension.CreateDecoder(typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
}
|
||||
for _, extension := range cfg.extensions {
|
||||
for _, extension := range ctx.extensions {
|
||||
decoder := extension.CreateDecoder(typ)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
@@ -247,27 +247,27 @@ func _getTypeDecoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValDecode
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncoder {
|
||||
encoder := _getTypeEncoderFromExtension(cfg, typ)
|
||||
func getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
encoder := _getTypeEncoderFromExtension(ctx, typ)
|
||||
if encoder != nil {
|
||||
for _, extension := range extensions {
|
||||
encoder = extension.DecorateEncoder(typ, encoder)
|
||||
}
|
||||
for _, extension := range cfg.extensions {
|
||||
for _, extension := range ctx.extensions {
|
||||
encoder = extension.DecorateEncoder(typ, encoder)
|
||||
}
|
||||
}
|
||||
return encoder
|
||||
}
|
||||
|
||||
func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncoder {
|
||||
func _getTypeEncoderFromExtension(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
for _, extension := range extensions {
|
||||
encoder := extension.CreateEncoder(typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
}
|
||||
for _, extension := range cfg.extensions {
|
||||
for _, extension := range ctx.extensions {
|
||||
encoder := extension.CreateEncoder(typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
@@ -287,13 +287,13 @@ func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncode
|
||||
return nil
|
||||
}
|
||||
|
||||
func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructDescriptor {
|
||||
func describeStruct(ctx *ctx, typ reflect.Type) *StructDescriptor {
|
||||
embeddedBindings := []*Binding{}
|
||||
bindings := []*Binding{}
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
tag, hastag := field.Tag.Lookup(cfg.getTagKey())
|
||||
if cfg.onlyTaggedField && !hastag {
|
||||
tag, hastag := field.Tag.Lookup(ctx.getTagKey())
|
||||
if ctx.onlyTaggedField && !hastag {
|
||||
continue
|
||||
}
|
||||
tagParts := strings.Split(tag, ",")
|
||||
@@ -302,7 +302,7 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
|
||||
}
|
||||
if field.Anonymous && (tag == "" || tagParts[0] == "") {
|
||||
if field.Type.Kind() == reflect.Struct {
|
||||
structDescriptor := describeStruct(cfg, prefix, field.Type)
|
||||
structDescriptor := describeStruct(ctx, field.Type)
|
||||
for _, binding := range structDescriptor.Fields {
|
||||
binding.levels = append([]int{i}, binding.levels...)
|
||||
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
|
||||
@@ -312,7 +312,7 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
|
||||
}
|
||||
continue
|
||||
} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
|
||||
structDescriptor := describeStruct(cfg, prefix, field.Type.Elem())
|
||||
structDescriptor := describeStruct(ctx, field.Type.Elem())
|
||||
for _, binding := range structDescriptor.Fields {
|
||||
binding.levels = append([]int{i}, binding.levels...)
|
||||
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
|
||||
@@ -329,11 +329,11 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
|
||||
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
|
||||
decoder := fieldDecoders[fieldCacheKey]
|
||||
if decoder == nil {
|
||||
decoder = decoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
|
||||
decoder = decoderOfType(ctx.append(field.Name), field.Type)
|
||||
}
|
||||
encoder := fieldEncoders[fieldCacheKey]
|
||||
if encoder == nil {
|
||||
encoder = encoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
|
||||
encoder = encoderOfType(ctx.append(field.Name), field.Type)
|
||||
}
|
||||
binding := &Binding{
|
||||
Field: &field,
|
||||
@@ -345,9 +345,9 @@ func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructD
|
||||
binding.levels = []int{i}
|
||||
bindings = append(bindings, binding)
|
||||
}
|
||||
return createStructDescriptor(cfg, typ, bindings, embeddedBindings)
|
||||
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
|
||||
}
|
||||
func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
|
||||
func createStructDescriptor(ctx *ctx, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
|
||||
structDescriptor := &StructDescriptor{
|
||||
Type: typ,
|
||||
Fields: bindings,
|
||||
@@ -355,10 +355,10 @@ func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Bin
|
||||
for _, extension := range extensions {
|
||||
extension.UpdateStructDescriptor(structDescriptor)
|
||||
}
|
||||
for _, extension := range cfg.extensions {
|
||||
for _, extension := range ctx.extensions {
|
||||
extension.UpdateStructDescriptor(structDescriptor)
|
||||
}
|
||||
processTags(structDescriptor, cfg)
|
||||
processTags(structDescriptor, ctx.frozenConfig)
|
||||
// merge normal & embedded bindings & sort with original order
|
||||
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
|
||||
sort.Sort(allBindings)
|
||||
|
@@ -35,7 +35,7 @@ func CastJsonNumber(val interface{}) (string, bool) {
|
||||
var jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem()
|
||||
var jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem()
|
||||
|
||||
func createDecoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func createDecoderOfJsonNumber(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
if typ.AssignableTo(jsonNumberType) {
|
||||
return &jsonNumberCodec{}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func createDecoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Typ
|
||||
return nil
|
||||
}
|
||||
|
||||
func createEncoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func createEncoderOfJsonNumber(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
if typ.AssignableTo(jsonNumberType) {
|
||||
return &jsonNumberCodec{}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
var jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
|
||||
var jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem()
|
||||
|
||||
func createEncoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
if typ == jsonRawMessageType {
|
||||
return &jsonRawMessageCodec{}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func createEncoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect
|
||||
return nil
|
||||
}
|
||||
|
||||
func createDecoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
if typ == jsonRawMessageType {
|
||||
return &jsonRawMessageCodec{}
|
||||
}
|
||||
|
@@ -8,9 +8,9 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func decoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
keyDecoder := decoderOfMapKey(cfg, prefix+" [mapKey]", typ.Key())
|
||||
elemDecoder := decoderOfType(cfg, prefix+" [mapElem]", typ.Elem())
|
||||
func decoderOfMap(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), typ.Key())
|
||||
elemDecoder := decoderOfType(ctx.append("[mapElem]"), typ.Elem())
|
||||
mapType := reflect2.Type2(typ).(*reflect2.UnsafeMapType)
|
||||
return &mapDecoder{
|
||||
mapType: mapType,
|
||||
@@ -21,25 +21,25 @@ func decoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder
|
||||
}
|
||||
}
|
||||
|
||||
func encoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
if cfg.sortMapKeys {
|
||||
func encoderOfMap(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
if ctx.sortMapKeys {
|
||||
return &sortKeysMapEncoder{
|
||||
mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType),
|
||||
keyEncoder: encoderOfMapKey(cfg, prefix+" [mapKey]", typ.Key()),
|
||||
elemEncoder: encoderOfType(cfg, prefix+" [mapElem]", typ.Elem()),
|
||||
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), typ.Key()),
|
||||
elemEncoder: encoderOfType(ctx.append("[mapElem]"), typ.Elem()),
|
||||
}
|
||||
}
|
||||
return &mapEncoder{
|
||||
mapType: reflect2.Type2(typ).(*reflect2.UnsafeMapType),
|
||||
keyEncoder: encoderOfMapKey(cfg, prefix+" [mapKey]", typ.Key()),
|
||||
elemEncoder: encoderOfType(cfg, prefix+" [mapElem]", typ.Elem()),
|
||||
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), typ.Key()),
|
||||
elemEncoder: encoderOfType(ctx.append("[mapElem]"), typ.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
func decoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func decoderOfMapKey(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
return decoderOfType(cfg, prefix, reflect2.DefaultTypeOfKind(reflect.String).Type1())
|
||||
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String).Type1())
|
||||
case reflect.Bool,
|
||||
reflect.Uint8, reflect.Int8,
|
||||
reflect.Uint16, reflect.Int16,
|
||||
@@ -49,7 +49,7 @@ func decoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
|
||||
reflect.Float32, reflect.Float64,
|
||||
reflect.Uintptr:
|
||||
typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1()
|
||||
return &numericMapKeyDecoder{decoderOfType(cfg, prefix, typ)}
|
||||
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
|
||||
default:
|
||||
ptrType := reflect.PtrTo(typ)
|
||||
if ptrType.Implements(textMarshalerType) {
|
||||
@@ -68,10 +68,10 @@ func decoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
|
||||
}
|
||||
}
|
||||
|
||||
func encoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func encoderOfMapKey(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
return encoderOfType(cfg, prefix, reflect2.DefaultTypeOfKind(reflect.String).Type1())
|
||||
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String).Type1())
|
||||
case reflect.Bool,
|
||||
reflect.Uint8, reflect.Int8,
|
||||
reflect.Uint16, reflect.Int16,
|
||||
@@ -81,17 +81,17 @@ func encoderOfMapKey(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
|
||||
reflect.Float32, reflect.Float64,
|
||||
reflect.Uintptr:
|
||||
typ = reflect2.DefaultTypeOfKind(typ.Kind()).Type1()
|
||||
return &numericMapKeyEncoder{encoderOfType(cfg, prefix, typ)}
|
||||
return &numericMapKeyEncoder{encoderOfType(ctx, typ)}
|
||||
default:
|
||||
if typ == textMarshalerType {
|
||||
return &directTextMarshalerEncoder{
|
||||
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")),
|
||||
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
|
||||
}
|
||||
}
|
||||
if typ.Implements(textMarshalerType) {
|
||||
return &textMarshalerEncoder{
|
||||
valType: reflect2.Type2(typ),
|
||||
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")),
|
||||
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
|
||||
}
|
||||
}
|
||||
return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
|
||||
|
@@ -13,7 +13,7 @@ var unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
|
||||
func createDecoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func createDecoderOfMarshaler(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
ptrType := reflect.PtrTo(typ)
|
||||
if ptrType.Implements(unmarshalerType) {
|
||||
return &referenceDecoder{
|
||||
@@ -28,16 +28,16 @@ func createDecoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type
|
||||
return nil
|
||||
}
|
||||
|
||||
func createEncoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func createEncoderOfMarshaler(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
if typ == marshalerType {
|
||||
checkIsEmpty := createCheckIsEmpty(cfg, typ)
|
||||
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
||||
var encoder ValEncoder = &directMarshalerEncoder{
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
}
|
||||
return encoder
|
||||
}
|
||||
if typ.Implements(marshalerType) {
|
||||
checkIsEmpty := createCheckIsEmpty(cfg, typ)
|
||||
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
||||
var encoder ValEncoder = &marshalerEncoder{
|
||||
valType: reflect2.Type2(typ),
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
@@ -45,8 +45,8 @@ func createEncoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type
|
||||
return encoder
|
||||
}
|
||||
ptrType := reflect.PtrTo(typ)
|
||||
if prefix != "" && ptrType.Implements(marshalerType) {
|
||||
checkIsEmpty := createCheckIsEmpty(cfg, ptrType)
|
||||
if ctx.prefix != "" && ptrType.Implements(marshalerType) {
|
||||
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
|
||||
var encoder ValEncoder = &marshalerEncoder{
|
||||
valType: reflect2.Type2(ptrType),
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
@@ -54,28 +54,28 @@ func createEncoderOfMarshaler(cfg *frozenConfig, prefix string, typ reflect.Type
|
||||
return &referenceEncoder{encoder}
|
||||
}
|
||||
if typ == textMarshalerType {
|
||||
checkIsEmpty := createCheckIsEmpty(cfg, typ)
|
||||
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
||||
var encoder ValEncoder = &directTextMarshalerEncoder{
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")),
|
||||
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
|
||||
}
|
||||
return encoder
|
||||
}
|
||||
if typ.Implements(textMarshalerType) {
|
||||
checkIsEmpty := createCheckIsEmpty(cfg, typ)
|
||||
checkIsEmpty := createCheckIsEmpty(ctx, typ)
|
||||
var encoder ValEncoder = &textMarshalerEncoder{
|
||||
valType: reflect2.Type2(typ),
|
||||
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")),
|
||||
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
}
|
||||
return encoder
|
||||
}
|
||||
// if prefix is empty, the type is the root type
|
||||
if prefix != "" && ptrType.Implements(textMarshalerType) {
|
||||
checkIsEmpty := createCheckIsEmpty(cfg, ptrType)
|
||||
if ctx.prefix != "" && ptrType.Implements(textMarshalerType) {
|
||||
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
|
||||
var encoder ValEncoder = &textMarshalerEncoder{
|
||||
valType: reflect2.Type2(ptrType),
|
||||
stringEncoder: cfg.EncoderOf(reflect.TypeOf("")),
|
||||
stringEncoder: ctx.EncoderOf(reflect.TypeOf("")),
|
||||
checkIsEmpty: checkIsEmpty,
|
||||
}
|
||||
return &referenceEncoder{encoder}
|
||||
|
@@ -7,9 +7,9 @@ import (
|
||||
"github.com/v2pro/plz/reflect2"
|
||||
)
|
||||
|
||||
func createEncoderOfNative(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func createEncoderOfNative(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
||||
sliceDecoder := decoderOfSlice(cfg, prefix, typ)
|
||||
sliceDecoder := decoderOfSlice(ctx, typ)
|
||||
return &base64Codec{sliceDecoder: sliceDecoder}
|
||||
}
|
||||
typeName := typ.String()
|
||||
@@ -17,163 +17,163 @@ func createEncoderOfNative(cfg *frozenConfig, prefix string, typ reflect.Type) V
|
||||
switch kind {
|
||||
case reflect.String:
|
||||
if typeName != "string" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*string)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*string)(nil)).Elem())
|
||||
}
|
||||
return &stringCodec{}
|
||||
case reflect.Int:
|
||||
if typeName != "int" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*int)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*int)(nil)).Elem())
|
||||
}
|
||||
return &intCodec{}
|
||||
case reflect.Int8:
|
||||
if typeName != "int8" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*int8)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*int8)(nil)).Elem())
|
||||
}
|
||||
return &int8Codec{}
|
||||
case reflect.Int16:
|
||||
if typeName != "int16" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*int16)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*int16)(nil)).Elem())
|
||||
}
|
||||
return &int16Codec{}
|
||||
case reflect.Int32:
|
||||
if typeName != "int32" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*int32)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*int32)(nil)).Elem())
|
||||
}
|
||||
return &int32Codec{}
|
||||
case reflect.Int64:
|
||||
if typeName != "int64" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*int64)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*int64)(nil)).Elem())
|
||||
}
|
||||
return &int64Codec{}
|
||||
case reflect.Uint:
|
||||
if typeName != "uint" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*uint)(nil)).Elem())
|
||||
}
|
||||
return &uintCodec{}
|
||||
case reflect.Uint8:
|
||||
if typeName != "uint8" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint8)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*uint8)(nil)).Elem())
|
||||
}
|
||||
return &uint8Codec{}
|
||||
case reflect.Uint16:
|
||||
if typeName != "uint16" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint16)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*uint16)(nil)).Elem())
|
||||
}
|
||||
return &uint16Codec{}
|
||||
case reflect.Uint32:
|
||||
if typeName != "uint32" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint32)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*uint32)(nil)).Elem())
|
||||
}
|
||||
return &uint32Codec{}
|
||||
case reflect.Uintptr:
|
||||
if typeName != "uintptr" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*uintptr)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*uintptr)(nil)).Elem())
|
||||
}
|
||||
return &uintptrCodec{}
|
||||
case reflect.Uint64:
|
||||
if typeName != "uint64" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*uint64)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*uint64)(nil)).Elem())
|
||||
}
|
||||
return &uint64Codec{}
|
||||
case reflect.Float32:
|
||||
if typeName != "float32" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*float32)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*float32)(nil)).Elem())
|
||||
}
|
||||
return &float32Codec{}
|
||||
case reflect.Float64:
|
||||
if typeName != "float64" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*float64)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*float64)(nil)).Elem())
|
||||
}
|
||||
return &float64Codec{}
|
||||
case reflect.Bool:
|
||||
if typeName != "bool" {
|
||||
return encoderOfType(cfg, prefix, reflect.TypeOf((*bool)(nil)).Elem())
|
||||
return encoderOfType(ctx, reflect.TypeOf((*bool)(nil)).Elem())
|
||||
}
|
||||
return &boolCodec{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createDecoderOfNative(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func createDecoderOfNative(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
||||
sliceDecoder := decoderOfSlice(cfg, prefix, typ)
|
||||
sliceDecoder := decoderOfSlice(ctx, typ)
|
||||
return &base64Codec{sliceDecoder: sliceDecoder}
|
||||
}
|
||||
typeName := typ.String()
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
if typeName != "string" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*string)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*string)(nil)).Elem())
|
||||
}
|
||||
return &stringCodec{}
|
||||
case reflect.Int:
|
||||
if typeName != "int" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*int)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*int)(nil)).Elem())
|
||||
}
|
||||
return &intCodec{}
|
||||
case reflect.Int8:
|
||||
if typeName != "int8" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*int8)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*int8)(nil)).Elem())
|
||||
}
|
||||
return &int8Codec{}
|
||||
case reflect.Int16:
|
||||
if typeName != "int16" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*int16)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*int16)(nil)).Elem())
|
||||
}
|
||||
return &int16Codec{}
|
||||
case reflect.Int32:
|
||||
if typeName != "int32" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*int32)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*int32)(nil)).Elem())
|
||||
}
|
||||
return &int32Codec{}
|
||||
case reflect.Int64:
|
||||
if typeName != "int64" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*int64)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*int64)(nil)).Elem())
|
||||
}
|
||||
return &int64Codec{}
|
||||
case reflect.Uint:
|
||||
if typeName != "uint" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*uint)(nil)).Elem())
|
||||
}
|
||||
return &uintCodec{}
|
||||
case reflect.Uint8:
|
||||
if typeName != "uint8" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint8)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*uint8)(nil)).Elem())
|
||||
}
|
||||
return &uint8Codec{}
|
||||
case reflect.Uint16:
|
||||
if typeName != "uint16" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint16)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*uint16)(nil)).Elem())
|
||||
}
|
||||
return &uint16Codec{}
|
||||
case reflect.Uint32:
|
||||
if typeName != "uint32" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint32)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*uint32)(nil)).Elem())
|
||||
}
|
||||
return &uint32Codec{}
|
||||
case reflect.Uintptr:
|
||||
if typeName != "uintptr" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*uintptr)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*uintptr)(nil)).Elem())
|
||||
}
|
||||
return &uintptrCodec{}
|
||||
case reflect.Uint64:
|
||||
if typeName != "uint64" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*uint64)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*uint64)(nil)).Elem())
|
||||
}
|
||||
return &uint64Codec{}
|
||||
case reflect.Float32:
|
||||
if typeName != "float32" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*float32)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*float32)(nil)).Elem())
|
||||
}
|
||||
return &float32Codec{}
|
||||
case reflect.Float64:
|
||||
if typeName != "float64" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*float64)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*float64)(nil)).Elem())
|
||||
}
|
||||
return &float64Codec{}
|
||||
case reflect.Bool:
|
||||
if typeName != "bool" {
|
||||
return decoderOfType(cfg, prefix, reflect.TypeOf((*bool)(nil)).Elem())
|
||||
return decoderOfType(ctx, reflect.TypeOf((*bool)(nil)).Elem())
|
||||
}
|
||||
return &boolCodec{}
|
||||
}
|
||||
|
@@ -6,18 +6,18 @@ import (
|
||||
"github.com/v2pro/plz/reflect2"
|
||||
)
|
||||
|
||||
func decoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func decoderOfOptional(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
elemType := typ.Elem()
|
||||
decoder := decoderOfType(cfg, prefix, elemType)
|
||||
if prefix == "" && elemType.Kind() == reflect.Ptr {
|
||||
decoder := decoderOfType(ctx, elemType)
|
||||
if ctx.prefix == "" && elemType.Kind() == reflect.Ptr {
|
||||
return &dereferenceDecoder{reflect2.Type2(elemType), decoder}
|
||||
}
|
||||
return &OptionalDecoder{reflect2.Type2(elemType), decoder}
|
||||
}
|
||||
|
||||
func encoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func encoderOfOptional(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
elemType := typ.Elem()
|
||||
elemEncoder := encoderOfType(cfg, prefix, elemType)
|
||||
elemEncoder := encoderOfType(ctx, elemType)
|
||||
encoder := &OptionalEncoder{elemEncoder}
|
||||
return encoder
|
||||
}
|
||||
|
@@ -8,14 +8,14 @@ import (
|
||||
"github.com/v2pro/plz/reflect2"
|
||||
)
|
||||
|
||||
func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem())
|
||||
func decoderOfSlice(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
decoder := decoderOfType(ctx.append("[sliceElem]"), typ.Elem())
|
||||
sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType)
|
||||
return &sliceDecoder{sliceType, decoder}
|
||||
}
|
||||
|
||||
func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
encoder := encoderOfType(cfg, prefix+"[slice]->", typ.Elem())
|
||||
func encoderOfSlice(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
encoder := encoderOfType(ctx.append("[sliceElem]"), typ.Elem())
|
||||
sliceType := reflect2.Type2(typ).(*reflect2.UnsafeSliceType)
|
||||
return &sliceEncoder{sliceType, encoder}
|
||||
}
|
||||
|
@@ -8,9 +8,9 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
|
||||
func decoderOfStruct(ctx *ctx, typ reflect.Type) ValDecoder {
|
||||
bindings := map[string]*Binding{}
|
||||
structDescriptor := describeStruct(cfg, prefix, typ)
|
||||
structDescriptor := describeStruct(ctx, typ)
|
||||
for _, binding := range structDescriptor.Fields {
|
||||
for _, fromName := range binding.FromNames {
|
||||
old := bindings[fromName]
|
||||
@@ -18,7 +18,7 @@ func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
|
||||
bindings[fromName] = binding
|
||||
continue
|
||||
}
|
||||
ignoreOld, ignoreNew := resolveConflictBinding(cfg, old, binding)
|
||||
ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding)
|
||||
if ignoreOld {
|
||||
delete(bindings, fromName)
|
||||
}
|
||||
@@ -31,11 +31,11 @@ func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
|
||||
for k, binding := range bindings {
|
||||
fields[k] = binding.Decoder.(*structFieldDecoder)
|
||||
}
|
||||
return createStructDecoder(cfg, typ, fields)
|
||||
return createStructDecoder(ctx, typ, fields)
|
||||
}
|
||||
|
||||
func createStructDecoder(cfg *frozenConfig, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
|
||||
if cfg.disallowUnknownFields {
|
||||
func createStructDecoder(ctx *ctx, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
|
||||
if ctx.disallowUnknownFields {
|
||||
return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
|
||||
}
|
||||
knownHash := map[int64]struct{}{
|
||||
|
@@ -8,14 +8,14 @@ import (
|
||||
"github.com/v2pro/plz/reflect2"
|
||||
)
|
||||
|
||||
func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
|
||||
func encoderOfStruct(ctx *ctx, typ reflect.Type) ValEncoder {
|
||||
type bindingTo struct {
|
||||
binding *Binding
|
||||
toName string
|
||||
ignored bool
|
||||
}
|
||||
orderedBindings := []*bindingTo{}
|
||||
structDescriptor := describeStruct(cfg, prefix, typ)
|
||||
structDescriptor := describeStruct(ctx, typ)
|
||||
for _, binding := range structDescriptor.Fields {
|
||||
for _, toName := range binding.ToNames {
|
||||
new := &bindingTo{
|
||||
@@ -26,7 +26,7 @@ func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
|
||||
if old.toName != toName {
|
||||
continue
|
||||
}
|
||||
old.ignored, new.ignored = resolveConflictBinding(cfg, old.binding, new.binding)
|
||||
old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding)
|
||||
}
|
||||
orderedBindings = append(orderedBindings, new)
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEnco
|
||||
return &structEncoder{typ, finalOrderedFields}
|
||||
}
|
||||
|
||||
func createCheckIsEmpty(cfg *frozenConfig, typ reflect.Type) checkIsEmpty {
|
||||
func createCheckIsEmpty(ctx *ctx, typ reflect.Type) checkIsEmpty {
|
||||
kind := typ.Kind()
|
||||
switch kind {
|
||||
case reflect.String:
|
||||
@@ -88,7 +88,7 @@ func createCheckIsEmpty(cfg *frozenConfig, typ reflect.Type) checkIsEmpty {
|
||||
case reflect.Slice:
|
||||
return &sliceEncoder{}
|
||||
case reflect.Map:
|
||||
return encoderOfMap(cfg, "", typ)
|
||||
return encoderOfMap(ctx, typ)
|
||||
case reflect.Ptr:
|
||||
return &OptionalEncoder{}
|
||||
default:
|
||||
|
@@ -120,8 +120,7 @@ func init() {
|
||||
Field1 string `json:"field-1,omitempty"`
|
||||
Field2 func() `json:"-"`
|
||||
}{},
|
||||
// TODO: fix me
|
||||
//structRecursive{},
|
||||
structRecursive{},
|
||||
struct {
|
||||
*CacheItem
|
||||
|
||||
|
Reference in New Issue
Block a user