Selectors and Filters

Selectors, Slices and Filter Expressions

RFC 9535 has five selectors: a name (['title'] or .title), the wildcard *, an index ([-1] counts from the end), a slice ([start:end:step]) and a filter ([?expr], with @ as the current node and &&, ||, !). The descendant segment .. searches every depth.

RFC 9535 selectors on BookNest's catalogJavaScript
import json
import jsonpath
books = json.load(open("data/books.json", encoding="utf-8"))
for query in ["$.books[-1].title", "$.books[::2].id", "$.books[?@.price > 20].id",
              "$..books[?@.inStock == false && @.rating > 4].author"]:
    print(f"{query:52} {jsonpath.findall(query, books)}")
match = next(jsonpath.finditer("$.books[?@.year == 2026].title", books))
print(match.path, "->", match.obj)
Output
$.books[-1].title                                    ['Gardens in Glass']
$.books[::2].id                                      [1, 3, 5]
$.books[?@.price > 20].id                            [2, 3, 6]
$..books[?@.inStock == false && @.rating > 4].author ['Priya Nair']
$['books'][3]['title'] -> Small Steps to Big Summits

Filters never raise errors: comparing a string with a number, or testing a missing member, is simply false.