jsonpath: use ordered map json unmarshaler

This commit is contained in:
Evgeniy Stratonikov 2021-05-07 19:48:57 +03:00
parent 6890688b8f
commit 5fc81c787b
5 changed files with 32 additions and 24 deletions

1
go.mod
View file

@ -19,6 +19,7 @@ require (
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.6.1
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73 github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73
github.com/urfave/cli v1.20.0 github.com/urfave/cli v1.20.0
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74
go.etcd.io/bbolt v1.3.4 go.etcd.io/bbolt v1.3.4
go.uber.org/atomic v1.4.0 go.uber.org/atomic v1.4.0
go.uber.org/zap v1.10.0 go.uber.org/zap v1.10.0

2
go.sum
View file

@ -230,6 +230,8 @@ github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2K
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo=
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7 h1:Y17pEjKgx2X0A69WQPGa8hx/Myzu+4NdUxlkZpbAYio= github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7 h1:Y17pEjKgx2X0A69WQPGa8hx/Myzu+4NdUxlkZpbAYio=

View file

@ -1,21 +1,27 @@
package oracle package oracle
import ( import (
"encoding/json" "bytes"
"errors" "errors"
"unicode/utf8" "unicode/utf8"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/services/oracle/jsonpath" "github.com/nspcc-dev/neo-go/pkg/services/oracle/jsonpath"
json "github.com/virtuald/go-ordered-json"
) )
func filter(value []byte, path string) ([]byte, error) { func filter(value []byte, path string) ([]byte, error) {
if !utf8.Valid(value) { if !utf8.Valid(value) {
return nil, errors.New("not an UTF-8") return nil, errors.New("not an UTF-8")
} }
buf := bytes.NewBuffer(value)
d := json.NewDecoder(buf)
d.UseOrderedObject()
var v interface{} var v interface{}
if err := json.Unmarshal(value, &v); err != nil { if err := d.Decode(&v); err != nil {
return nil, err return nil, err
} }

View file

@ -1,10 +1,10 @@
package jsonpath package jsonpath
import ( import (
"encoding/json"
"sort"
"strconv" "strconv"
"strings" "strings"
json "github.com/virtuald/go-ordered-json"
) )
type ( type (
@ -193,16 +193,9 @@ func (p *pathParser) descend(objs []interface{}) ([]interface{}, bool) {
switch obj := objs[i].(type) { switch obj := objs[i].(type) {
case []interface{}: case []interface{}:
values = append(values, obj...) values = append(values, obj...)
case map[string]interface{}: case json.OrderedObject:
keys := make([]string, 0, len(obj)) for i := range obj {
for k := range obj { values = append(values, obj[i].Value)
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
values = append(values, obj[k])
} }
} }
} }
@ -243,14 +236,17 @@ func (p *pathParser) descendByIdentAux(objs []interface{}, checkDepth bool, name
var values []interface{} var values []interface{}
for i := range objs { for i := range objs {
obj, ok := objs[i].(map[string]interface{}) obj, ok := objs[i].(json.OrderedObject)
if !ok { if !ok {
continue continue
} }
for j := range names { for j := range names {
if v, ok := obj[names[j]]; ok { for k := range obj {
values = append(values, v) if obj[k].Key == names[j] {
values = append(values, obj[k].Value)
break
}
} }
} }
} }

View file

@ -1,12 +1,13 @@
package jsonpath package jsonpath
import ( import (
"encoding/json" "bytes"
"math" "math"
"strconv" "strconv"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
json "github.com/virtuald/go-ordered-json"
) )
type pathTestCase struct { type pathTestCase struct {
@ -16,7 +17,10 @@ type pathTestCase struct {
func unmarshalGet(t *testing.T, js string, path string) ([]interface{}, bool) { func unmarshalGet(t *testing.T, js string, path string) ([]interface{}, bool) {
var v interface{} var v interface{}
require.NoError(t, json.Unmarshal([]byte(js), &v)) buf := bytes.NewBuffer([]byte(js))
d := json.NewDecoder(buf)
d.UseOrderedObject()
require.NoError(t, d.Decode(&v))
return Get(path, v) return Get(path, v)
} }
@ -94,8 +98,8 @@ func TestDescendByIdent(t *testing.T) {
testCases := []pathTestCase{ testCases := []pathTestCase{
{"$.store.name", `["big"]`}, {"$.store.name", `["big"]`},
{"$['store']['name']", `["big"]`}, {"$['store']['name']", `["big"]`},
{"$[*].name", `["small","big"]`}, {"$[*].name", `["big","small"]`},
{"$.*.name", `["small","big"]`}, {"$.*.name", `["big","small"]`},
{"$..store.name", `["big"]`}, {"$..store.name", `["big"]`},
{"$.store..name", `["big","ppp","sub1","sub2"]`}, {"$.store..name", `["big","ppp","sub1","sub2"]`},
{"$..sub.name", `[]`}, {"$..sub.name", `[]`},
@ -248,11 +252,10 @@ func TestCSharpCompat(t *testing.T) {
"expensive": 10 "expensive": 10
}` }`
// FIXME(fyrchik): some tests are commented because of how maps are processed.
testCases := []pathTestCase{ testCases := []pathTestCase{
{"$.store.book[*].author", `["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]`}, {"$.store.book[*].author", `["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]`},
{"$..author", `["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]`}, {"$..author", `["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]`},
//{"$.store.*", `[[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],{"color":"red","price":19.95}]`}, {"$.store.*", `[[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],{"color":"red","price":19.95}]`},
{"$.store..price", `[19.95,8.95,12.99,8.99,22.99]`}, {"$.store..price", `[19.95,8.95,12.99,8.99,22.99]`},
{"$..book[2]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]`}, {"$..book[2]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]`},
{"$..book[-2]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]`}, {"$..book[-2]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]`},
@ -261,7 +264,7 @@ func TestCSharpCompat(t *testing.T) {
{"$..book[1:2]", `[{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]`}, {"$..book[1:2]", `[{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]`},
{"$..book[-2:]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]`}, {"$..book[-2:]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]`},
{"$..book[2:]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]`}, {"$..book[2:]", `[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]`},
//{"$..*", `[{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}},10,[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],{"color":"red","price":19.95},{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99},"red",19.95,"reference","Nigel Rees","Sayings of the Century",8.95,"fiction","Evelyn Waugh","Sword of Honour",12.99,"fiction","Herman Melville","Moby Dick","0-553-21311-3",8.99,"fiction","J. R. R. Tolkien","The Lord of the Rings","0-395-19395-8",22.99]`}, {"$.*", `[{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}},10]`},
{"$..invalidfield", `[]`}, {"$..invalidfield", `[]`},
} }