2019-02-26 13:05:15 +04:00
package jsonpath
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
type test struct {
name string
json string
path string
expected [ ] Result
}
var tests = [ ] test {
2019-10-19 01:41:57 +04:00
{ ` 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 ` ) } } ,
2019-10-19 00:39:21 +04:00
2019-10-19 01:41:57 +04:00
{ ` 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 ) } } ,
2019-10-19 00:39:21 +04:00
{ ` array range (no index) selection ` , ` { "aKey":[11,22,33,44]} ` , ` $.aKey[1:1]+ ` , [ ] Result { } } ,
2019-10-19 01:41:57 +04:00
{ ` array range (no upper bound) selection ` , ` { "aKey":[11,22,33]} ` , ` $.aKey[1:]+ ` , [ ] Result { newResult ( ` 22 ` , JSONNumber , ` aKey ` , 1 ) , newResult ( ` 33 ` , JSONNumber , ` aKey ` , 2 ) } } ,
2019-10-19 00:39:21 +04:00
{ ` empty array - try selection ` , ` { "aKey":[]} ` , ` $.aKey[1]+ ` , [ ] Result { } } ,
2019-10-19 01:41:57 +04:00
{ ` 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 ) } } ,
2019-10-19 00:39:21 +04:00
2019-10-19 01:41:57 +04:00
{ ` 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 ` ) } } ,
2019-02-26 13:05:15 +04:00
}
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 )
2019-10-19 01:41:57 +04:00
2019-02-26 13:05:15 +04:00
if as . NoError ( eval . Error ) {
as . EqualValues ( t . expected , res , "Testing of %q" , t . name )
}
}
2019-10-19 01:41:57 +04:00
evalReader , err := EvalPathsInReader ( strings . NewReader ( t . json ) , paths )
2019-02-26 13:05:15 +04:00
if as . NoError ( err , "Testing: %s" , t . name ) {
2019-10-19 01:41:57 +04:00
res := toResultArray ( evalReader )
2019-02-26 13:05:15 +04:00
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 ) )
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
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 )
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
for {
if r , ok := e . Next ( ) ; ok {
if r != nil {
vals = append ( vals , * r )
}
} else {
break
}
}
2019-10-19 02:14:19 +04:00
2019-02-26 13:05:15 +04:00
return vals
}