diff --git a/ast/node.go b/ast/node.go index a11718e49..ad66dec17 100644 --- a/ast/node.go +++ b/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) { if err := self.checkRaw(); err != nil { return 0, err } 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_FALSE : return 0, nil 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) { if err := self.checkRaw(); err != nil { return json.Number(""), err } switch self.t { 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_FALSE : return json.Number("0"), nil case _V_ANY : @@ -329,7 +339,7 @@ func (self *Node) Float64() (float64, error) { return 0.0, err } 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_FALSE : return 0.0, nil case _V_ANY : diff --git a/ast/node_test.go b/ast/node_test.go index 7446dad28..5cc42c700 100644 --- a/ast/node_test.go +++ b/ast/node_test.go @@ -17,18 +17,19 @@ package ast import ( - `encoding/json` - `fmt` - `reflect` - `runtime` - `runtime/debug` - `strconv` - `testing` - - `github.com/bytedance/sonic/encoder` - `github.com/bytedance/sonic/internal/native/types` - `github.com/bytedance/sonic/internal/rt` - `github.com/stretchr/testify/assert` + `encoding/json` + `errors` + `fmt` + `reflect` + `runtime` + `runtime/debug` + `strconv` + `testing` + + `github.com/bytedance/sonic/encoder` + `github.com/bytedance/sonic/internal/native/types` + `github.com/bytedance/sonic/internal/rt` + `github.com/stretchr/testify/assert` ) @@ -232,6 +233,7 @@ func TestTypeCast(t *testing.T) { exp interface{} err error } + var nonEmptyErr error = errors.New("") a1 := NewAny(1) 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() @@ -282,6 +284,8 @@ func TestTypeCast(t *testing.T) { {"Bool", NewRaw("false"), false, nil}, {"Int64", NewRaw("true"), int64(1), 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(int8(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}, {"Float64", NewRaw("true"), float64(1), 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", NewAny(float32(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", NewAny(json.Number("0")), json.Number("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("false"), json.Number("0"), nil}, {"StrictNumber", NewRaw("true"), json.Number(""), ErrUnsupportType}, @@ -380,8 +389,13 @@ func TestTypeCast(t *testing.T) { if !reflect.DeepEqual(rets[0].Interface(), c.exp) { t.Fatal(i, rets[0].Interface(), c.exp) } - if rets[1].Interface() != c.err { - t.Fatal(i, rets[1].Interface()) + v := 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) } } }