Skip to content

Commit 2f8d57c

Browse files
peter-jozsaJózsa Péter
andauthored
Fix problem when filtering a root array (#21)
* Fixes a problem when filtering a root array * Support expressions on the right side of equations with array roots. --------- Co-authored-by: Józsa Péter <jozsa.peter@pwstudio.hu>
1 parent 2e52cf6 commit 2f8d57c

2 files changed

Lines changed: 98 additions & 14 deletions

File tree

jsonpath.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ func tokenize(query string) ([]string, error) {
144144
// token_start := false
145145
// token_end := false
146146
token := ""
147+
open := 0
147148

148149
// fmt.Println("-------------------------------------------------- start")
149150
for idx, x := range query {
@@ -171,14 +172,22 @@ func tokenize(query string) ([]string, error) {
171172
if strings.Contains(token, "[") {
172173
// fmt.Println(" contains [ ")
173174
if x == ']' && !strings.HasSuffix(token, "\\]") {
174-
if token[0] == '.' {
175-
tokens = append(tokens, token[1:])
176-
} else {
177-
tokens = append(tokens, token[:])
175+
open--
176+
177+
if open == 0 {
178+
if token[0] == '.' {
179+
tokens = append(tokens, token[1:])
180+
} else {
181+
tokens = append(tokens, token[:])
182+
}
183+
token = ""
178184
}
179-
token = ""
180185
continue
181186
}
187+
188+
if x == '[' && !strings.HasSuffix(token, "\\[") {
189+
open++
190+
}
182191
} else {
183192
// fmt.Println(" doesn't contains [ ")
184193
if x == '.' {
@@ -359,8 +368,12 @@ func get_key(obj interface{}, key string) (interface{}, error) {
359368
res := []interface{}{}
360369
for i := 0; i < reflect.ValueOf(obj).Len(); i++ {
361370
tmp, _ := get_idx(obj, i)
362-
if v, err := get_key(tmp, key); err == nil {
363-
res = append(res, v)
371+
if key == "" {
372+
res = append(res, tmp)
373+
} else {
374+
if v, err := get_key(tmp, key); err == nil {
375+
res = append(res, v)
376+
}
364377
}
365378
}
366379
return res, nil
@@ -663,7 +676,7 @@ func eval_filter(obj, root interface{}, lp, op, rp string) (res bool, err error)
663676
var rp_v interface{}
664677
if strings.HasPrefix(rp, "@.") {
665678
rp_v, err = filter_get_from_explicit_path(obj, rp)
666-
} else if strings.HasPrefix(rp, "$.") {
679+
} else if strings.HasPrefix(rp, "$.") || strings.HasPrefix(rp, "$[") {
667680
rp_v, err = filter_get_from_explicit_path(root, rp)
668681
} else {
669682
rp_v = rp

jsonpath_test.go

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func Test_jsonpath_JsonPathLookup_1(t *testing.T) {
9696
if res_v, ok := res.([]interface{}); ok != true || res_v[0].(float64) != 8.95 || res_v[1].(float64) != 12.99 || res_v[2].(float64) != 8.99 || res_v[3].(float64) != 22.99 {
9797
t.Errorf("exp: [8.95, 12.99, 8.99, 22.99], got: %v", res)
9898
}
99-
99+
100100
// range
101101
res, err = JsonPathLookup(json_data, "$.store.book[0:1].price")
102102
t.Log(err, res)
@@ -453,7 +453,10 @@ func Test_jsonpath_get_key(t *testing.T) {
453453
},
454454
}
455455
res, err = get_key(obj4, "a")
456-
fmt.Println(err, res)
456+
if res_v, ok := res.([]interface{}); ok != true || len(res_v) != 2 || res_v[0] != 1 || res_v[1] != 2 {
457+
fmt.Println(err, res)
458+
t.Errorf("[]map[string]interface{} support failed")
459+
}
457460
}
458461

459462
func Test_jsonpath_get_idx(t *testing.T) {
@@ -1179,13 +1182,13 @@ func Test_jsonpath_rootnode_is_array_range(t *testing.T) {
11791182
t.Logf("idx: %v, v: %v", idx, v)
11801183
}
11811184
if len(ares) != 2 {
1182-
t.Fatal("len is not 2. got: %v", len(ares))
1185+
t.Fatalf("len is not 2. got: %v", len(ares))
11831186
}
11841187
if ares[0].(float64) != 12.34 {
1185-
t.Fatal("idx: 0, should be 12.34. got: %v", ares[0])
1188+
t.Fatalf("idx: 0, should be 12.34. got: %v", ares[0])
11861189
}
11871190
if ares[1].(float64) != 13.34 {
1188-
t.Fatal("idx: 0, should be 12.34. got: %v", ares[1])
1191+
t.Fatalf("idx: 0, should be 12.34. got: %v", ares[1])
11891192
}
11901193
}
11911194

@@ -1232,7 +1235,7 @@ func Test_jsonpath_rootnode_is_nested_array_range(t *testing.T) {
12321235
t.Logf("idx: %v, v: %v", idx, v)
12331236
}
12341237
if len(ares) != 2 {
1235-
t.Fatal("len is not 2. got: %v", len(ares))
1238+
t.Fatalf("len is not 2. got: %v", len(ares))
12361239
}
12371240

12381241
//FIXME: `$[:1].[0].test` got wrong result
@@ -1243,3 +1246,71 @@ func Test_jsonpath_rootnode_is_nested_array_range(t *testing.T) {
12431246
// t.Fatal("idx: 0, should be 3.1, got: %v", ares[1])
12441247
//}
12451248
}
1249+
1250+
func Test_root_array(t *testing.T) {
1251+
var (
1252+
err error
1253+
books = []map[string]interface{}{
1254+
map[string]interface{}{
1255+
"category": "reference",
1256+
"meta": map[string]interface{}{
1257+
"language": "en",
1258+
"release_year": 1984,
1259+
"available_for_order": false,
1260+
},
1261+
"author": "Nigel Rees",
1262+
"title": "Sayings of the Century",
1263+
"price": 8.95,
1264+
},
1265+
map[string]interface{}{
1266+
"category": "fiction",
1267+
"meta": map[string]interface{}{
1268+
"language": "en",
1269+
"release_year": 2012,
1270+
"availabe_for_order": true,
1271+
},
1272+
"author": "Evelyn Waugh",
1273+
"title": "Sword of Honour",
1274+
"price": 12.99,
1275+
},
1276+
map[string]interface{}{
1277+
"category": "fiction",
1278+
"meta": nil,
1279+
"author": "Herman Melville",
1280+
"title": "Moby Dick",
1281+
"isbn": "0-553-21311-3",
1282+
"price": 8.99,
1283+
},
1284+
}
1285+
)
1286+
1287+
res, err := JsonPathLookup(books, "$[?(@.meta.language == 'en')]")
1288+
if res_v, ok := res.([]interface{}); err != nil || ok == false || len(res_v) != 2 {
1289+
fmt.Println(res, err)
1290+
t.Error("root array support is broken")
1291+
}
1292+
1293+
res2, err := JsonPathLookup(books, "$[?(@.meta)]")
1294+
if res_v, ok := res2.([]interface{}); err != nil || ok == false || len(res_v) != 2 {
1295+
fmt.Println(res2, err)
1296+
t.Error("root array support broken")
1297+
}
1298+
1299+
res3, err := JsonPathLookup(books, "$[-1]")
1300+
if res_v, ok := res3.(map[string]interface{}); err != nil || ok == false || len(res_v) != 6 || res_v["meta"] != nil {
1301+
fmt.Println(res3, err)
1302+
t.Error("root array support broken")
1303+
}
1304+
1305+
res4, err := JsonPathLookup(books, "$[*]")
1306+
if res_v, ok := res4.([]map[string]interface{}); err != nil || ok == false || len(res_v) != 3 {
1307+
fmt.Println(res4, err)
1308+
t.Error("root array support broken")
1309+
}
1310+
1311+
res5, err := JsonPathLookup(books, "$[?(@.meta.language == 'en')].meta.release_year")
1312+
if res_v, ok := res5.([]interface{}); err != nil || ok == false || len(res_v) != 2 {
1313+
fmt.Println(res5, err)
1314+
t.Error("root array support is broken")
1315+
}
1316+
}

0 commit comments

Comments
 (0)