mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +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) {
|
||||
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 :
|
||||
|
|
|
|||
|
|
@ -17,18 +17,19 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
`encoding/json`
|
||||
`fmt`
|
||||
`reflect`
|
||||
`runtime`
|
||||
`runtime/debug`
|
||||
`strconv`
|
||||
`testing`
|
||||
`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`
|
||||
`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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue