mirror of
https://github.com/ii64/sonic.git
synced 2026-06-22 17:36:48 +08:00
feat: (ast) support casting V_STRING to number (#262)
This commit is contained in:
parent
07d7b867d4
commit
755c0252a9
2 changed files with 41 additions and 17 deletions
18
ast/node.go
18
ast/node.go
|
|
@ -187,13 +187,14 @@ func (self *Node) Bool() (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64 casts the node to int64 value, including V_NUMBER, V_TRUE, V_FALSE, V_ANY
|
// Int64 casts the node to int64 value, including V_NUMBER, V_TRUE, V_FALSE, V_ANY,
|
||||||
|
// V_STRING of invalid digits
|
||||||
func (self *Node) Int64() (int64, error) {
|
func (self *Node) Int64() (int64, error) {
|
||||||
if err := self.checkRaw(); err != nil {
|
if err := self.checkRaw(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
switch self.t {
|
switch self.t {
|
||||||
case _V_NUMBER : return numberToInt64(self)
|
case _V_NUMBER, types.V_STRING : return numberToInt64(self)
|
||||||
case types.V_TRUE : return 1, nil
|
case types.V_TRUE : return 1, nil
|
||||||
case types.V_FALSE : return 0, nil
|
case types.V_FALSE : return 0, nil
|
||||||
case _V_ANY :
|
case _V_ANY :
|
||||||
|
|
@ -241,13 +242,22 @@ func (self *Node) StrictInt64() (int64, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number casts node to float64, including V_NUMBER, V_TRUE, V_FALSE, V_ANY of json.Number
|
// Number casts node to float64, including V_NUMBER, V_TRUE, V_FALSE, V_ANY of json.Number,
|
||||||
|
// V_STRING of invalid digits
|
||||||
func (self *Node) Number() (json.Number, error) {
|
func (self *Node) Number() (json.Number, error) {
|
||||||
if err := self.checkRaw(); err != nil {
|
if err := self.checkRaw(); err != nil {
|
||||||
return json.Number(""), err
|
return json.Number(""), err
|
||||||
}
|
}
|
||||||
switch self.t {
|
switch self.t {
|
||||||
case _V_NUMBER : return toNumber(self) , nil
|
case _V_NUMBER : return toNumber(self) , nil
|
||||||
|
case types.V_STRING :
|
||||||
|
if _, err := numberToInt64(self); err == nil {
|
||||||
|
return toNumber(self), nil
|
||||||
|
} else if _, err := numberToFloat64(self); err == nil {
|
||||||
|
return toNumber(self), nil
|
||||||
|
} else {
|
||||||
|
return json.Number(""), err
|
||||||
|
}
|
||||||
case types.V_TRUE : return json.Number("1"), nil
|
case types.V_TRUE : return json.Number("1"), nil
|
||||||
case types.V_FALSE : return json.Number("0"), nil
|
case types.V_FALSE : return json.Number("0"), nil
|
||||||
case _V_ANY :
|
case _V_ANY :
|
||||||
|
|
@ -329,7 +339,7 @@ func (self *Node) Float64() (float64, error) {
|
||||||
return 0.0, err
|
return 0.0, err
|
||||||
}
|
}
|
||||||
switch self.t {
|
switch self.t {
|
||||||
case _V_NUMBER : return numberToFloat64(self)
|
case _V_NUMBER, types.V_STRING : return numberToFloat64(self)
|
||||||
case types.V_TRUE : return 1.0, nil
|
case types.V_TRUE : return 1.0, nil
|
||||||
case types.V_FALSE : return 0.0, nil
|
case types.V_FALSE : return 0.0, nil
|
||||||
case _V_ANY :
|
case _V_ANY :
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,19 @@
|
||||||
package ast
|
package ast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
`encoding/json`
|
`encoding/json`
|
||||||
`fmt`
|
`errors`
|
||||||
`reflect`
|
`fmt`
|
||||||
`runtime`
|
`reflect`
|
||||||
`runtime/debug`
|
`runtime`
|
||||||
`strconv`
|
`runtime/debug`
|
||||||
`testing`
|
`strconv`
|
||||||
|
`testing`
|
||||||
|
|
||||||
`github.com/bytedance/sonic/encoder`
|
`github.com/bytedance/sonic/encoder`
|
||||||
`github.com/bytedance/sonic/internal/native/types`
|
`github.com/bytedance/sonic/internal/native/types`
|
||||||
`github.com/bytedance/sonic/internal/rt`
|
`github.com/bytedance/sonic/internal/rt`
|
||||||
`github.com/stretchr/testify/assert`
|
`github.com/stretchr/testify/assert`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -232,6 +233,7 @@ func TestTypeCast(t *testing.T) {
|
||||||
exp interface{}
|
exp interface{}
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
var nonEmptyErr error = errors.New("")
|
||||||
a1 := NewAny(1)
|
a1 := NewAny(1)
|
||||||
lazyArray, _ := NewParser("[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]").Parse()
|
lazyArray, _ := NewParser("[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]").Parse()
|
||||||
lazyObject, _ := NewParser(`{"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16}`).Parse()
|
lazyObject, _ := NewParser(`{"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16}`).Parse()
|
||||||
|
|
@ -282,6 +284,8 @@ func TestTypeCast(t *testing.T) {
|
||||||
{"Bool", NewRaw("false"), false, nil},
|
{"Bool", NewRaw("false"), false, nil},
|
||||||
{"Int64", NewRaw("true"), int64(1), nil},
|
{"Int64", NewRaw("true"), int64(1), nil},
|
||||||
{"Int64", NewRaw("false"), int64(0), nil},
|
{"Int64", NewRaw("false"), int64(0), nil},
|
||||||
|
{"Int64", NewRaw("\"1\""), int64(1), nil},
|
||||||
|
{"Int64", NewRaw("\"1.0\""), int64(0), nonEmptyErr},
|
||||||
{"Int64", NewAny(int(0)), int64(0), nil},
|
{"Int64", NewAny(int(0)), int64(0), nil},
|
||||||
{"Int64", NewAny(int8(0)), int64(0), nil},
|
{"Int64", NewAny(int8(0)), int64(0), nil},
|
||||||
{"Int64", NewAny(int16(0)), int64(0), nil},
|
{"Int64", NewAny(int16(0)), int64(0), nil},
|
||||||
|
|
@ -308,6 +312,8 @@ func TestTypeCast(t *testing.T) {
|
||||||
{"StrictInt64", NewRaw("0"), int64(0), nil},
|
{"StrictInt64", NewRaw("0"), int64(0), nil},
|
||||||
{"Float64", NewRaw("true"), float64(1), nil},
|
{"Float64", NewRaw("true"), float64(1), nil},
|
||||||
{"Float64", NewRaw("false"), float64(0), nil},
|
{"Float64", NewRaw("false"), float64(0), nil},
|
||||||
|
{"Float64", NewRaw("\"1.0\""), float64(1.0), nil},
|
||||||
|
{"Float64", NewRaw("\"xx\""), float64(0), nonEmptyErr},
|
||||||
{"Float64", Node{}, float64(0), ErrUnsupportType},
|
{"Float64", Node{}, float64(0), ErrUnsupportType},
|
||||||
{"Float64", NewAny(float32(0)), float64(0), nil},
|
{"Float64", NewAny(float32(0)), float64(0), nil},
|
||||||
{"Float64", NewAny(float64(0)), float64(0), nil},
|
{"Float64", NewAny(float64(0)), float64(0), nil},
|
||||||
|
|
@ -321,6 +327,9 @@ func TestTypeCast(t *testing.T) {
|
||||||
{"Number", Node{}, json.Number(""), ErrUnsupportType},
|
{"Number", Node{}, json.Number(""), ErrUnsupportType},
|
||||||
{"Number", NewAny(json.Number("0")), json.Number("0"), nil},
|
{"Number", NewAny(json.Number("0")), json.Number("0"), nil},
|
||||||
{"Number", NewRaw("0.0"), json.Number("0.0"), nil},
|
{"Number", NewRaw("0.0"), json.Number("0.0"), nil},
|
||||||
|
{"Number", NewRaw("\"1\""), json.Number("1"), nil},
|
||||||
|
{"Number", NewRaw("\"1.1\""), json.Number("1.1"), nil},
|
||||||
|
{"Number", NewRaw("\"0.x0\""), json.Number(""), nonEmptyErr},
|
||||||
{"Number", NewRaw("true"), json.Number("1"), nil},
|
{"Number", NewRaw("true"), json.Number("1"), nil},
|
||||||
{"Number", NewRaw("false"), json.Number("0"), nil},
|
{"Number", NewRaw("false"), json.Number("0"), nil},
|
||||||
{"StrictNumber", NewRaw("true"), json.Number(""), ErrUnsupportType},
|
{"StrictNumber", NewRaw("true"), json.Number(""), ErrUnsupportType},
|
||||||
|
|
@ -380,8 +389,13 @@ func TestTypeCast(t *testing.T) {
|
||||||
if !reflect.DeepEqual(rets[0].Interface(), c.exp) {
|
if !reflect.DeepEqual(rets[0].Interface(), c.exp) {
|
||||||
t.Fatal(i, rets[0].Interface(), c.exp)
|
t.Fatal(i, rets[0].Interface(), c.exp)
|
||||||
}
|
}
|
||||||
if rets[1].Interface() != c.err {
|
v := rets[1].Interface();
|
||||||
t.Fatal(i, rets[1].Interface())
|
if c.err == nonEmptyErr {
|
||||||
|
if reflect.ValueOf(v).IsNil() {
|
||||||
|
t.Fatal(i, v)
|
||||||
|
}
|
||||||
|
} else if v != c.err {
|
||||||
|
t.Fatal(i, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue