mirror of https://github.com/goccy/go-json.git
Merge 96b9d74fc6
into 3e9769d637
This commit is contained in:
commit
b18db1095d
|
@ -208,10 +208,18 @@ func Test_Decoder(t *testing.T) {
|
||||||
t.Run("interface", func(t *testing.T) {
|
t.Run("interface", func(t *testing.T) {
|
||||||
t.Run("number", func(t *testing.T) {
|
t.Run("number", func(t *testing.T) {
|
||||||
var v interface{}
|
var v interface{}
|
||||||
assertErr(t, json.Unmarshal([]byte(`10`), &v))
|
assertErr(t, json.Unmarshal([]byte(`10.0`), &v))
|
||||||
assertEq(t, "interface.kind", "float64", reflect.TypeOf(v).Kind().String())
|
assertEq(t, "interface.kind", "float64", reflect.TypeOf(v).Kind().String())
|
||||||
assertEq(t, "interface", `10`, fmt.Sprint(v))
|
assertEq(t, "interface", `10`, fmt.Sprint(v))
|
||||||
})
|
})
|
||||||
|
t.Run("int64", func(t *testing.T) {
|
||||||
|
type StructValueLayout struct {
|
||||||
|
Values []interface{} `json:"values"`
|
||||||
|
}
|
||||||
|
var structLayout StructValueLayout
|
||||||
|
assertErr(t, json.Unmarshal([]byte(`{"values":[2074546971352916989, "test"]}`), &structLayout))
|
||||||
|
assertEq(t, "int64", int64(2074546971352916989), structLayout.Values[0].(int64))
|
||||||
|
})
|
||||||
t.Run("string", func(t *testing.T) {
|
t.Run("string", func(t *testing.T) {
|
||||||
var v interface{}
|
var v interface{}
|
||||||
assertErr(t, json.Unmarshal([]byte(`"hello"`), &v))
|
assertErr(t, json.Unmarshal([]byte(`"hello"`), &v))
|
||||||
|
|
|
@ -18,6 +18,7 @@ type intDecoder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
|
func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
|
||||||
|
if typ != nil {
|
||||||
return &intDecoder{
|
return &intDecoder{
|
||||||
typ: typ,
|
typ: typ,
|
||||||
kind: typ.Kind(),
|
kind: typ.Kind(),
|
||||||
|
@ -25,6 +26,13 @@ func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsa
|
||||||
structName: structName,
|
structName: structName,
|
||||||
fieldName: fieldName,
|
fieldName: fieldName,
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return &intDecoder{
|
||||||
|
op: op,
|
||||||
|
structName: structName,
|
||||||
|
fieldName: fieldName,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
||||||
|
@ -190,6 +198,7 @@ func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return d.typeError(bytes, s.totalOffset())
|
return d.typeError(bytes, s.totalOffset())
|
||||||
}
|
}
|
||||||
|
if d.typ != nil {
|
||||||
switch d.kind {
|
switch d.kind {
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
if i64 < -1*(1<<7) || (1<<7) <= i64 {
|
if i64 < -1*(1<<7) || (1<<7) <= i64 {
|
||||||
|
@ -204,6 +213,7 @@ func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro
|
||||||
return d.typeError(bytes, s.totalOffset())
|
return d.typeError(bytes, s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
d.op(p, i64)
|
d.op(p, i64)
|
||||||
s.reset()
|
s.reset()
|
||||||
return nil
|
return nil
|
||||||
|
@ -223,6 +233,7 @@ func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, d.typeError(bytes, cursor)
|
return 0, d.typeError(bytes, cursor)
|
||||||
}
|
}
|
||||||
|
if d.typ != nil {
|
||||||
switch d.kind {
|
switch d.kind {
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
if i64 < -1*(1<<7) || (1<<7) <= i64 {
|
if i64 < -1*(1<<7) || (1<<7) <= i64 {
|
||||||
|
@ -237,6 +248,7 @@ func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
|
||||||
return 0, d.typeError(bytes, cursor)
|
return 0, d.typeError(bytes, cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
d.op(p, i64)
|
d.op(p, i64)
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding"
|
"encoding"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/errors"
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
@ -18,6 +19,7 @@ type interfaceDecoder struct {
|
||||||
sliceDecoder *sliceDecoder
|
sliceDecoder *sliceDecoder
|
||||||
mapDecoder *mapDecoder
|
mapDecoder *mapDecoder
|
||||||
floatDecoder *floatDecoder
|
floatDecoder *floatDecoder
|
||||||
|
intDecoder *intDecoder
|
||||||
numberDecoder *numberDecoder
|
numberDecoder *numberDecoder
|
||||||
stringDecoder *stringDecoder
|
stringDecoder *stringDecoder
|
||||||
}
|
}
|
||||||
|
@ -30,6 +32,9 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
|
||||||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
|
intDecoder: newIntDecoder(nil, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||||
|
*(*interface{})(p) = v
|
||||||
|
}),
|
||||||
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
|
@ -78,6 +83,9 @@ func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *inter
|
||||||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
|
intDecoder: newIntDecoder(nil, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||||
|
*(*interface{})(p) = v
|
||||||
|
}),
|
||||||
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
|
@ -423,7 +431,13 @@ func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, dep
|
||||||
**(**interface{})(unsafe.Pointer(&p)) = v
|
**(**interface{})(unsafe.Pointer(&p)) = v
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
bytes, _, _ := d.numberDecoder.decodeByte(ctx.Buf, cursor)
|
||||||
|
numberStr := *(*string)(unsafe.Pointer(&bytes))
|
||||||
|
if strings.Contains(numberStr, ".") {
|
||||||
return d.floatDecoder.Decode(ctx, cursor, depth, p)
|
return d.floatDecoder.Decode(ctx, cursor, depth, p)
|
||||||
|
} else {
|
||||||
|
return d.intDecoder.Decode(ctx, cursor, depth, p)
|
||||||
|
}
|
||||||
case '"':
|
case '"':
|
||||||
var v string
|
var v string
|
||||||
ptr := unsafe.Pointer(&v)
|
ptr := unsafe.Pointer(&v)
|
||||||
|
|
Loading…
Reference in New Issue