mirror of
https://github.com/json-iterator/go.git
synced 2025-05-13 21:36:29 +02:00
#27 support json.Unmarshaler
This commit is contained in:
parent
f6f159e108
commit
7d2ae80c37
@ -30,6 +30,17 @@ func (iter *Iterator) ReadBool() (ret bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (iter *Iterator) SkipAndReturnBytes() []byte {
|
||||||
|
if iter.reader != nil {
|
||||||
|
panic("reader input does not support this api")
|
||||||
|
}
|
||||||
|
before := iter.head
|
||||||
|
iter.Skip()
|
||||||
|
after := iter.head
|
||||||
|
return iter.buf[before:after]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Skip skips a json object and positions to relatively the next json object
|
// Skip skips a json object and positions to relatively the next json object
|
||||||
func (iter *Iterator) Skip() {
|
func (iter *Iterator) Skip() {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
|
@ -75,6 +75,7 @@ var fieldEncoders map[string]Encoder
|
|||||||
var extensions []ExtensionFunc
|
var extensions []ExtensionFunc
|
||||||
var anyType reflect.Type
|
var anyType reflect.Type
|
||||||
var marshalerType reflect.Type
|
var marshalerType reflect.Type
|
||||||
|
var unmarshalerType reflect.Type
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
typeDecoders = map[string]Decoder{}
|
typeDecoders = map[string]Decoder{}
|
||||||
@ -86,6 +87,7 @@ func init() {
|
|||||||
atomic.StorePointer(&ENCODERS, unsafe.Pointer(&map[string]Encoder{}))
|
atomic.StorePointer(&ENCODERS, unsafe.Pointer(&map[string]Encoder{}))
|
||||||
anyType = reflect.TypeOf((*Any)(nil)).Elem()
|
anyType = reflect.TypeOf((*Any)(nil)).Elem()
|
||||||
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||||
|
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
|
func addDecoderToCache(cacheKey reflect.Type, decoder Decoder) {
|
||||||
@ -293,9 +295,6 @@ func (p prefix) addToEncoder(encoder Encoder, err error) (Encoder, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func decoderOfType(typ reflect.Type) (Decoder, error) {
|
func decoderOfType(typ reflect.Type) (Decoder, error) {
|
||||||
if typ.ConvertibleTo(anyType) {
|
|
||||||
return &anyCodec{}, nil
|
|
||||||
}
|
|
||||||
typeName := typ.String()
|
typeName := typ.String()
|
||||||
typeDecoder := typeDecoders[typeName]
|
typeDecoder := typeDecoders[typeName]
|
||||||
if typeDecoder != nil {
|
if typeDecoder != nil {
|
||||||
@ -315,6 +314,13 @@ func decoderOfType(typ reflect.Type) (Decoder, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createDecoderOfType(typ reflect.Type) (Decoder, error) {
|
func createDecoderOfType(typ reflect.Type) (Decoder, error) {
|
||||||
|
if typ.ConvertibleTo(anyType) {
|
||||||
|
return &anyCodec{}, nil
|
||||||
|
}
|
||||||
|
if typ.ConvertibleTo(unmarshalerType) {
|
||||||
|
templateInterface := reflect.New(typ).Elem().Interface()
|
||||||
|
return &optionalDecoder{typ, &unmarshalerDecoder{extractInterface(templateInterface)}}, nil
|
||||||
|
}
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return &stringCodec{}, nil
|
return &stringCodec{}, nil
|
||||||
|
@ -363,3 +363,19 @@ func (encoder *marshalerEncoder) isEmpty(ptr unsafe.Pointer) bool {
|
|||||||
return len(bytes) > 0
|
return len(bytes) > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type unmarshalerDecoder struct {
|
||||||
|
templateInterface emptyInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (decoder *unmarshalerDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
|
templateInterface := decoder.templateInterface
|
||||||
|
templateInterface.word = ptr
|
||||||
|
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||||
|
unmarshaler := (*realInterface).(json.Unmarshaler)
|
||||||
|
bytes := iter.SkipAndReturnBytes()
|
||||||
|
err := unmarshaler.UnmarshalJSON(bytes)
|
||||||
|
if err != nil {
|
||||||
|
iter.reportError("unmarshaler", err.Error())
|
||||||
|
}
|
||||||
|
}
|
@ -150,3 +150,27 @@ func Test_marshaler(t *testing.T) {
|
|||||||
should.Nil(err)
|
should.Nil(err)
|
||||||
should.Equal(`{"Field":"hello"}`, str)
|
should.Equal(`{"Field":"hello"}`, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ObjectImplementedUnmarshaler int
|
||||||
|
|
||||||
|
func (obj *ObjectImplementedUnmarshaler) UnmarshalJSON([]byte) error {
|
||||||
|
*obj = 100
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_unmarshaler(t *testing.T) {
|
||||||
|
type TestObject struct {
|
||||||
|
Field *ObjectImplementedUnmarshaler
|
||||||
|
Field2 string
|
||||||
|
}
|
||||||
|
should := require.New(t)
|
||||||
|
obj := TestObject{}
|
||||||
|
val := ObjectImplementedUnmarshaler(0)
|
||||||
|
obj.Field = &val
|
||||||
|
err := json.Unmarshal([]byte(`{"Field":"hello"}`), &obj)
|
||||||
|
should.Nil(err)
|
||||||
|
should.Equal(100, int(*obj.Field))
|
||||||
|
err = Unmarshal([]byte(`{"Field":"hello"}`), &obj)
|
||||||
|
should.Nil(err)
|
||||||
|
should.Equal(100, int(*obj.Field))
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user