forked from mirror/go-json
Support UnmarshalText for decoding
This commit is contained in:
parent
c23e5f43a7
commit
bb169a5cf6
|
@ -152,7 +152,7 @@ func (d *Decoder) compileHead(typ *rtype) (decoder, error) {
|
||||||
if typ.Implements(unmarshalJSONType) {
|
if typ.Implements(unmarshalJSONType) {
|
||||||
return newUnmarshalJSONDecoder(typ), nil
|
return newUnmarshalJSONDecoder(typ), nil
|
||||||
} else if typ.Implements(unmarshalTextType) {
|
} else if typ.Implements(unmarshalTextType) {
|
||||||
|
return newUnmarshalTextDecoder(typ), nil
|
||||||
}
|
}
|
||||||
return d.compile(typ.Elem())
|
return d.compile(typ.Elem())
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ func (d *Decoder) compile(typ *rtype) (decoder, error) {
|
||||||
if typ.Implements(unmarshalJSONType) {
|
if typ.Implements(unmarshalJSONType) {
|
||||||
return newUnmarshalJSONDecoder(typ), nil
|
return newUnmarshalJSONDecoder(typ), nil
|
||||||
} else if typ.Implements(unmarshalTextType) {
|
} else if typ.Implements(unmarshalTextType) {
|
||||||
|
return newUnmarshalTextDecoder(typ), nil
|
||||||
}
|
}
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
|
|
|
@ -197,3 +197,24 @@ func Test_UnmarshalJSON(t *testing.T) {
|
||||||
assertEq(t, "unmarshal", v.v, 10)
|
assertEq(t, "unmarshal", v.v, 10)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type unmarshalText struct {
|
||||||
|
v int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *unmarshalText) UnmarshalText(b []byte) error {
|
||||||
|
var v int
|
||||||
|
if err := json.Unmarshal(b, &v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u.v = v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_UnmarshalText(t *testing.T) {
|
||||||
|
t.Run("*struct", func(t *testing.T) {
|
||||||
|
var v unmarshalText
|
||||||
|
assertErr(t, json.Unmarshal([]byte(`11`), &v))
|
||||||
|
assertEq(t, "unmarshal", v.v, 11)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package json
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type unmarshalTextDecoder struct {
|
||||||
|
typ *rtype
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUnmarshalTextDecoder(typ *rtype) *unmarshalTextDecoder {
|
||||||
|
return &unmarshalTextDecoder{typ: typ}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *unmarshalTextDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
|
||||||
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
start := cursor
|
||||||
|
end, err := skipValue(buf, cursor)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
src := buf[start:end]
|
||||||
|
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
||||||
|
typ: d.typ,
|
||||||
|
ptr: unsafe.Pointer(p),
|
||||||
|
}))
|
||||||
|
if err := v.(encoding.TextUnmarshaler).UnmarshalText(src); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return end, nil
|
||||||
|
}
|
Loading…
Reference in New Issue