diff --git a/feature_reflect.go b/feature_reflect.go index 100e7e6..62fc892 100644 --- a/feature_reflect.go +++ b/feature_reflect.go @@ -5,6 +5,7 @@ import ( "reflect" "sync/atomic" "unsafe" + "errors" ) /* @@ -345,7 +346,11 @@ func decoderOfType(typ reflect.Type) (Decoder, error) { case reflect.Bool: return &boolCodec{}, nil case reflect.Interface: - return &interfaceCodec{}, nil + if typ.NumMethod() == 0 { + return &interfaceCodec{}, nil + } else { + return nil, errors.New("unsupportd type: " + typ.String()) + } case reflect.Struct: return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(typ)) case reflect.Slice: diff --git a/jsoniter_interface_test.go b/jsoniter_interface_test.go index 8dd8844..e1d78ba 100644 --- a/jsoniter_interface_test.go +++ b/jsoniter_interface_test.go @@ -3,6 +3,7 @@ package jsoniter import ( "testing" "github.com/json-iterator/go/require" + "unsafe" ) func Test_write_array_of_interface(t *testing.T) { @@ -22,11 +23,20 @@ func Test_write_map_of_interface(t *testing.T) { } type MyInterface interface { + Hello() string +} + +type MyString string + +func (ms MyString) Hello() string { + return string(ms) } func Test_write_map_of_custom_interface(t *testing.T) { should := require.New(t) - val := map[string]MyInterface{"hello":"world"} + myStr := MyString("world") + should.Equal("world", myStr.Hello()) + val := map[string]MyInterface{"hello":myStr} str, err := MarshalToString(val) should.Nil(err) should.Equal(`{"hello":"world"}`, str) @@ -39,4 +49,23 @@ func Test_write_interface(t *testing.T) { str, err := MarshalToString(val) should.Nil(err) should.Equal(`"hello"`, str) +} + +func Test_read_interface(t *testing.T) { + should := require.New(t) + var val interface{} + err := UnmarshalFromString(`"hello"`, &val) + should.Nil(err) + should.Equal("hello", val) +} + +func Test_read_custom_interface(t *testing.T) { + should := require.New(t) + var val MyInterface + RegisterTypeDecoder("jsoniter.MyInterface", func(ptr unsafe.Pointer, iter *Iterator) { + *((*MyInterface)(ptr)) = MyString(iter.ReadString()) + }) + err := UnmarshalFromString(`"hello"`, &val) + should.Nil(err) + should.Equal("hello", val.Hello()) } \ No newline at end of file