Browse Source

#101 checkIsEmpty can not reuse createEncoderOfSimpleType, otherwise it will fail when struct member is not serializable

Tao Wen 8 years ago
parent
commit
815aa331a8
2 changed files with 78 additions and 21 deletions
  1. 56 2
      feature_reflect.go
  2. 22 19
      jsoniter_customize_test.go

+ 56 - 2
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()

+ 22 - 19
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)
+}