107 lines
4.5 KiB
Go
107 lines
4.5 KiB
Go
package jsonpath
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
type test struct {
|
|
name string
|
|
json string
|
|
path string
|
|
expected []Result
|
|
}
|
|
|
|
var tests = []test{
|
|
{`key selection`, `{"aKey":32}`, `$.aKey+`, []Result{newResult(`32`, JSONNumber, `aKey`)}},
|
|
{`nested key selection`, `{"aKey":{"bKey":32}}`, `$.aKey+`, []Result{newResult(`{"bKey":32}`, JSONObject, `aKey`)}},
|
|
{`empty array`, `{"aKey":[]}`, `$.aKey+`, []Result{newResult(`[]`, JSONArray, `aKey`)}},
|
|
{`multiple same-level keys, weird spacing`, `{ "aKey" : true , "bKey": [ 1 , 2 ], "cKey" : true } `, `$.bKey+`, []Result{newResult(`[1,2]`, JSONArray, `bKey`)}},
|
|
|
|
{`array index selection`, `{"aKey":[123,456]}`, `$.aKey[1]+`, []Result{newResult(`456`, JSONNumber, `aKey`, 1)}},
|
|
{`array wild index selection`, `{"aKey":[123,456]}`, `$.aKey[*]+`, []Result{newResult(`123`, JSONNumber, `aKey`, 0), newResult(`456`, JSONNumber, `aKey`, 1)}},
|
|
{`array range index selection`, `{"aKey":[11,22,33,44]}`, `$.aKey[1:3]+`, []Result{newResult(`22`, JSONNumber, `aKey`, 1), newResult(`33`, JSONNumber, `aKey`, 2)}},
|
|
{`array range (no index) selection`, `{"aKey":[11,22,33,44]}`, `$.aKey[1:1]+`, []Result{}},
|
|
{`array range (no upper bound) selection`, `{"aKey":[11,22,33]}`, `$.aKey[1:]+`, []Result{newResult(`22`, JSONNumber, `aKey`, 1), newResult(`33`, JSONNumber, `aKey`, 2)}},
|
|
|
|
{`empty array - try selection`, `{"aKey":[]}`, `$.aKey[1]+`, []Result{}},
|
|
{`null selection`, `{"aKey":[null]}`, `$.aKey[0]+`, []Result{newResult(`null`, JSONNull, `aKey`, 0)}},
|
|
{`empty object`, `{"aKey":{}}`, `$.aKey+`, []Result{newResult(`{}`, JSONObject, `aKey`)}},
|
|
{`object w/ height=2`, `{"aKey":{"bKey":32}}`, `$.aKey.bKey+`, []Result{newResult(`32`, JSONNumber, `aKey`, `bKey`)}},
|
|
{`array of multiple types`, `{"aKey":[1,{"s":true},"asdf"]}`, `$.aKey[1]+`, []Result{newResult(`{"s":true}`, JSONObject, `aKey`, 1)}},
|
|
{`nested array selection`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey+`, []Result{newResult(`[123,456]`, JSONArray, `aKey`, `bKey`)}},
|
|
{`nested array`, `[[[[[]], [true, false, []]]]]`, `$[0][0][1][2]+`, []Result{newResult(`[]`, JSONArray, 0, 0, 1, 2)}},
|
|
{`index of array selection`, `{"aKey":{"bKey":[123, 456, 789]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JSONNumber, `aKey`, `bKey`, 1)}},
|
|
{`index of array selection (more than one)`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JSONNumber, `aKey`, `bKey`, 1)}},
|
|
{`multi-level object/array`, `{"1Key":{"aKey": null, "bKey":{"trash":[1,2]}, "cKey":[123,456] }, "2Key":false}`, `$.1Key.bKey.trash[0]+`, []Result{newResult(`1`, JSONNumber, `1Key`, `bKey`, `trash`, 0)}},
|
|
{`multi-level array`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*].michael[1]+`, []Result{newResult(`6`, JSONNumber, `aKey`, 3, `michael`, 1)}},
|
|
{`multi-level array 2`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*][1]+`, []Result{newResult(`"3"`, JSONString, `aKey`, 4, 1)}},
|
|
|
|
{`evaluation literal equality`, `{"items":[ {"name":"alpha", "value":11}]}`, `$.items[*]?("bravo" == "bravo").value+`, []Result{newResult(`11`, JSONNumber, `items`, 0, `value`)}},
|
|
{`evaluation based on string equal to path value`, `{"items":[ {"name":"alpha", "value":11}, {"name":"bravo", "value":22}, {"name":"charlie", "value":33} ]}`, `$.items[*]?(@.name == "bravo").value+`, []Result{newResult(`22`, JSONNumber, `items`, 1, `value`)}},
|
|
}
|
|
|
|
func TestPathQuery(t *testing.T) {
|
|
as := assert.New(t)
|
|
|
|
for _, t := range tests {
|
|
paths, err := ParsePaths(t.path)
|
|
if as.NoError(err) {
|
|
eval, err := EvalPathsInBytes([]byte(t.json), paths)
|
|
if as.NoError(err, "Testing: %s", t.name) {
|
|
res := toResultArray(eval)
|
|
|
|
if as.NoError(eval.Error) {
|
|
as.EqualValues(t.expected, res, "Testing of %q", t.name)
|
|
}
|
|
}
|
|
|
|
evalReader, err := EvalPathsInReader(strings.NewReader(t.json), paths)
|
|
if as.NoError(err, "Testing: %s", t.name) {
|
|
res := toResultArray(evalReader)
|
|
|
|
if as.NoError(eval.Error) {
|
|
as.EqualValues(t.expected, res, "Testing of %q", t.name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func newResult(value string, typ int, keys ...interface{}) Result {
|
|
keysChanged := make([]interface{}, len(keys))
|
|
|
|
for i, k := range keys {
|
|
switch v := k.(type) {
|
|
case string:
|
|
keysChanged[i] = []byte(v)
|
|
default:
|
|
keysChanged[i] = v
|
|
}
|
|
}
|
|
|
|
return Result{
|
|
Value: []byte(value),
|
|
Keys: keysChanged,
|
|
Type: typ,
|
|
}
|
|
}
|
|
|
|
func toResultArray(e *Eval) []Result {
|
|
vals := make([]Result, 0)
|
|
|
|
for {
|
|
if r, ok := e.Next(); ok {
|
|
if r != nil {
|
|
vals = append(vals, *r)
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
return vals
|
|
}
|