mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +08:00
chore!: return error for scanning API (#81)
* chore!: return error for cast API BREAKING CHANGE: - Set()/Unset()/SetByIndex()/UnsetByIndex/Add() - Raw()/Bool()/Int64()/Float64()/Number()/Len()/Cap() - Values()/Properties()/Map()/Array()/Interface() Co-authored-by: duanyi.aster <duanyi.aster@bytedance.com>
This commit is contained in:
parent
6aec2f3722
commit
1f13d31b5a
10 changed files with 838 additions and 341 deletions
17
README.md
17
README.md
|
|
@ -151,6 +151,23 @@ root, err := sonic.Get(input, "key1", 1, "key2")
|
|||
sub := root.Get("key3").Index(2).Int64() // == 3
|
||||
```
|
||||
|
||||
#### Set/Unset
|
||||
Modify the json content by Set()/Unset()
|
||||
```go
|
||||
import "github.com/bytedance/sonic"
|
||||
|
||||
// Set
|
||||
exist, err := root.Set("key4", NewBool(true)) // exist == false
|
||||
alias1 := root.Get("key4")
|
||||
println(alias1.Valid()) // true
|
||||
alias2 := root.Index(1)
|
||||
println(alias1 == alias2) // true
|
||||
|
||||
// Unset
|
||||
exist, err := root.UnsetByIndex(1) // exist == true
|
||||
println(root.Get("key4").Check()) // "value not exist"
|
||||
```
|
||||
|
||||
#### Serialize
|
||||
To encode `ast.Node` as json, use `MarshalJson()` or `json.Marshal()` (MUST pass the node's pointer)
|
||||
```go
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
`errors`
|
||||
`sync`
|
||||
)
|
||||
|
||||
|
|
@ -69,7 +68,8 @@ func (self *Node) encode(buf *[]byte) error {
|
|||
return self.encodeRaw(buf)
|
||||
}
|
||||
switch self.Type() {
|
||||
case V_NONE : return errors.New("value not exist")
|
||||
case V_NONE : return ErrNotExist
|
||||
case V_ERROR : return self.Check()
|
||||
case V_NULL : return self.encodeNull(buf)
|
||||
case V_TRUE : return self.encodeTrue(buf)
|
||||
case V_FALSE : return self.encodeFalse(buf)
|
||||
|
|
@ -77,13 +77,15 @@ func (self *Node) encode(buf *[]byte) error {
|
|||
case V_OBJECT: return self.encodeObject(buf)
|
||||
case V_STRING: return self.encodeString(buf)
|
||||
case V_NUMBER: return self.encodeNumber(buf)
|
||||
default : errors.New("unsupported type")
|
||||
default : return ErrUnsupportType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Node) encodeRaw(buf *[]byte) error {
|
||||
raw := self.Raw()
|
||||
raw, err := self.Raw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*buf = append(*buf, raw...)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -119,7 +121,9 @@ func (self *Node) encodeString(buf *[]byte) error {
|
|||
|
||||
func (self *Node) encodeArray(buf *[]byte) error {
|
||||
if self.isLazy() {
|
||||
self.skipAllIndex()
|
||||
if err := self.skipAllIndex(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
nb := self.len()
|
||||
|
|
@ -157,7 +161,9 @@ func (self *Pair) encode(buf *[]byte) error {
|
|||
|
||||
func (self *Node) encodeObject(buf *[]byte) error {
|
||||
if self.isLazy() {
|
||||
self.skipAllKey()
|
||||
if err := self.skipAllKey(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
nb := self.len()
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ func (self *Iterator) Len() int {
|
|||
}
|
||||
|
||||
func (self *Iterator) HasNext() bool {
|
||||
return self.i < self.p.len()
|
||||
return self.i < self.p.len() && self.p.Valid()
|
||||
}
|
||||
|
||||
type ListIterator struct {
|
||||
|
|
|
|||
|
|
@ -47,14 +47,15 @@ func TestRawIterator(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ai := root.Values()
|
||||
ai, _ := root.Values()
|
||||
i := int64(0)
|
||||
for ai.HasNext() {
|
||||
v := &Node{}
|
||||
if !ai.Next(v) {
|
||||
t.Fatalf("no next")
|
||||
}
|
||||
if i < int64(loop) && v.Int64() != i {
|
||||
}
|
||||
x, _ := v.Int64()
|
||||
if i < int64(loop) && x != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, v)
|
||||
}
|
||||
if i != int64(ai.Pos())-1 || i >= int64(ai.Len()) {
|
||||
|
|
@ -67,15 +68,17 @@ func TestRawIterator(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mi := root.Properties()
|
||||
mi, _ := root.Properties()
|
||||
i = int64(0)
|
||||
for mi.HasNext() {
|
||||
v := &Pair{}
|
||||
if !mi.Next(v) {
|
||||
t.Fatalf("no next")
|
||||
}
|
||||
if i < int64(loop) &&( v.Value.Int64() != i ||v.Key != fmt.Sprintf("k%d", i)) {
|
||||
t.Fatalf("exp:%v, got:%v", i, v.Value.Interface())
|
||||
}
|
||||
x, _ := v.Value.Int64()
|
||||
if i < int64(loop) &&( x != i ||v.Key != fmt.Sprintf("k%d", i)) {
|
||||
vv, _ := v.Value.Interface()
|
||||
t.Fatalf("exp:%v, got:%v", i, vv)
|
||||
}
|
||||
if i != int64(mi.Pos())-1 || i >= int64(mi.Len()) {
|
||||
t.Fatal(i)
|
||||
|
|
@ -92,14 +95,15 @@ func TestIterator(t *testing.T) {
|
|||
if err != 0 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ai := root.Get("array").Values()
|
||||
ai, _ := root.Get("array").Values()
|
||||
i := int64(0)
|
||||
for ai.HasNext() {
|
||||
v := &Node{}
|
||||
if !ai.Next(v) {
|
||||
t.Fatalf("no next")
|
||||
}
|
||||
if i < int64(loop) && v.Int64() != i {
|
||||
x, _ := v.Int64()
|
||||
if i < int64(loop) && x != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, v)
|
||||
}
|
||||
if i != int64(ai.Pos())-1 || i >= int64(ai.Len()) {
|
||||
|
|
@ -112,15 +116,17 @@ func TestIterator(t *testing.T) {
|
|||
if err != 0 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mi := root.Get("object").Properties()
|
||||
mi, _ := root.Get("object").Properties()
|
||||
i = int64(0)
|
||||
for mi.HasNext() {
|
||||
v := &Pair{}
|
||||
if !mi.Next(v) {
|
||||
t.Fatalf("no next")
|
||||
}
|
||||
if i < int64(loop) &&( v.Value.Int64() != i ||v.Key != fmt.Sprintf("k%d", i)) {
|
||||
t.Fatalf("exp:%v, got:%v", i, v.Value.Interface())
|
||||
x, _ := v.Value.Int64()
|
||||
if i < int64(loop) &&( x != i ||v.Key != fmt.Sprintf("k%d", i)) {
|
||||
vv, _ := v.Value.Interface()
|
||||
t.Fatalf("exp:%v, got:%v", i, vv)
|
||||
}
|
||||
if i != int64(mi.Pos())-1 || i >= int64(mi.Len()) {
|
||||
t.Fatal(i)
|
||||
|
|
@ -135,7 +141,7 @@ func BenchmarkArrays(b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
a := root.Array()
|
||||
a, _ := root.Array()
|
||||
for _,v := range a {
|
||||
_ = v
|
||||
}
|
||||
|
|
@ -148,7 +154,7 @@ func BenchmarkListIterator(b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
it := root.Values()
|
||||
it, _ := root.Values()
|
||||
for it.HasNext() {
|
||||
v := &Node{}
|
||||
if !it.Next(v) {
|
||||
|
|
@ -164,7 +170,7 @@ func BenchmarkMap(b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
m := root.Map()
|
||||
m, _ := root.Map()
|
||||
for k,v := range m {
|
||||
_ = v
|
||||
_ = k
|
||||
|
|
@ -178,7 +184,7 @@ func BenchmarkObjectIterator(b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
it := root.Properties()
|
||||
it, _ := root.Properties()
|
||||
for it.HasNext() {
|
||||
v := &Pair{}
|
||||
if !it.Next(v) {
|
||||
|
|
|
|||
664
ast/node.go
664
ast/node.go
File diff suppressed because it is too large
Load diff
285
ast/node_test.go
285
ast/node_test.go
|
|
@ -18,6 +18,8 @@ package ast
|
|||
|
||||
import (
|
||||
`encoding/json`
|
||||
`fmt`
|
||||
`reflect`
|
||||
`strconv`
|
||||
`testing`
|
||||
|
||||
|
|
@ -28,13 +30,134 @@ import (
|
|||
|
||||
var parallelism = 4
|
||||
|
||||
func TestTypeCast(t *testing.T) {
|
||||
type tcase struct {
|
||||
method string
|
||||
node Node
|
||||
exp interface{}
|
||||
err error
|
||||
}
|
||||
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()
|
||||
var cases = []tcase{
|
||||
{"Raw", Node{}, "", ErrUnsupportType},
|
||||
{"Raw", newRawNode("[ ]", types.V_ARRAY), "[ ]", nil},
|
||||
{"Bool", Node{}, false, ErrNotExist},
|
||||
{"Bool", newRawNode("true", types.V_TRUE), true, nil},
|
||||
{"Bool", newRawNode("false", types.V_FALSE), false, nil},
|
||||
{"Int64", Node{}, int64(0), ErrNotExist},
|
||||
{"Int64", newRawNode("0", _V_NUMBER), int64(0), nil},
|
||||
{"Float64", Node{}, float64(0), ErrNotExist},
|
||||
{"Float64", newRawNode("0.0", _V_NUMBER), float64(0.0), nil},
|
||||
{"Number", Node{}, json.Number(""), ErrNotExist},
|
||||
{"Number", newRawNode("0.0", _V_NUMBER), json.Number("0.0"), nil},
|
||||
{"Number", newRawNode("true", types.V_TRUE), json.Number("1"), nil},
|
||||
{"Number", newRawNode("false", types.V_FALSE), json.Number("0"), nil},
|
||||
{"String", Node{}, "", ErrNotExist},
|
||||
{"String", newRawNode(`""`, types.V_STRING), ``, nil},
|
||||
{"String", newRawNode(`0.0`, _V_NUMBER), "0.0", nil},
|
||||
{"String", newRawNode(`null`, types.V_NULL), "null", nil},
|
||||
{"String", newRawNode(`true`, types.V_TRUE), "true", nil},
|
||||
{"String", newRawNode(`false`, types.V_FALSE), "false", nil},
|
||||
{"Len", NewNull(), 0, ErrUnsupportType},
|
||||
{"Len", newRawNode(`"1"`, types.V_STRING), 1, nil},
|
||||
{"Len", newRawNode(`[1]`, types.V_ARRAY), 0, nil},
|
||||
{"Len", NewArray([]Node{NewNull()}), 1, nil},
|
||||
{"Len", lazyArray, 0, nil},
|
||||
{"Len", newRawNode(`{"a":1}`, types.V_OBJECT), 0, nil},
|
||||
{"Len", lazyObject, 0, nil},
|
||||
{"Cap", NewNull(), 0, ErrUnsupportType},
|
||||
{"Cap", newRawNode(`[1]`, types.V_ARRAY), _DEFAULT_NODE_CAP, nil},
|
||||
{"Cap", NewObject([]Pair{{"",NewNull()}}), 1, nil},
|
||||
{"Cap", newRawNode(`{"a":1}`, types.V_OBJECT), _DEFAULT_NODE_CAP, nil},
|
||||
}
|
||||
lazyArray.skipAllIndex()
|
||||
lazyObject.skipAllKey()
|
||||
cases = append(cases,
|
||||
tcase{"Len", lazyObject, 17, nil},
|
||||
tcase{"Len", lazyObject, 17, nil},
|
||||
tcase{"Cap", lazyObject, _DEFAULT_NODE_CAP*2, nil},
|
||||
tcase{"Cap", lazyObject, _DEFAULT_NODE_CAP*2, nil},
|
||||
)
|
||||
|
||||
for i, c := range cases {
|
||||
fmt.Println(c)
|
||||
rt := reflect.ValueOf(&c.node)
|
||||
m := rt.MethodByName(c.method)
|
||||
rets := m.Call([]reflect.Value{})
|
||||
if len(rets) != 2 {
|
||||
t.Fatal(i, rets)
|
||||
}
|
||||
if rets[0].Interface() != c.exp {
|
||||
t.Fatal(i, rets[0].Interface())
|
||||
}
|
||||
if rets[1].Interface() != c.err {
|
||||
t.Fatal(i, rets[1].Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckError(t *testing.T) {
|
||||
s, err := NewParser(`{"a":{}, "b":talse, "c":{}}`).Parse()
|
||||
if err != 0 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := s.GetByPath()
|
||||
// fmt.Println(root.Check())
|
||||
a := root.Get("a")
|
||||
if a.Check() != nil {
|
||||
t.Fatal(a.Check())
|
||||
}
|
||||
c := root.Get("c")
|
||||
if c.Check() == nil {
|
||||
t.Fatal()
|
||||
}
|
||||
fmt.Println(c.Check())
|
||||
|
||||
_, e := a.Properties()
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
exist, e := a.Set("d", newRawNode("x", types.V_OBJECT))
|
||||
if exist || e != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if a.len() != 1 {
|
||||
t.Fail()
|
||||
}
|
||||
d := a.Get("d").Get("")
|
||||
if d.Check() == nil {
|
||||
t.Fatal(d)
|
||||
}
|
||||
exist, e = a.Set("e", newRawNode("[}", types.V_ARRAY))
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
if a.len() != 2 {
|
||||
t.Fail()
|
||||
}
|
||||
d = a.Index(1).Index(0)
|
||||
if d.Check() == nil {
|
||||
t.Fatal(d)
|
||||
}
|
||||
|
||||
|
||||
it, e := root.Interface()
|
||||
if e == nil {
|
||||
t.Fatal(it)
|
||||
}
|
||||
fmt.Println(e)
|
||||
}
|
||||
|
||||
func TestIndex(t *testing.T) {
|
||||
root, derr := NewParser(_TwitterJson).Parse()
|
||||
if derr != 0 {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
status := root.GetByPath("statuses", 0)
|
||||
if status.Index(4).String() != status.Get("id_str").String() {
|
||||
x, _ := status.Index(4).String()
|
||||
y, _ := status.Get("id_str").String()
|
||||
if x != y {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
|
@ -48,25 +171,26 @@ func TestUnset(t *testing.T) {
|
|||
if !entities.Exists() {
|
||||
t.Fatal()
|
||||
}
|
||||
exist := entities.Unset("urls")
|
||||
if !exist {
|
||||
exist, err := entities.Unset("urls")
|
||||
if !exist || err != nil {
|
||||
t.Fatal()
|
||||
}
|
||||
e := entities.Get("urls")
|
||||
if e.Exists() {
|
||||
t.Fatal()
|
||||
}
|
||||
if entities.Len() != 2 {
|
||||
if entities.len() != 2 {
|
||||
t.Fatal()
|
||||
}
|
||||
|
||||
entities.Set("urls", NewString("a"))
|
||||
e = entities.Get("urls")
|
||||
if !e.Exists() || e.String() != "a" {
|
||||
x, _ := e.String()
|
||||
if !e.Exists() || x != "a" {
|
||||
t.Fatal()
|
||||
}
|
||||
exist = entities.UnsetByIndex(entities.Len()-1)
|
||||
if !exist {
|
||||
exist, err = entities.UnsetByIndex(entities.len()-1)
|
||||
if !exist || err != nil {
|
||||
t.Fatal()
|
||||
}
|
||||
e = entities.Get("urls")
|
||||
|
|
@ -76,11 +200,12 @@ func TestUnset(t *testing.T) {
|
|||
|
||||
hashtags := entities.Get("hashtags").Index(0)
|
||||
hashtags.Set("text2", newRawNode(`{}`, types.V_OBJECT))
|
||||
exist = hashtags.Unset("indices")
|
||||
if !exist || hashtags.Len() != 2 {
|
||||
exist, err = hashtags.Unset("indices")
|
||||
if !exist || err != nil || hashtags.len() != 2 {
|
||||
t.Fatal()
|
||||
}
|
||||
if hashtags.Get("text").String() != "freebandnames" {
|
||||
y, _ := hashtags.Get("text").String()
|
||||
if y != "freebandnames" {
|
||||
t.Fatal()
|
||||
}
|
||||
if hashtags.Get("text2").Type() != V_OBJECT {
|
||||
|
|
@ -91,14 +216,16 @@ func TestUnset(t *testing.T) {
|
|||
ums.Add(NewNull())
|
||||
ums.Add(NewBool(true))
|
||||
ums.Add(NewBool(false))
|
||||
if ums.Len() != 3 {
|
||||
if ums.len() != 3 {
|
||||
t.Fatal()
|
||||
}
|
||||
exist = ums.UnsetByIndex(1)
|
||||
if !exist {
|
||||
exist, err = ums.UnsetByIndex(1)
|
||||
if !exist || err != nil {
|
||||
t.Fatal()
|
||||
}
|
||||
if ums.Index(0).Interface() != nil || ums.Index(1).Interface() != false {
|
||||
v1, _ := ums.Index(0).Interface()
|
||||
v2, _ := ums.Index(1).Interface()
|
||||
if v1 != nil || v2 != false {
|
||||
t.Fatal()
|
||||
}
|
||||
|
||||
|
|
@ -111,14 +238,15 @@ func TestUnsafeNode(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a := root.UnsafeArray()
|
||||
a, _ := root.UnsafeArray()
|
||||
if len(a) != loop {
|
||||
t.Fatalf("exp:%v, got:%v", loop, len(a))
|
||||
}
|
||||
for i := int64(0); i<int64(loop); i++{
|
||||
in := a[i]
|
||||
if in.Int64() != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, in.Int64())
|
||||
x, _ := in.Int64()
|
||||
if x != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, x)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +254,7 @@ func TestUnsafeNode(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := root.UnsafeMap()
|
||||
b, _ := root.UnsafeMap()
|
||||
if len(b) != loop {
|
||||
t.Fatalf("exp:%v, got:%v", loop, len(b))
|
||||
}
|
||||
|
|
@ -135,27 +263,37 @@ func TestUnsafeNode(t *testing.T) {
|
|||
if k != b[i].Key {
|
||||
t.Fatalf("unexpected element: %#v", b[i])
|
||||
}
|
||||
if b[i].Value.Int64() != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, b[i].Value.Int64())
|
||||
x, _ := b[i].Value.Int64()
|
||||
if x != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseNode(t *testing.T) {
|
||||
str, loop := getTestIteratorSample()
|
||||
root, e := NewParser(str).Parse()
|
||||
if e != 0 {
|
||||
t.Fatal(e)
|
||||
}
|
||||
_, er := root.InterfaceUseNode()
|
||||
if er != nil {
|
||||
t.Fatal(er)
|
||||
}
|
||||
|
||||
root, err := NewSearcher(str).GetByPath("array")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a := root.ArrayUseNode()
|
||||
a, _ := root.ArrayUseNode()
|
||||
if len(a) != loop {
|
||||
t.Fatalf("exp:%v, got:%v", loop, len(a))
|
||||
}
|
||||
for i := int64(0); i<int64(loop); i++{
|
||||
in := a[i]
|
||||
if in.Int64() != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, in.Int64())
|
||||
a, _ := in.Int64()
|
||||
if a != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, a)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,14 +301,16 @@ func TestUseNode(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a = root.InterfaceUseNode().([]Node)
|
||||
x, _ := root.InterfaceUseNode()
|
||||
a = x.([]Node)
|
||||
if len(a) != loop {
|
||||
t.Fatalf("exp:%v, got:%v", loop, len(a))
|
||||
}
|
||||
for i := int64(0); i<int64(loop); i++{
|
||||
in := a[i]
|
||||
if in.Int64() != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, in.Int64())
|
||||
a, _ := in.Int64()
|
||||
if a != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, a)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +318,7 @@ func TestUseNode(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := root.MapUseNode()
|
||||
b, _ := root.MapUseNode()
|
||||
if len(b) != loop {
|
||||
t.Fatalf("exp:%v, got:%v", loop, len(b))
|
||||
}
|
||||
|
|
@ -188,8 +328,9 @@ func TestUseNode(t *testing.T) {
|
|||
if !ok {
|
||||
t.Fatalf("unexpected element: %#v", xn)
|
||||
}
|
||||
if xn.Int64() != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, xn.Int64())
|
||||
a, _ := xn.Int64()
|
||||
if a != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, a)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +338,8 @@ func TestUseNode(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b = root.InterfaceUseNode().(map[string]Node)
|
||||
x, _ = root.InterfaceUseNode()
|
||||
b = x.(map[string]Node)
|
||||
if len(b) != loop {
|
||||
t.Fatalf("exp:%v, got:%v", loop, len(b))
|
||||
}
|
||||
|
|
@ -207,13 +349,24 @@ func TestUseNode(t *testing.T) {
|
|||
if !ok {
|
||||
t.Fatalf("unexpected element: %#v", xn)
|
||||
}
|
||||
if xn.Int64() != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, xn.Int64())
|
||||
a, _ := xn.Int64()
|
||||
if a != i {
|
||||
t.Fatalf("exp:%v, got:%v", i, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseNumber(t *testing.T) {
|
||||
str, _ := getTestIteratorSample()
|
||||
root, e := NewParser(str).Parse()
|
||||
if e != 0 {
|
||||
t.Fatal(e)
|
||||
}
|
||||
_, er := root.InterfaceUseNumber()
|
||||
if er != nil {
|
||||
t.Fatal(er)
|
||||
}
|
||||
|
||||
node, err := NewParser("1061346755812312312313").Parse()
|
||||
if err != 0 {
|
||||
t.Fatal(err)
|
||||
|
|
@ -221,16 +374,19 @@ func TestUseNumber(t *testing.T) {
|
|||
if node.Type() != V_NUMBER {
|
||||
t.Fatalf("wrong type: %v", node.Type())
|
||||
}
|
||||
iv := node.InterfaceUseNumber().(json.Number)
|
||||
x, _ := node.InterfaceUseNumber()
|
||||
iv := x.(json.Number)
|
||||
if iv.String() != "1061346755812312312313" {
|
||||
t.Fatalf("exp:%#v, got:%#v", "1061346755812312312313", iv.String())
|
||||
}
|
||||
ix := node.Interface().(float64)
|
||||
x, _ = node.Interface()
|
||||
ix := x.(float64)
|
||||
if ix != float64(1061346755812312312313) {
|
||||
t.Fatalf("exp:%#v, got:%#v", float64(1061346755812312312313), ix)
|
||||
}
|
||||
ij,_ := node.Number().Int64()
|
||||
jj,_ := json.Number("1061346755812312312313").Int64()
|
||||
xj, _ := node.Number()
|
||||
ij, _ := xj.Int64()
|
||||
jj, _ := json.Number("1061346755812312312313").Int64()
|
||||
if ij != jj {
|
||||
t.Fatalf("exp:%#v, got:%#v", jj, ij)
|
||||
}
|
||||
|
|
@ -241,14 +397,14 @@ func TestMap(t *testing.T) {
|
|||
if err != 0 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := node.Map()
|
||||
m, _ := node.Map()
|
||||
assert.Equal(t, m, map[string]interface{}{
|
||||
"a": float64(0),
|
||||
"b": float64(1),
|
||||
"c": -1.2,
|
||||
"d": -1.2e-10,
|
||||
})
|
||||
m1 := node.MapUseNumber()
|
||||
m1, _ := node.MapUseNumber()
|
||||
assert.Equal(t, m1, map[string]interface{}{
|
||||
"a": json.Number("-0"),
|
||||
"b": json.Number("1"),
|
||||
|
|
@ -262,14 +418,14 @@ func TestArray(t *testing.T) {
|
|||
if err != 0 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := node.Array()
|
||||
m, _ := node.Array()
|
||||
assert.Equal(t, m, []interface{}{
|
||||
float64(0),
|
||||
float64(1),
|
||||
-1.2,
|
||||
-1.2e-10,
|
||||
})
|
||||
m1 := node.ArrayUseNumber()
|
||||
m1, _ := node.ArrayUseNumber()
|
||||
assert.Equal(t, m1, []interface{}{
|
||||
json.Number("-0"),
|
||||
json.Number("1"),
|
||||
|
|
@ -283,7 +439,7 @@ func TestNodeRaw(t *testing.T) {
|
|||
if derr != nil {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val := root.Raw()
|
||||
val, _ := root.Raw()
|
||||
var comp = `{
|
||||
"max_id": 250126199840518145,
|
||||
"since_id": 24012619984051000,
|
||||
|
|
@ -303,7 +459,7 @@ func TestNodeRaw(t *testing.T) {
|
|||
if derr != nil {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val = root.Raw()
|
||||
val, _ = root.Raw()
|
||||
comp = `[
|
||||
{
|
||||
"text": "freebandnames",
|
||||
|
|
@ -322,7 +478,7 @@ func TestNodeRaw(t *testing.T) {
|
|||
if derr != nil {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val = root.Raw()
|
||||
val, _ = root.Raw()
|
||||
comp = `{ "a" : "bc"}`
|
||||
if val != comp {
|
||||
t.Fatalf("exp: %+v, got: %+v", comp, val)
|
||||
|
|
@ -332,7 +488,7 @@ func TestNodeRaw(t *testing.T) {
|
|||
if derr != nil {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val = root.Raw()
|
||||
val, _ = root.Raw()
|
||||
comp = `[1,2 ]`
|
||||
if val != comp {
|
||||
t.Fatalf("exp: %+v, got: %+v", comp, val)
|
||||
|
|
@ -342,7 +498,7 @@ func TestNodeRaw(t *testing.T) {
|
|||
if derr != nil {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val = root.Raw()
|
||||
val, _ = root.Raw()
|
||||
comp = `{}`
|
||||
if val != comp {
|
||||
t.Fatalf("exp: %+v, got: %+v", comp, val)
|
||||
|
|
@ -352,7 +508,7 @@ func TestNodeRaw(t *testing.T) {
|
|||
if derr != nil {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val = root.Raw()
|
||||
val, _ = root.Raw()
|
||||
comp = `[]`
|
||||
if val != comp {
|
||||
t.Fatalf("exp: %+v, got: %+v", comp, val)
|
||||
|
|
@ -364,7 +520,7 @@ func TestNodeGet(t *testing.T) {
|
|||
if derr != 0 {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val := root.Get("search_metadata").Get("max_id").Int64()
|
||||
val, _ := root.Get("search_metadata").Get("max_id").Int64()
|
||||
if val != int64(250126199840518145) {
|
||||
t.Fatalf("exp: %+v, got: %+v", 250126199840518145, val)
|
||||
}
|
||||
|
|
@ -375,7 +531,7 @@ func TestNodeIndex(t *testing.T) {
|
|||
if derr != 0 {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val := root.Get("statuses").Index(3).Get("id_str").String()
|
||||
val, _ := root.Get("statuses").Index(3).Get("id_str").String()
|
||||
if val != "249279667666817024" {
|
||||
t.Fatalf("exp: %+v, got: %+v", "249279667666817024", val)
|
||||
}
|
||||
|
|
@ -386,7 +542,7 @@ func TestNodeGetByPath(t *testing.T) {
|
|||
if derr != 0 {
|
||||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
val := root.GetByPath("statuses", 3, "id_str").String()
|
||||
val, _ := root.GetByPath("statuses", 3, "id_str").String()
|
||||
if val != "249279667666817024" {
|
||||
t.Fatalf("exp: %+v, got: %+v", "249279667666817024", val)
|
||||
}
|
||||
|
|
@ -399,14 +555,14 @@ func TestNodeSet(t *testing.T) {
|
|||
}
|
||||
app,_ := NewParser("111").Parse()
|
||||
root.GetByPath("statuses", 3).Set("id_str", app)
|
||||
val := root.GetByPath("statuses", 3, "id_str").Int64()
|
||||
val, _ := root.GetByPath("statuses", 3, "id_str").Int64()
|
||||
if val != 111 {
|
||||
t.Fatalf("exp: %+v, got: %+v", 111, val)
|
||||
}
|
||||
for i := root.GetByPath("statuses", 3).Cap(); i >= 0; i-- {
|
||||
for i := root.GetByPath("statuses", 3).cap(); i >= 0; i-- {
|
||||
root.GetByPath("statuses", 3).Set("id_str"+strconv.Itoa(i), app)
|
||||
}
|
||||
val = root.GetByPath("statuses", 3, "id_str0").Int64()
|
||||
val, _ = root.GetByPath("statuses", 3, "id_str0").Int64()
|
||||
if val != 111 {
|
||||
t.Fatalf("exp: %+v, got: %+v", 111, val)
|
||||
}
|
||||
|
|
@ -416,7 +572,7 @@ func TestNodeSet(t *testing.T) {
|
|||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
root.GetByPath("statuses", 3).Set("id_str2", nroot)
|
||||
val2 := root.GetByPath("statuses", 3, "id_str2", "a", 4, "b").String()
|
||||
val2, _ := root.GetByPath("statuses", 3, "id_str2", "a", 4, "b").String()
|
||||
if val2 != "c" {
|
||||
t.Fatalf("exp:%+v, got:%+v", "c", val2)
|
||||
}
|
||||
|
|
@ -432,7 +588,8 @@ func TestNodeSetByIndex(t *testing.T) {
|
|||
st.SetByIndex(0, app)
|
||||
st = root.GetByPath("statuses")
|
||||
val := st.Index(0)
|
||||
if val.Int64() != 111 {
|
||||
x, _ := val.Int64()
|
||||
if x != 111 {
|
||||
t.Fatalf("exp: %+v, got: %+v", 111, val)
|
||||
}
|
||||
|
||||
|
|
@ -441,7 +598,7 @@ func TestNodeSetByIndex(t *testing.T) {
|
|||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
root.GetByPath("statuses").SetByIndex(0, nroot)
|
||||
val2 := root.GetByPath("statuses", 0, "a", 4, "b").String()
|
||||
val2, _ := root.GetByPath("statuses", 0, "a", 4, "b").String()
|
||||
if val2 != "c" {
|
||||
t.Fatalf("exp:%+v, got:%+v", "c", val2)
|
||||
}
|
||||
|
|
@ -454,14 +611,14 @@ func TestNodeAdd(t *testing.T) {
|
|||
}
|
||||
app, _ := NewParser("111").Parse()
|
||||
|
||||
for i := root.GetByPath("statuses").Cap(); i >= 0; i-- {
|
||||
for i := root.GetByPath("statuses").cap(); i >= 0; i-- {
|
||||
root.GetByPath("statuses").Add(app)
|
||||
}
|
||||
val := root.GetByPath("statuses", 4).Int64()
|
||||
val, _ := root.GetByPath("statuses", 4).Int64()
|
||||
if val != 111 {
|
||||
t.Fatalf("exp: %+v, got: %+v", 111, val)
|
||||
}
|
||||
val = root.GetByPath("statuses", root.GetByPath("statuses").Len()-1).Int64()
|
||||
val, _ = root.GetByPath("statuses", root.GetByPath("statuses").len()-1).Int64()
|
||||
if val != 111 {
|
||||
t.Fatalf("exp: %+v, got: %+v", 111, val)
|
||||
}
|
||||
|
|
@ -471,7 +628,7 @@ func TestNodeAdd(t *testing.T) {
|
|||
t.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
root.GetByPath("statuses").Add(nroot)
|
||||
val2 := root.GetByPath("statuses", root.GetByPath("statuses").Len()-1, "a", 4, "b").String()
|
||||
val2, _ := root.GetByPath("statuses", root.GetByPath("statuses").len()-1, "a", 4, "b").String()
|
||||
if val2 != "c" {
|
||||
t.Fatalf("exp:%+v, got:%+v", "c", val2)
|
||||
}
|
||||
|
|
@ -497,13 +654,13 @@ func BenchmarkNodeGetByPath(b *testing.B) {
|
|||
if derr != 0 {
|
||||
b.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
_ = root.GetByPath("statuses", 3, "entities", "hashtags", 0, "text").String()
|
||||
_, _ = root.GetByPath("statuses", 3, "entities", "hashtags", 0, "text").String()
|
||||
b.SetParallelism(parallelism)
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_ = root.GetByPath("statuses", 3, "entities", "hashtags", 0, "text").String()
|
||||
_, _ = root.GetByPath("statuses", 3, "entities", "hashtags", 0, "text").String()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -553,7 +710,7 @@ func BenchmarkMapGet(b *testing.B) {
|
|||
node.Set("test3", NewNumber("3"))
|
||||
node.Set("test4", NewNumber("4"))
|
||||
node.Set("test5", NewNumber("5"))
|
||||
m := node.Map()
|
||||
m, _ := node.Map()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = m["text"]
|
||||
|
|
@ -578,7 +735,7 @@ func BenchmarkMapSet(b *testing.B) {
|
|||
if derr != 0 {
|
||||
b.Fatalf("decode failed: %v", derr.Error())
|
||||
}
|
||||
node := root.Get("statuses").Index(3).Get("entities").Get("hashtags").Index(0).Map()
|
||||
node, _ := root.Get("statuses").Index(3).Get("entities").Get("hashtags").Index(0).Map()
|
||||
b.SetParallelism(parallelism)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
|
@ -611,7 +768,7 @@ func BenchmarkSliceAdd(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
root, _ := NewParser(data).Parse()
|
||||
node := root.Get("statuses").Array()
|
||||
node, _ := root.Get("statuses").Array()
|
||||
node = append(node, map[string]interface{}{"test": 1})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package ast
|
|||
import (
|
||||
`fmt`
|
||||
`sync`
|
||||
`unsafe`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/decoder`
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
|
|
@ -30,7 +30,18 @@ import (
|
|||
|
||||
const _DEFAULT_NODE_CAP int = 16
|
||||
|
||||
const _ERR_NOT_FOUND types.ParsingError = 33
|
||||
const (
|
||||
_ERR_NOT_FOUND types.ParsingError = 33
|
||||
_ERR_UNSUPPORT_TYPE types.ParsingError = 34
|
||||
)
|
||||
|
||||
var (
|
||||
nodeNotExist = newError(_ERR_NOT_FOUND, "value not exists")
|
||||
nodeUnsupportType = newError(_ERR_UNSUPPORT_TYPE, "unsupported type")
|
||||
|
||||
ErrNotExist error = nodeNotExist
|
||||
ErrUnsupportType error = nodeUnsupportType
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
p int
|
||||
|
|
@ -330,20 +341,24 @@ func (self *Parser) skip() (int, types.ParsingError) {
|
|||
/** Parser Factory **/
|
||||
|
||||
// Loads parse all json into interface{}
|
||||
func Loads(src string) (int, interface{}, types.ParsingError) {
|
||||
func Loads(src string) (int, interface{}, error) {
|
||||
ps := &Parser{s: src}
|
||||
np, err := ps.Parse()
|
||||
|
||||
/* check for errors */
|
||||
if err != 0 {
|
||||
return 0, nil, err
|
||||
return 0, nil, ps.ExportError(err)
|
||||
} else {
|
||||
return ps.Pos(), np.Interface(), 0
|
||||
x, err := np.Interface()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return ps.Pos(), x, nil
|
||||
}
|
||||
}
|
||||
|
||||
// LoadsUseNumber parse all json into interface{}, with numeric nodes casted to json.Number
|
||||
func LoadsUseNumber(src string) (int, interface{}, types.ParsingError) {
|
||||
func LoadsUseNumber(src string) (int, interface{}, error) {
|
||||
ps := &Parser{s: src}
|
||||
np, err := ps.Parse()
|
||||
|
||||
|
|
@ -351,7 +366,11 @@ func LoadsUseNumber(src string) (int, interface{}, types.ParsingError) {
|
|||
if err != 0 {
|
||||
return 0, nil, err
|
||||
} else {
|
||||
return ps.Pos(), np.InterfaceUseNumber(), 0
|
||||
x, err := np.InterfaceUseNumber()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return ps.Pos(), x, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -362,11 +381,19 @@ func NewParser(src string) *Parser {
|
|||
// ExportError converts types.ParsingError to std Error
|
||||
func (self *Parser) ExportError(err types.ParsingError) error {
|
||||
if err == _ERR_NOT_FOUND {
|
||||
return fmt.Errorf("node not exists")
|
||||
return ErrNotExist
|
||||
}
|
||||
return fmt.Errorf("%q", decoder.SyntaxError{
|
||||
Pos: self.p,
|
||||
Src: self.s,
|
||||
Pos : self.p,
|
||||
Src : self.s,
|
||||
Code: err,
|
||||
}.Description())
|
||||
}
|
||||
|
||||
func (self *Parser) syntaxError(err types.ParsingError) *decoder.SyntaxError {
|
||||
return &decoder.SyntaxError{
|
||||
Pos : self.p,
|
||||
Src : self.s,
|
||||
Code: err,
|
||||
}
|
||||
}
|
||||
|
|
@ -28,13 +28,14 @@ import (
|
|||
func runDecoderTest(t *testing.T, src string, expect interface{}) {
|
||||
vv, err := NewParser(src).Parse()
|
||||
if err != 0 { panic(err) }
|
||||
assert.Equal(t, expect, vv.Interface())
|
||||
x, _ := vv.Interface()
|
||||
assert.Equal(t, expect, x)
|
||||
}
|
||||
|
||||
func runDecoderTestUseNumber(t *testing.T, src string, expect interface{}) {
|
||||
vv, err := NewParser(src).Parse()
|
||||
if err != 0 { panic(err) }
|
||||
vvv := vv.InterfaceUseNumber()
|
||||
vvv, _ := vv.InterfaceUseNumber()
|
||||
switch vvv.(type) {
|
||||
case json.Number:
|
||||
assert.Equal(t, expect, n2f64(vvv.(json.Number)))
|
||||
|
|
@ -156,12 +157,12 @@ func TestParser_Basic(t *testing.T) {
|
|||
|
||||
func TestLoads(t *testing.T) {
|
||||
_,i,e := Loads(`{"a": "123", "b": true, "c": false, "d": null, "e": 2.4, "f": 1.2e15, "g": 1}`)
|
||||
if e != 0 {
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
assert.Equal(t, map[string]interface{}{"a": "123", "b": true, "c": false, "d": nil, "e": 2.4, "f": 1.2e15, "g": float64(1)}, i)
|
||||
_,i,e = LoadsUseNumber(`{"a": "123", "b": true, "c": false, "d": null, "e": 2.4, "f": 1.2e15, "g": 1}`)
|
||||
if e != 0 {
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
assert.Equal(t, map[string]interface{}{"a": "123", "b": true, "c": false, "d": nil, "e": json.Number("2.4"), "f": json.Number("1.2e15"), "g": json.Number("1")}, i)
|
||||
|
|
@ -284,7 +285,7 @@ func BenchmarkGetOne_Sonic(b *testing.B) {
|
|||
b.SetBytes(int64(len(_TwitterJson)))
|
||||
for i := 0; i < b.N; i++ {
|
||||
ast, _ := NewParser(_TwitterJson).Parse()
|
||||
node := ast.Get("statuses").Index(2).Get("id").Int64()
|
||||
node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
|
||||
if node != 249289491129438208 {
|
||||
b.Fail()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,27 +60,32 @@ func TestSearcher_GetByPath(t *testing.T) {
|
|||
s := NewSearcher(` { "xx" : [] ,"yy" :{ }, "test" : [ true , 0.1 , "abc", ["h"], {"a":"bc"} ] } `)
|
||||
|
||||
node, e := s.GetByPath("test", 0)
|
||||
if e != nil || node.Bool() != true {
|
||||
a, _ := node.Bool()
|
||||
if e != nil || a != true {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = s.GetByPath("test", 1)
|
||||
if e != nil || node.Float64() != 0.1 {
|
||||
b, _ := node.Float64()
|
||||
if e != nil || b != 0.1 {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = s.GetByPath("test", 2)
|
||||
if e != nil || node.String() != "abc" {
|
||||
c, _ := node.String()
|
||||
if e != nil || c != "abc" {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = s.GetByPath("test", 3)
|
||||
if e != nil || node.Array()[0] != "h" {
|
||||
arr, _ := node.Array()
|
||||
if e != nil || arr[0] != "h" {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = s.GetByPath("test", 4, "a")
|
||||
if e != nil || node.String() != "bc" {
|
||||
d, _ := node.String()
|
||||
if e != nil || d != "bc" {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
}
|
||||
|
|
@ -123,9 +128,9 @@ func TestLoadIndex(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a := node.Index(3).Float64()
|
||||
a, _ := node.Index(3).Float64()
|
||||
assert.Equal(t, -1.2e-10, a)
|
||||
m := node.Array()
|
||||
m, _ := node.Array()
|
||||
assert.Equal(t, m, []interface{}{
|
||||
float64(0),
|
||||
float64(1),
|
||||
|
|
@ -185,7 +190,8 @@ func BenchmarkSearchOne_Sonic(b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if node.Int64() != 249279667666817024 {
|
||||
x, _ := node.Int64()
|
||||
if x != 249279667666817024 {
|
||||
b.Fatal(node.Interface())
|
||||
}
|
||||
}
|
||||
|
|
@ -230,7 +236,8 @@ func BenchmarkSearchOne_Parallel_Sonic(b *testing.B) {
|
|||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if node.Int64() != 249279667666817024 {
|
||||
x, _ := node.Int64()
|
||||
if x != 249279667666817024 {
|
||||
b.Fatal(node.Interface())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,27 +48,32 @@ func TestExampleSearch(t *testing.T) {
|
|||
data := []byte(` { "xx" : [] ,"yy" :{ }, "test" : [ true , 0.1 , "abc", ["h"], {"a":"bc"} ] } `)
|
||||
|
||||
node, e := Get(data, "test", 0)
|
||||
if e != nil || node.Bool() != true {
|
||||
x, _ := node.Bool()
|
||||
if e != nil || x != true {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = Get(data, "test", 1)
|
||||
if e != nil || node.Float64() != 0.1 {
|
||||
a, _ := node.Float64()
|
||||
if e != nil || a != 0.1 {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = Get(data, "test", 2)
|
||||
if e != nil || node.String() != "abc" {
|
||||
b, _ := node.String()
|
||||
if e != nil || b != "abc" {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = Get(data, "test", 3)
|
||||
if e != nil || node.Array()[0] != "h" {
|
||||
arr, _ := node.Array()
|
||||
if e != nil || arr[0] != "h" {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
|
||||
node, e = Get(data, "test", 4, "a")
|
||||
if e != nil || node.String() != "bc" {
|
||||
c, _ := node.String()
|
||||
if e != nil || c != "bc" {
|
||||
t.Fatalf("node: %v, err: %v", node, e)
|
||||
}
|
||||
}
|
||||
|
|
@ -148,8 +153,9 @@ func TestRandomValidStrings(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal("search data failed:",err)
|
||||
}
|
||||
if token.Interface().(string) != su {
|
||||
t.Fatalf("string mismatch, exp: %v, got: %v", su, token.Interface())
|
||||
x, _ := token.Interface()
|
||||
if x.(string) != su {
|
||||
t.Fatalf("string mismatch, exp: %v, got: %v", su, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -166,8 +172,9 @@ func TestEmoji(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
s, _ := v["utf8"].(string)
|
||||
if value.String() != s {
|
||||
t.Fatalf("expected '%v', got '%v'", s, value.String())
|
||||
x, _ := value.String()
|
||||
if x != s {
|
||||
t.Fatalf("expected '%v', got '%v'", s, x)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -176,8 +183,10 @@ func testEscapePath(t *testing.T, json, expect string, path ...interface{}) {
|
|||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
if n.String() != expect {
|
||||
t.Fatalf("expected '%v', got '%v'", expect, n.Interface())
|
||||
x, _ := n.String()
|
||||
if x != expect {
|
||||
x, _ := n.Interface()
|
||||
t.Fatalf("expected '%v', got '%v'", expect, x)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,19 +222,23 @@ func TestParseAny(t *testing.T) {
|
|||
if n == nil {
|
||||
panic("n is nil")
|
||||
}
|
||||
assertCond(n.Float64() == 100)
|
||||
x, _ := n.Float64()
|
||||
assertCond(x == 100)
|
||||
n, e = Parse("true")
|
||||
assertCond(e == nil)
|
||||
if n == nil {
|
||||
panic("n is nil")
|
||||
}
|
||||
assertCond(n.Bool())
|
||||
|
||||
a, _ := n.Bool()
|
||||
assertCond(a)
|
||||
n, e = Parse("false")
|
||||
assertCond(e == nil)
|
||||
if n == nil {
|
||||
panic("n is nil")
|
||||
}
|
||||
assertCond(n.Bool() == false)
|
||||
b, _ := n.Bool()
|
||||
assertCond(b == false)
|
||||
n, e = Parse("yikes")
|
||||
assertCond(e != nil)
|
||||
}
|
||||
|
|
@ -263,7 +276,9 @@ func TestTime(t *testing.T) {
|
|||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
for _, v := range n.Array() {
|
||||
|
||||
arr, _ := n.Array()
|
||||
for _, v := range arr {
|
||||
s := v.(string)
|
||||
num = append(num, s)
|
||||
}
|
||||
|
|
@ -303,7 +318,7 @@ func TestUnmarshalMap(t *testing.T) {
|
|||
if err != nil || n == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m1 := n.Map()
|
||||
m1, _ := n.Map()
|
||||
var m2 map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(exampleJSON), &m2); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -337,7 +352,8 @@ func GetMany(src2 string, path ...string) (ret []string) {
|
|||
ret = append(ret, "")
|
||||
continue
|
||||
}
|
||||
ret = append(ret, fmt.Sprintf("%v", n.Interface()))
|
||||
x, _ := n.Interface()
|
||||
ret = append(ret, fmt.Sprintf("%v", x))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -361,7 +377,7 @@ func get(str string, path string) *ast.Node {
|
|||
|
||||
func TestSingleArrayValue(t *testing.T) {
|
||||
var data = []byte(`{"key": "value","key2":[1,2,3,4,"A"]}`)
|
||||
array := get(string(data), "key2").Array()
|
||||
array, _ := get(string(data), "key2").Array()
|
||||
if len(array) != 5 {
|
||||
t.Fatalf("got '%v', expected '%v'", len(array), 5)
|
||||
}
|
||||
|
|
@ -392,6 +408,7 @@ var manyJSON = ` {
|
|||
|
||||
func TestManyBasic(t *testing.T) {
|
||||
testMany := func(shouldFallback bool, expect string, paths ...string) {
|
||||
println()
|
||||
rs := GetMany(
|
||||
manyJSON,
|
||||
paths...,
|
||||
|
|
@ -413,7 +430,8 @@ func TestManyBasic(t *testing.T) {
|
|||
testMany(true, `[]`, strings.Repeat("a.", 40)+"hello")
|
||||
res := get(manyJSON, strings.Repeat("a.", 48)+"a")
|
||||
assertCond(res != nil)
|
||||
testMany(true, "["+fmt.Sprint(res.Interface())+"]", strings.Repeat("a.", 48)+"a")
|
||||
x, _ := res.Interface()
|
||||
testMany(true, "["+fmt.Sprint(x)+"]", strings.Repeat("a.", 48)+"a")
|
||||
// these should fallback
|
||||
testMany(true, `[Cat Nancy]`, "name_first", "name.first")
|
||||
testMany(true, `[world]`, strings.Repeat("a.", 70)+"hello")
|
||||
|
|
@ -432,7 +450,8 @@ func testManyAny(t *testing.T, json string, paths, expected []string) {
|
|||
which = "Get"
|
||||
result = nil
|
||||
for j := 0; j < len(expected); j++ {
|
||||
result = append(result, fmt.Sprintf("%v", get(json, paths[j]).Interface()))
|
||||
x, _ := get(json, paths[j]).Interface()
|
||||
result = append(result, fmt.Sprintf("%v", x))
|
||||
}
|
||||
} else if i == 1 {
|
||||
which = "GetMany"
|
||||
|
|
@ -546,7 +565,7 @@ func TestGetMany2(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNullArray(t *testing.T) {
|
||||
n := get(`{"data":null}`, "data").Interface()
|
||||
n, _ := get(`{"data":null}`, "data").Interface()
|
||||
if n != nil {
|
||||
t.Fatalf("expected '%v', got '%v'", nil, n)
|
||||
}
|
||||
|
|
@ -558,7 +577,8 @@ func TestNullArray(t *testing.T) {
|
|||
if reflect.DeepEqual(n, &ast.Node{}) {
|
||||
t.Fatalf("expected '%v', got '%v'", nil, n)
|
||||
}
|
||||
n = len(get(`{"data":[null]}`, "data").Array())
|
||||
arr, _ := get(`{"data":[null]}`, "data").Array()
|
||||
n = len(arr)
|
||||
if n != 1 {
|
||||
t.Fatalf("expected '%v', got '%v'", 1, n)
|
||||
}
|
||||
|
|
@ -613,7 +633,11 @@ func TestGetNotExist(t *testing.T) {
|
|||
t.Fatal()
|
||||
}
|
||||
v2 := ret.GetByPath("m1", "m2")
|
||||
if !v2.Exists() || !v2.IsRaw() || v2.Int64() != 3 {
|
||||
if !v2.Exists() || !v2.IsRaw() {
|
||||
t.Fatal(ret.Type())
|
||||
}
|
||||
x, _ := v2.Int64()
|
||||
if x != 3 {
|
||||
t.Fatal(x)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue