mirror of
https://github.com/json-iterator/go.git
synced 2025-03-20 20:54:55 +02:00
#76 support TextUnmarshal
This commit is contained in:
parent
08dbc98040
commit
545a32f2a1
@ -54,6 +54,7 @@ var jsoniterRawMessageType reflect.Type
|
|||||||
var anyType reflect.Type
|
var anyType reflect.Type
|
||||||
var marshalerType reflect.Type
|
var marshalerType reflect.Type
|
||||||
var unmarshalerType reflect.Type
|
var unmarshalerType reflect.Type
|
||||||
|
var textMarshalerType reflect.Type
|
||||||
var textUnmarshalerType reflect.Type
|
var textUnmarshalerType reflect.Type
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -63,6 +64,7 @@ func init() {
|
|||||||
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()
|
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||||
|
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||||
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +261,7 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
|
|||||||
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
||||||
return &base64Codec{}, nil
|
return &base64Codec{}, nil
|
||||||
}
|
}
|
||||||
if typ.ConvertibleTo(unmarshalerType) {
|
if typ.Implements(unmarshalerType) {
|
||||||
templateInterface := reflect.New(typ).Elem().Interface()
|
templateInterface := reflect.New(typ).Elem().Interface()
|
||||||
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
|
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
|
||||||
if typ.Kind() != reflect.Struct {
|
if typ.Kind() != reflect.Struct {
|
||||||
@ -267,12 +269,25 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
|
|||||||
}
|
}
|
||||||
return decoder, nil
|
return decoder, nil
|
||||||
}
|
}
|
||||||
if reflect.PtrTo(typ).ConvertibleTo(unmarshalerType) {
|
if reflect.PtrTo(typ).Implements(unmarshalerType) {
|
||||||
templateInterface := reflect.New(typ).Interface()
|
templateInterface := reflect.New(typ).Interface()
|
||||||
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
|
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
|
||||||
return decoder, nil
|
return decoder, nil
|
||||||
}
|
}
|
||||||
if typ.ConvertibleTo(anyType) {
|
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}
|
||||||
|
}
|
||||||
|
return decoder, nil
|
||||||
|
}
|
||||||
|
if reflect.PtrTo(typ).Implements(textUnmarshalerType) {
|
||||||
|
templateInterface := reflect.New(typ).Interface()
|
||||||
|
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
|
||||||
|
return decoder, nil
|
||||||
|
}
|
||||||
|
if typ.Implements(anyType) {
|
||||||
return &anyCodec{}, nil
|
return &anyCodec{}, nil
|
||||||
}
|
}
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
@ -402,7 +417,7 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error
|
|||||||
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
|
||||||
return &base64Codec{typ}, nil
|
return &base64Codec{typ}, nil
|
||||||
}
|
}
|
||||||
if typ.ConvertibleTo(marshalerType) {
|
if typ.Implements(marshalerType) {
|
||||||
templateInterface := reflect.New(typ).Elem().Interface()
|
templateInterface := reflect.New(typ).Elem().Interface()
|
||||||
var encoder ValEncoder = &marshalerEncoder{extractInterface(templateInterface)}
|
var encoder ValEncoder = &marshalerEncoder{extractInterface(templateInterface)}
|
||||||
if typ.Kind() != reflect.Struct {
|
if typ.Kind() != reflect.Struct {
|
||||||
@ -410,7 +425,15 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error
|
|||||||
}
|
}
|
||||||
return encoder, nil
|
return encoder, nil
|
||||||
}
|
}
|
||||||
if typ.ConvertibleTo(anyType) {
|
if typ.Implements(textMarshalerType) {
|
||||||
|
templateInterface := reflect.New(typ).Elem().Interface()
|
||||||
|
var encoder ValEncoder = &textMarshalerEncoder{extractInterface(templateInterface)}
|
||||||
|
if typ.Kind() != reflect.Struct {
|
||||||
|
encoder = &optionalEncoder{encoder}
|
||||||
|
}
|
||||||
|
return encoder, nil
|
||||||
|
}
|
||||||
|
if typ.Implements(anyType) {
|
||||||
return &anyCodec{}, nil
|
return &anyCodec{}, nil
|
||||||
}
|
}
|
||||||
kind := typ.Kind()
|
kind := typ.Kind()
|
||||||
|
@ -35,6 +35,7 @@ func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
decoder.elemDecoder.Decode(unsafe.Pointer(elem.Pointer()), iter)
|
decoder.elemDecoder.Decode(unsafe.Pointer(elem.Pointer()), iter)
|
||||||
// to put into map, we have to use reflection
|
// to put into map, we have to use reflection
|
||||||
keyType := decoder.keyType
|
keyType := decoder.keyType
|
||||||
|
// TODO: remove this from loop
|
||||||
switch {
|
switch {
|
||||||
case keyType.Kind() == reflect.String:
|
case keyType.Kind() == reflect.String:
|
||||||
realVal.SetMapIndex(reflect.ValueOf(keyStr).Convert(keyType), elem.Elem())
|
realVal.SetMapIndex(reflect.ValueOf(keyStr).Convert(keyType), elem.Elem())
|
||||||
@ -48,6 +49,15 @@ func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
}
|
}
|
||||||
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler), elem.Elem())
|
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler), elem.Elem())
|
||||||
return true
|
return true
|
||||||
|
case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
|
||||||
|
textUnmarshaler := reflect.New(keyType).Interface().(encoding.TextUnmarshaler)
|
||||||
|
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
|
||||||
|
if err != nil {
|
||||||
|
iter.ReportError("read map key as TextUnmarshaler", err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler).Elem(), elem.Elem())
|
||||||
|
return true
|
||||||
default:
|
default:
|
||||||
switch keyType.Kind() {
|
switch keyType.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stringCodec struct {
|
type stringCodec struct {
|
||||||
@ -574,6 +575,40 @@ func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type textMarshalerEncoder struct {
|
||||||
|
templateInterface emptyInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
|
templateInterface := encoder.templateInterface
|
||||||
|
templateInterface.word = ptr
|
||||||
|
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||||
|
marshaler := (*realInterface).(encoding.TextMarshaler)
|
||||||
|
bytes, err := marshaler.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
stream.Error = err
|
||||||
|
} else {
|
||||||
|
stream.WriteString(string(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (encoder *textMarshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
|
||||||
|
WriteToStream(val, stream, encoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||||
|
templateInterface := encoder.templateInterface
|
||||||
|
templateInterface.word = ptr
|
||||||
|
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||||
|
marshaler := (*realInterface).(encoding.TextMarshaler)
|
||||||
|
bytes, err := marshaler.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return len(bytes) > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type unmarshalerDecoder struct {
|
type unmarshalerDecoder struct {
|
||||||
templateInterface emptyInterface
|
templateInterface emptyInterface
|
||||||
}
|
}
|
||||||
@ -586,6 +621,22 @@ func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
bytes := iter.SkipAndReturnBytes()
|
bytes := iter.SkipAndReturnBytes()
|
||||||
err := unmarshaler.UnmarshalJSON(bytes)
|
err := unmarshaler.UnmarshalJSON(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
iter.ReportError("unmarshaler", err.Error())
|
iter.ReportError("unmarshalerDecoder", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type textUnmarshalerDecoder struct {
|
||||||
|
templateInterface emptyInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||||
|
templateInterface := decoder.templateInterface
|
||||||
|
templateInterface.word = ptr
|
||||||
|
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
|
||||||
|
unmarshaler := (*realInterface).(encoding.TextUnmarshaler)
|
||||||
|
str := iter.ReadString()
|
||||||
|
err := unmarshaler.UnmarshalText([]byte(str))
|
||||||
|
if err != nil {
|
||||||
|
iter.ReportError("textUnmarshalerDecoder", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user