forked from mirror/go-json
Merge pull request #94 from goccy/feature/fix-issue93
Fix some bugs of encoder/decoder ( for #93 )
This commit is contained in:
commit
d4b5171fdf
|
@ -1,6 +1,7 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -39,11 +40,56 @@ var (
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func decodeWithUnmarshaler(s *stream, unmarshaler Unmarshaler) error {
|
||||||
|
start := s.cursor
|
||||||
|
if err := s.skipValue(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
src := s.buf[start:s.cursor]
|
||||||
|
dst := make([]byte, len(src))
|
||||||
|
copy(dst, src)
|
||||||
|
|
||||||
|
if err := unmarshaler.UnmarshalJSON(dst); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeWithTextUnmarshaler(s *stream, unmarshaler encoding.TextUnmarshaler) error {
|
||||||
|
start := s.cursor
|
||||||
|
if err := s.skipValue(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
src := s.buf[start:s.cursor]
|
||||||
|
dst := make([]byte, len(src))
|
||||||
|
copy(dst, src)
|
||||||
|
|
||||||
|
if err := unmarshaler.UnmarshalText(dst); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *interfaceDecoder) decodeStream(s *stream, p unsafe.Pointer) error {
|
func (d *interfaceDecoder) decodeStream(s *stream, p unsafe.Pointer) error {
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case '{':
|
case '{':
|
||||||
|
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
||||||
|
typ: d.typ,
|
||||||
|
ptr: p,
|
||||||
|
}))
|
||||||
|
rv := reflect.ValueOf(runtimeInterfaceValue)
|
||||||
|
if rv.NumMethod() > 0 && rv.CanInterface() {
|
||||||
|
if u, ok := rv.Interface().(Unmarshaler); ok {
|
||||||
|
return decodeWithUnmarshaler(s, u)
|
||||||
|
}
|
||||||
|
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
|
||||||
|
return decodeWithTextUnmarshaler(s, u)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// empty interface
|
||||||
var v map[string]interface{}
|
var v map[string]interface{}
|
||||||
ptr := unsafe.Pointer(&v)
|
ptr := unsafe.Pointer(&v)
|
||||||
if err := newMapDecoder(
|
if err := newMapDecoder(
|
||||||
|
|
|
@ -57,11 +57,14 @@ func (d *unmarshalJSONDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
src := buf[start:end]
|
src := buf[start:end]
|
||||||
|
dst := make([]byte, len(src))
|
||||||
|
copy(dst, src)
|
||||||
|
|
||||||
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: p,
|
ptr: p,
|
||||||
}))
|
}))
|
||||||
if err := v.(Unmarshaler).UnmarshalJSON(src); err != nil {
|
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||||
d.annotateError(cursor, err)
|
d.annotateError(cursor, err)
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,6 +267,12 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
|
||||||
code = code.next
|
code = code.next
|
||||||
case opMarshalJSON:
|
case opMarshalJSON:
|
||||||
ptr := load(ctxptr, code.idx)
|
ptr := load(ctxptr, code.idx)
|
||||||
|
if ptr == 0 {
|
||||||
|
b = encodeNull(b)
|
||||||
|
b = encodeComma(b)
|
||||||
|
code = code.next
|
||||||
|
break
|
||||||
|
}
|
||||||
v := e.ptrToInterface(code, ptr)
|
v := e.ptrToInterface(code, ptr)
|
||||||
bb, err := v.(Marshaler).MarshalJSON()
|
bb, err := v.(Marshaler).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -229,6 +229,12 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode)
|
||||||
code = code.next
|
code = code.next
|
||||||
case opMarshalJSON:
|
case opMarshalJSON:
|
||||||
ptr := load(ctxptr, code.idx)
|
ptr := load(ctxptr, code.idx)
|
||||||
|
if ptr == 0 {
|
||||||
|
b = encodeNull(b)
|
||||||
|
b = encodeComma(b)
|
||||||
|
code = code.next
|
||||||
|
break
|
||||||
|
}
|
||||||
v := e.ptrToInterface(code, ptr)
|
v := e.ptrToInterface(code, ptr)
|
||||||
bb, err := v.(Marshaler).MarshalJSON()
|
bb, err := v.(Marshaler).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -242,6 +242,12 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op
|
||||||
code = code.next
|
code = code.next
|
||||||
case opMarshalJSON:
|
case opMarshalJSON:
|
||||||
ptr := load(ctxptr, code.idx)
|
ptr := load(ctxptr, code.idx)
|
||||||
|
if ptr == 0 {
|
||||||
|
b = encodeNull(b)
|
||||||
|
b = encodeIndentComma(b)
|
||||||
|
code = code.next
|
||||||
|
break
|
||||||
|
}
|
||||||
v := e.ptrToInterface(code, ptr)
|
v := e.ptrToInterface(code, ptr)
|
||||||
bb, err := v.(Marshaler).MarshalJSON()
|
bb, err := v.(Marshaler).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -242,6 +242,12 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) (
|
||||||
code = code.next
|
code = code.next
|
||||||
case opMarshalJSON:
|
case opMarshalJSON:
|
||||||
ptr := load(ctxptr, code.idx)
|
ptr := load(ctxptr, code.idx)
|
||||||
|
if ptr == 0 {
|
||||||
|
b = encodeNull(b)
|
||||||
|
b = encodeIndentComma(b)
|
||||||
|
code = code.next
|
||||||
|
break
|
||||||
|
}
|
||||||
v := e.ptrToInterface(code, ptr)
|
v := e.ptrToInterface(code, ptr)
|
||||||
bb, err := v.(Marshaler).MarshalJSON()
|
bb, err := v.(Marshaler).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue