瀏覽代碼

#102 create correct type when pointer to Marshaler/Unmarshaler is nil

Tao Wen 8 年之前
父節點
當前提交
bf002a02be
共有 2 個文件被更改,包括 50 次插入6 次删除
  1. 4 4
      feature_reflect.go
  2. 46 2
      jsoniter_customize_test.go

+ 4 - 4
feature_reflect.go

@@ -288,8 +288,8 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
 	if typ.Implements(unmarshalerType) {
 		templateInterface := reflect.New(typ).Elem().Interface()
 		var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
-		if typ.Kind() != reflect.Struct {
-			decoder = &optionalDecoder{typ, decoder}
+		if typ.Kind() == reflect.Ptr {
+			decoder = &optionalDecoder{typ.Elem(), decoder}
 		}
 		return decoder, nil
 	}
@@ -301,8 +301,8 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
 	if typ.Implements(textUnmarshalerType) {
 		templateInterface := reflect.New(typ).Elem().Interface()
 		var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
-		if typ.Kind() != reflect.Struct {
-			decoder = &optionalDecoder{typ, decoder}
+		if typ.Kind() == reflect.Ptr {
+			decoder = &optionalDecoder{typ.Elem(), decoder}
 		}
 		return decoder, nil
 	}

+ 46 - 2
jsoniter_customize_test.go

@@ -232,7 +232,7 @@ func (q *withChan) UnmarshalJSON(value []byte) error {
 	return nil
 }
 
-func Test_with_chan(t *testing.T) {
+func Test_marshal_json_with_chan(t *testing.T) {
 	type TestObject struct {
 		F1 withChan
 	}
@@ -240,4 +240,48 @@ func Test_with_chan(t *testing.T) {
 	output, err := MarshalToString(TestObject{})
 	should.Nil(err)
 	should.Equal(`{"F1":""}`, output)
-}
+}
+
+type withTime struct {
+	time.Time
+}
+
+func (t *withTime) UnmarshalJSON(b []byte) error {
+	return nil
+}
+func (t withTime) MarshalJSON() ([]byte, error) {
+	return []byte(`"fake"`), nil
+}
+
+func Test_marshal_json_with_time(t *testing.T) {
+	type S1 struct {
+		F1 withTime
+		F2 *withTime
+	}
+	type TestObject struct {
+		TF1 S1
+	}
+	should := require.New(t)
+	obj := TestObject{
+		S1{
+			F1: withTime{
+				time.Unix(0, 0),
+			},
+			F2: &withTime{
+				time.Unix(0, 0),
+			},
+		},
+	}
+	output, err := json.Marshal(obj)
+	should.Nil(err)
+	should.Equal(`{"TF1":{"F1":"fake","F2":"fake"}}`, string(output))
+	output, err = Marshal(obj)
+	should.Nil(err)
+	should.Equal(`{"TF1":{"F1":"fake","F2":"fake"}}`, string(output))
+	obj = TestObject{}
+	should.Nil(json.Unmarshal([]byte(`{"TF1":{"F1":"fake","F2":"fake"}}`), &obj))
+	should.NotNil(obj.TF1.F2)
+	obj = TestObject{}
+	should.Nil(Unmarshal([]byte(`{"TF1":{"F1":"fake","F2":"fake"}}`), &obj))
+	should.NotNil(obj.TF1.F2)
+}