We follow RFC 9535 strictly and test against the JSONPath Compliance Test Suite.
Table of Contents
Install Python JSONPath RFC 9535 using pip:
pip install jsonpath-rfc9535
Or Pipenv:
pipenv install -u jsonpath-rfc9535
import jsonpath_rfc9535 as jsonpath
data = {
"users": [
{"name": "Sue", "score": 100},
{"name": "Sally", "score": 84, "admin": False},
{"name": "John", "score": 86, "admin": True},
{"name": "Jane", "score": 55},
],
"moderator": "John",
}
for node in jsonpath.find("$.users[[email protected] > 85]", data):
print(node.value)
# {'name': 'Sue', 'score': 100}
# {'name': 'John', 'score': 86, 'admin': True}Or, reading JSON data from a file:
import json
import jsonpath_rfc9535 as jsonpath
with open("/path/to/some.json", encoding="utf-8") as fd:
data = json.load(fd)
nodes = jsonpath.find("$.some.query", data)
values = nodes.values()
# ...You could read data from a YAML formatted file too. If you have PyYaml installed:
import jsonpath_rfc9535 as jsonpath
import yaml
with open("some.yaml") as fd:
data = yaml.safe_load(fd)
products = jsonpath.find("$..products.*", data).values()
# ...- Change log: https://github.com/jg-rp/python-jsonpath-rfc9535/blob/main/CHANGELOG.md
- PyPi: https://pypi.org/project/jsonpath-rfc9535
- Source code: https://github.com/jg-rp/python-jsonpath-rfc9535
- Issue tracker: https://github.com/jg-rp/python-jsonpath-rfc9535/issues
- Python JSONPath - Another Python package implementing JSONPath, but with additional features and customization options.
- JSON P3 - RFC 9535 implemented in TypeScript.
find(query: str, value: JSONValue) -> JSONPathNodeList
Apply JSONPath expression query to value. value should arbitrary, possible nested, Python dictionaries, lists, strings, integers, floats, Booleans or None, as you would get from json.load().
A list of JSONPathNode instances is returned, one node for each value matched by query. The returned list will be empty if there were no matches.
Each JSONPathNode has properties:
value- The JSON-like value associated with the node.location- A tuple of property names and array/list indexes that were required to reach the node's value in the target JSON document.parent(New in version 0.2.0) - The node's parent node, orNoneif the current node is the root.
import jsonpath_rfc9535 as jsonpath
data = {
"users": [
{"name": "Sue", "score": 100},
{"name": "John", "score": 86, "admin": True},
{"name": "Sally", "score": 84, "admin": False},
{"name": "Jane", "score": 55},
],
"moderator": "John",
}
nodes = jsonpath.find("$.users[[email protected] > 85]", data)
for node in nodes:
print(f"{node.value} at '{node.path()}'")
# {'name': 'Sue', 'score': 100} at '$['users'][0]'
# {'name': 'John', 'score': 86, 'admin': True} at '$['users'][1]'JSONPathNode.path() returns the normalized path to the node in the target JSON document.
JSONPathNodeList is a subclass of list with some helper methods.
values()returns a list of values, one for each node.items()returns a list of(normalized path, value)tuples.
New in version 0.2.0
Assigning to JSONPathNode.value will update the node's value and mutate source data. Beware,updating data after evaluating a query can invalidate existing child node paths.
# ... continued from above
node = jsonpath.find_one("$.users[@.name == 'John'].score")
if node:
node.value = 999
print(data["users"][1]) # {'name': 'John', 'score': 999, 'admin': True}find_one(query: str, value: JSONValue) -> Optional[JSONPathNode]
find_one() accepts the same arguments as find(), but returns the first available JSONPathNode, or None if there were no matches.
find_one() is equivalent to:
def find_one(query, value):
try:
return next(iter(jsonpath.finditer(query, value)))
except StopIteration:
return Nonefinditer(query: str, value: JSONValue) -> Iterable[JSONPathNode]
finditer() accepts the same arguments as find(), but returns an iterator over JSONPathNode instances rather than a list. This could be useful if you're expecting a large number of results that you don't want to load into memory all at once.
compile(query: str) -> JSONPathQuery
find(query, value) is a convenience function for JSONPathEnvironment().compile(query).apply(value). Use compile(query) to obtain a JSONPathQuery instance which can be applied to difference JSON-like values repeatedly.
import jsonpath_rfc9535 as jsonpath
value = {
"users": [
{"name": "Sue", "score": 100},
{"name": "John", "score": 86, "admin": True},
{"name": "Sally", "score": 84, "admin": False},
{"name": "Jane", "score": 55},
],
"moderator": "John",
}
query = jsonpath.compile("$.users[[email protected] > 85]")
for node in query.apply(value):
print(f"{node.value} at '{node.path()}'")
# {'name': 'Sue', 'score': 100} at '$['users'][0]'
# {'name': 'John', 'score': 86, 'admin': True} at '$['users'][1]'A JSONPathQuery has a finditer(value) method too, and find(value) is an alias for apply(value).
python-jsonpath-rfc9535 is distributed under the terms of the MIT license.