Five typed functions are standard: length() of a string, array or object; count() of a nodelist; match() and search(), which test an I-Regexp (RFC 9485) against the whole string or any part of it; and value(), which unwraps a single-node nodelist.
import itertools, json
import jsonpath
books = json.load(open("data/books.json", encoding="utf-8"))
orders = [json.loads(s) for s in itertools.islice(open("data/orders.jsonl"), 12)]
for query, data in [("$.books[?length(@.title) > 22].id", books),
("$.books[?match(@.genre, 'Science')].id", books),
("$.books[?search(@.genre, 'Science')].id", books),
("$[?count(@.items[*]) == 3].order_id", orders),
("$[?value(@.items[*].qty) == 2].order_id", orders)]:
print(f"{query:52} {jsonpath.findall(query, data)}")Output
$.books[?length(@.title) > 22].id [2, 4, 5] $.books[?match(@.genre, 'Science')].id [] $.books[?search(@.genre, 'Science')].id [5] $[?count(@.items[*]) == 3].order_id [2, 5] $[?value(@.items[*].qty) == 2].order_id [9]
match is anchored at both ends, so 'Science' misses "Science Fiction". value() yields Nothing for several nodes, so the last query keeps only single-line orders.