mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +08:00
feat:(ast) Add more strict casting API (#249)
* feat:(ast) Add more strict API * test: add cast test
This commit is contained in:
parent
f8fb04a184
commit
2e751bf5db
3 changed files with 128 additions and 8 deletions
|
|
@ -85,7 +85,7 @@ func TestEncodeValue(t *testing.T) {
|
|||
{NewBool(false), "false", false},
|
||||
{NewNumber("0.0"), "0.0", false},
|
||||
{NewString(""), `""`, false},
|
||||
{NewString("\"\""), `"\"\""`, false},
|
||||
{NewString(`\"\"`), `"\\\"\\\""`, false},
|
||||
{NewString(_TwitterJson), string(quote), false},
|
||||
{NewArray([]Node{}), "[]", false},
|
||||
{NewArray([]Node{NewBool(true), NewString("true"), NewString("\t")}), `[true,"true","\t"]`, false},
|
||||
|
|
|
|||
93
ast/node.go
93
ast/node.go
|
|
@ -165,7 +165,7 @@ func (self *Node) checkRaw() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Bool_E returns bool value represented by this node
|
||||
// Bool returns bool value represented by this node
|
||||
//
|
||||
// If node type is not types.V_TRUE or types.V_FALSE,
|
||||
// V_RAW (must be a bool json value), or V_ANY (must be a bool type)
|
||||
|
|
@ -187,7 +187,7 @@ func (self *Node) Bool() (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Int64 as above.
|
||||
// Int64 casts the node to int64 value, including V_NUMBER, V_TRUE, V_FALSE, V_ANY
|
||||
func (self *Node) Int64() (int64, error) {
|
||||
if err := self.checkRaw(); err != nil {
|
||||
return 0, err
|
||||
|
|
@ -215,7 +215,33 @@ func (self *Node) Int64() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Number as above.
|
||||
// StrictInt64 exports underlying int64 value, including V_NUMBER, V_ANY
|
||||
func (self *Node) StrictInt64() (int64, error) {
|
||||
if err := self.checkRaw(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
switch self.t {
|
||||
case _V_NUMBER : return numberToInt64(self)
|
||||
case _V_ANY :
|
||||
any := self.packAny()
|
||||
switch v := any.(type) {
|
||||
case int : return int64(v), nil
|
||||
case int8 : return int64(v), nil
|
||||
case int16 : return int64(v), nil
|
||||
case int32 : return int64(v), nil
|
||||
case int64 : return int64(v), nil
|
||||
case uint : return int64(v), nil
|
||||
case uint8 : return int64(v), nil
|
||||
case uint16: return int64(v), nil
|
||||
case uint32: return int64(v), nil
|
||||
case uint64: return int64(v), nil
|
||||
default: return 0, ErrUnsupportType
|
||||
}
|
||||
default : return 0, ErrUnsupportType
|
||||
}
|
||||
}
|
||||
|
||||
// Number casts node to float64, including V_NUMBER, V_TRUE, V_FALSE, V_ANY of json.Number
|
||||
func (self *Node) Number() (json.Number, error) {
|
||||
if err := self.checkRaw(); err != nil {
|
||||
return json.Number(""), err
|
||||
|
|
@ -234,6 +260,23 @@ func (self *Node) Number() (json.Number, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Number exports underlying float64 value, including V_NUMBER, V_ANY of json.Number
|
||||
func (self *Node) StrictNumber() (json.Number, error) {
|
||||
if err := self.checkRaw(); err != nil {
|
||||
return json.Number(""), err
|
||||
}
|
||||
switch self.t {
|
||||
case _V_NUMBER : return toNumber(self) , nil
|
||||
case _V_ANY :
|
||||
if v, ok := self.packAny().(json.Number); ok {
|
||||
return v, nil
|
||||
} else {
|
||||
return json.Number(""), ErrUnsupportType
|
||||
}
|
||||
default : return json.Number(""), ErrUnsupportType
|
||||
}
|
||||
}
|
||||
|
||||
// String returns raw string value if node type is V_STRING.
|
||||
// Or return the string representation of other types:
|
||||
// V_NULL => "null",
|
||||
|
|
@ -261,7 +304,26 @@ func (self *Node) String() (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Float64 as above.
|
||||
// StrictString returns string value (unescaped), includeing V_STRING, V_ANY of string.
|
||||
// In other cases, it will return empty string.
|
||||
func (self *Node) StrictString() (string, error) {
|
||||
if err := self.checkRaw(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch self.t {
|
||||
case types.V_NULL : return "", nil
|
||||
case types.V_STRING : return addr2str(self.p, self.v), nil
|
||||
case _V_ANY :
|
||||
if v, ok := self.packAny().(string); ok {
|
||||
return v, nil
|
||||
} else {
|
||||
return "", ErrUnsupportType
|
||||
}
|
||||
default : return "", ErrUnsupportType
|
||||
}
|
||||
}
|
||||
|
||||
// Float64 casts node to float64, includeing V_NUMBER, V_TRUE, V_FALSE, V_ANY
|
||||
func (self *Node) Float64() (float64, error) {
|
||||
if err := self.checkRaw(); err != nil {
|
||||
return 0.0, err
|
||||
|
|
@ -281,6 +343,24 @@ func (self *Node) Float64() (float64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Float64 exports underlying float64 value, includeing V_NUMBER, V_ANY
|
||||
func (self *Node) StrictFloat64() (float64, error) {
|
||||
if err := self.checkRaw(); err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
switch self.t {
|
||||
case _V_NUMBER : return numberToFloat64(self)
|
||||
case _V_ANY :
|
||||
any := self.packAny()
|
||||
switch v := any.(type) {
|
||||
case float32 : return float64(v), nil
|
||||
case float64 : return float64(v), nil
|
||||
default : return 0, ErrUnsupportType
|
||||
}
|
||||
default : return 0.0, ErrUnsupportType
|
||||
}
|
||||
}
|
||||
|
||||
/** Sequencial Value Methods **/
|
||||
|
||||
// Len returns children count of a array|object|string node
|
||||
|
|
@ -1410,7 +1490,10 @@ func newBytes(v []byte) Node {
|
|||
}
|
||||
}
|
||||
|
||||
// NewString creates a node of type string
|
||||
// NewString creates a node of type V_STRING.
|
||||
// v is considered to be a valid UTF-8 string,
|
||||
// which means it won't be validated and unescaped.
|
||||
// when the node is encoded to json, v will be escaped.
|
||||
func NewString(v string) Node {
|
||||
return Node{
|
||||
t: types.V_STRING,
|
||||
|
|
|
|||
|
|
@ -280,6 +280,8 @@ func TestTypeCast(t *testing.T) {
|
|||
{"Bool", NewAny(false), false, nil},
|
||||
{"Bool", NewRaw("true"), true, nil},
|
||||
{"Bool", NewRaw("false"), false, nil},
|
||||
{"Int64", NewRaw("true"), int64(1), nil},
|
||||
{"Int64", NewRaw("false"), int64(0), nil},
|
||||
{"Int64", NewAny(int(0)), int64(0), nil},
|
||||
{"Int64", NewAny(int8(0)), int64(0), nil},
|
||||
{"Int64", NewAny(int16(0)), int64(0), nil},
|
||||
|
|
@ -291,22 +293,57 @@ func TestTypeCast(t *testing.T) {
|
|||
{"Int64", NewAny(uint64(0)), int64(0), nil},
|
||||
{"Int64", Node{}, int64(0), ErrUnsupportType},
|
||||
{"Int64", NewRaw("0"), int64(0), nil},
|
||||
{"StrictInt64", NewRaw("true"), int64(0), ErrUnsupportType},
|
||||
{"StrictInt64", NewRaw("false"), int64(0), ErrUnsupportType},
|
||||
{"StrictInt64", NewAny(int(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(int8(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(int16(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(int32(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(int64(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(uint(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(uint8(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(uint32(0)), int64(0), nil},
|
||||
{"StrictInt64", NewAny(uint64(0)), int64(0), nil},
|
||||
{"StrictInt64", Node{}, int64(0), ErrUnsupportType},
|
||||
{"StrictInt64", NewRaw("0"), int64(0), nil},
|
||||
{"Float64", NewRaw("true"), float64(1), nil},
|
||||
{"Float64", NewRaw("false"), float64(0), nil},
|
||||
{"Float64", Node{}, float64(0), ErrUnsupportType},
|
||||
{"Float64", NewAny(float32(0)), float64(0), nil},
|
||||
{"Float64", NewAny(float64(0)), float64(0), nil},
|
||||
{"Float64", NewRaw("0.0"), float64(0.0), nil},
|
||||
{"StrictFloat64", NewRaw("true"), float64(0), ErrUnsupportType},
|
||||
{"StrictFloat64", NewRaw("false"), float64(0), ErrUnsupportType},
|
||||
{"StrictFloat64", Node{}, float64(0), ErrUnsupportType},
|
||||
{"StrictFloat64", NewAny(float32(0)), float64(0), nil},
|
||||
{"StrictFloat64", NewAny(float64(0)), float64(0), nil},
|
||||
{"StrictFloat64", NewRaw("0.0"), float64(0.0), nil},
|
||||
{"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("true"), json.Number("1"), nil},
|
||||
{"Number", NewRaw("false"), json.Number("0"), nil},
|
||||
{"StrictNumber", NewRaw("true"), json.Number(""), ErrUnsupportType},
|
||||
{"StrictNumber", NewRaw("false"), json.Number(""), ErrUnsupportType},
|
||||
{"StrictNumber", Node{}, json.Number(""), ErrUnsupportType},
|
||||
{"StrictNumber", NewAny(json.Number("0")), json.Number("0"), nil},
|
||||
{"StrictNumber", NewRaw("0.0"), json.Number("0.0"), nil},
|
||||
{"String", Node{}, "", ErrUnsupportType},
|
||||
{"String", NewAny(""), "", nil},
|
||||
{"String", NewRaw(`""`), ``, nil},
|
||||
{"String", NewAny(`\u263a`), `\u263a`, nil},
|
||||
{"String", NewRaw(`"\u263a"`), `☺`, nil},
|
||||
{"String", NewString(`\u263a`), `\u263a`, nil},
|
||||
{"String", NewRaw(`0.0`), "0.0", nil},
|
||||
{"String", NewRaw(`null`), "null", nil},
|
||||
{"String", NewRaw(`true`), "true", nil},
|
||||
{"String", NewRaw(`false`), "false", nil},
|
||||
{"StrictString", Node{}, "", ErrUnsupportType},
|
||||
{"StrictString", NewAny(`\u263a`), `\u263a`, nil},
|
||||
{"StrictString", NewRaw(`"\u263a"`), `☺`, nil},
|
||||
{"StrictString", NewString(`\u263a`), `\u263a`, nil},
|
||||
{"StrictString", NewRaw(`0.0`), "", ErrUnsupportType},
|
||||
{"StrictString", NewRaw(`null`), "", nil},
|
||||
{"StrictString", NewRaw(`true`), "", ErrUnsupportType},
|
||||
{"StrictString", NewRaw(`false`), "", ErrUnsupportType},
|
||||
{"Len", Node{}, 0, nil},
|
||||
{"Len", NewAny(0), 0, ErrUnsupportType},
|
||||
{"Len", NewNull(), 0, nil},
|
||||
|
|
|
|||
Loading…
Reference in a new issue