From 815aa331a814e0ee2ed70d96e73af04180b93edd Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Sun, 2 Jul 2017 11:13:21 +0800 Subject: [PATCH] #101 checkIsEmpty can not reuse createEncoderOfSimpleType, otherwise it will fail when struct member is not serializable --- feature_reflect.go | 58 ++++++++++++++++++++++++++++++++++++-- jsoniter_customize_test.go | 41 ++++++++++++++------------- 2 files changed, 78 insertions(+), 21 deletions(-) diff --git a/feature_reflect.go b/feature_reflect.go index c821b6b..4c06897 100644 --- a/feature_reflect.go +++ b/feature_reflect.go @@ -446,7 +446,7 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error return &base64Codec{typ}, nil } if typ.Implements(marshalerType) { - checkIsEmpty, err := createEncoderOfSimpleType(cfg, typ) + checkIsEmpty, err := createCheckIsEmpty(typ) if err != nil { return nil, err } @@ -461,7 +461,7 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error return encoder, nil } if typ.Implements(textMarshalerType) { - checkIsEmpty, err := createEncoderOfSimpleType(cfg, typ) + checkIsEmpty, err := createCheckIsEmpty(typ) if err != nil { return nil, err } @@ -481,6 +481,60 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error return createEncoderOfSimpleType(cfg, typ) } +func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) { + kind := typ.Kind() + switch kind { + case reflect.String: + return &stringCodec{}, nil + case reflect.Int: + return &intCodec{}, nil + case reflect.Int8: + return &int8Codec{}, nil + case reflect.Int16: + return &int16Codec{}, nil + case reflect.Int32: + return &int32Codec{}, nil + case reflect.Int64: + return &int64Codec{}, nil + case reflect.Uint: + return &uintCodec{}, nil + case reflect.Uint8: + return &uint8Codec{}, nil + case reflect.Uint16: + return &uint16Codec{}, nil + case reflect.Uint32: + return &uint32Codec{}, nil + case reflect.Uintptr: + return &uintptrCodec{}, nil + case reflect.Uint64: + return &uint64Codec{}, nil + case reflect.Float32: + return &float32Codec{}, nil + case reflect.Float64: + return &float64Codec{}, nil + case reflect.Bool: + return &boolCodec{}, nil + case reflect.Interface: + if typ.NumMethod() == 0 { + return &emptyInterfaceCodec{}, nil + } else { + return &nonEmptyInterfaceCodec{}, nil + } + case reflect.Struct: + return &structEncoder{}, nil + case reflect.Array: + return &arrayEncoder{}, nil + case reflect.Slice: + return &sliceEncoder{}, nil + case reflect.Map: + return &mapEncoder{}, nil + case reflect.Ptr: + return &optionalEncoder{}, nil + default: + return nil, fmt.Errorf("unsupported type: %v", typ) + } +} + func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { typeName := typ.String() kind := typ.Kind() diff --git a/jsoniter_customize_test.go b/jsoniter_customize_test.go index 552d3d6..416afcc 100644 --- a/jsoniter_customize_test.go +++ b/jsoniter_customize_test.go @@ -118,25 +118,6 @@ func Test_customize_field_by_extension(t *testing.T) { should.Equal(`{"field-1":100}`, str) } -//func Test_unexported_fields(t *testing.T) { -// jsoniter := Config{SupportUnexportedStructFields: true}.Froze() -// should := require.New(t) -// type TestObject struct { -// field1 string -// field2 string `json:"field-2"` -// } -// obj := TestObject{} -// obj.field1 = "hello" -// should.Nil(jsoniter.UnmarshalFromString(`{}`, &obj)) -// should.Equal("hello", obj.field1) -// should.Nil(jsoniter.UnmarshalFromString(`{"field1": "world", "field-2": "abc"}`, &obj)) -// should.Equal("world", obj.field1) -// should.Equal("abc", obj.field2) -// str, err := jsoniter.MarshalToString(obj) -// should.Nil(err) -// should.Contains(str, `"field-2":"abc"`) -//} - type timeImplementedMarshaler time.Time func (obj timeImplementedMarshaler) MarshalJSON() ([]byte, error) { @@ -238,3 +219,25 @@ func Test_marshaler_on_struct(t *testing.T) { //json.Marshal(fixed) Marshal(fixed) } + +type withChan struct { + F2 chan []byte +} + +func (q withChan) MarshalJSON() ([]byte, error) { + return []byte(`""`), nil +} + +func (q *withChan) UnmarshalJSON(value []byte) error { + return nil +} + +func Test_with_chan(t *testing.T) { + type TestObject struct { + F1 withChan + } + should := require.New(t) + output, err := MarshalToString(TestObject{}) + should.Nil(err) + should.Equal(`{"F1":""}`, output) +} \ No newline at end of file