
Security News
Potemkin Understanding in LLMs: New Study Reveals Flaws in AI Benchmarks
New research reveals that LLMs often fake understanding, passing benchmarks but failing to apply concepts or stay internally consistent.
The jsonpath_tp is a jsonpath implementation built on top of treepath technology. Jsonpath is query language for extracting data from json document. The jsonpath_tp attempts to follow the standard defined in jsonpath with the exceptions:
The jsonpath_tp can be used programmatically or via th OS command line interface (CLI) with the addition of jsonpath_cli with package.
All the jsonpath_tp components should be imported as follows:
from jsonpath_tp import get, find
A jsonpath example that gets c's value from json data.
data = {
"a": {
"b": [
{
"c": 1
},
{
"c": 2
}]
}
}
value = get("$.a.b[0].c", data)
assert value == 1
A jsonpath example that gets c's value from json data.
value = [value for value in find("$.a.b[*].c", data)]
assert value == [1, 2]
The examples shown in this README use the following json document. It describes our solar system. Click to expand.
{
"star": {
"name": "Sun",
"diameter": 1391016,
"age": null,
"planets": {
"inner": [
{
"name": "Mercury",
"Number of Moons": "0",
"diameter": 4879,
"has-moons": false
},
{
"name": "Venus",
"Number of Moons": "0",
"diameter": 12104,
"has-moons": false
},
{
"name": "Earth",
"Number of Moons": "1",
"diameter": 12756,
"has-moons": true
},
{
"name": "Mars",
"Number of Moons": "2",
"diameter": 6792,
"has-moons": true
}
],
"outer": [
{
"name": "Jupiter",
"Number of Moons": "79",
"diameter": 142984,
"has-moons": true
},
{
"name": "Saturn",
"Number of Moons": "82",
"diameter": 120536,
"has-moons": true
},
{
"name": "Uranus",
"Number of Moons": "27",
"diameter": 51118,
"has-moons": true
},
{
"name": "Neptune",
"Number of Moons": "14",
"diameter": 49528,
"has-moons": true
}
]
}
}
}
Description | Xpath | jsonpath | treepath |
---|---|---|---|
Find planet earth. | /star/planets/inner[name='Earth'] | $.star.planets.inner[?(@.name=='Earth')] | path.star.planets.inner[*][?(@.name == 'Earth')] |
List the names of all inner planets. | /star/planets/inner[*].name | $.star.planets.inner[*].name | path.star.planets.inner[*].name |
List the names of all planets. | /star/planets/*/name | $.star.planets.[].name | path.star.planets.wc[*].name |
List the names of all celestial bodies | //name | $..name | path.rec.name |
List all nodes in the tree Preorder | //* | $.. | path.rec |
Get the third rock from the sun | /star/planets/inner[3] | $.star.planets.inner[2] | path.star.planets.inner[2] |
List first two inner planets | /star/planets.inner[position()<3] | $.star.planets.inner[:2] | path.star.planets.inner[0:2] |
$.star.planets.inner[0, 1] | path.star.planets.inner[0, 2] | ||
List planets smaller than earth | /star/planets/inner[diameter < 1] | $.star.planets.inner[?(@.diameter < 12756)] | path.star.planets.inner[wc][has(path.diameter < 12756)] |
List celestial bodies that have planets. | //*[planets]/name | $..[?(@.planets)].name | path.rec[?(@.planets)].name |
List the planets with more than 50 moons | $..[?(int(@['Number of Moons']) > 50)].name | path.rec[wc][has(path['Number of Moons'] > 50, int)].name |
The get function returns the first value the path leads to.
Get the star name from the solar_system
sun = get("$.star.name", solar_system)
assert sun == 'Sun'
When there is no match, MatchNotFoundError is thrown.
try:
get("$.star.human_population", solar_system)
assert False, "Not expecting humans on the sun"
except MatchNotFoundError:
pass
Or if preferred, a default value can be given.
human_population = get("$.star.human_population", solar_system, default=0)
assert human_population == 0
In addition to a constant, the default value may also be a callable
def population():
return 0
human_population = get("$.star.human_population", solar_system, default=population)
assert human_population == 0
The default value can be automatically injected in to json document
human_population = get("$.star.human_population", solar_system, default=1, store_default=True)
assert human_population == solar_system['star']["human_population"]
The find function returns an Iterator that iterates to each value the path leads to. Each value is determine on its iteration.
Find All the planet names.
inner_planets = [planet for planet in find("$.star.planets.inner[*].name", solar_system)]
assert inner_planets == ['Mercury', 'Venus', 'Earth', 'Mars']
All the functions: get, find, support tracing. An option, when enabled, records the route the algorithm takes to determine a match.
This example logs the route the algorithm takes to find the inner planets. The print function is give to capture the logs, but any single argument function can be used.
inner_planets = [planet for planet in find("$.star.planets.inner[*].name", solar_system, trace=log_to(print))]
assert inner_planets == ['Mercury', 'Venus', 'Earth', 'Mars']
The results
"""
at $.star got {'name': 'Sun', 'dia...
at $.star.planets got {'inner': [{'name': ...
at $.star.planets.inner got [{'name': 'Mercury',...
at $.star.planets.inner[*] got {'name': 'Mercury', ...
at $.star.planets.inner[0].name got 'Mercury'
at $.star.planets.inner[*] got {'name': 'Venus', 'N...
at $.star.planets.inner[1].name got 'Venus'
at $.star.planets.inner[*] got {'name': 'Earth', 'N...
at $.star.planets.inner[2].name got 'Earth'
at $.star.planets.inner[*] got {'name': 'Mars', 'Nu...
at $.star.planets.inner[3].name got 'Mars'
"""
The $ point to root of the tree.
value = get("$", solar_system)
assert value == solar_system
In a filter, the @ point to the current element.
value = get("$.star[?(@ == 'Sun')]", solar_system)
assert value == 'Sun'
The dictionary keys are referenced as dynamic attributes on a path.
inner_from_attribute = get("$.star.planets.inner", solar_system)
inner_from_string_keys = get("$.['star']['planets']['inner']", solar_system)
assert inner_from_attribute == inner_from_string_keys == solar_system['star']['planets']['inner']
Dictionary keys that are not valid python syntax can be referenced as quoted strings.
sun_equatorial_diameter = get("$.star.planets.inner[0]['Number of Moons']", solar_system)
assert sun_equatorial_diameter == solar_system['star']['planets']['inner'][0]['Number of Moons']
The * attribute specifies all sibling keys. It is useful for iterating over attributes.
star_children = [child for child in find("$.star.*", solar_system)]
assert star_children == [solar_system['star']['name'],
solar_system['star']['diameter'],
solar_system['star']["age"],
solar_system['star']['planets'], ]
Multiple dictionary keys can be specified using a comma delimited list.
last_and_first = [planet for planet in find("$.star['diameter', 'name']", solar_system)]
assert last_and_first == [1391016, "Sun"]
List can be access using index.
earth = get("$.star.planets.inner[2]", solar_system)
assert earth == solar_system['star']['planets']['inner'][2]
List the third inner and outer planet.
last_two = [planet for planet in find("$.star.*.*[2].name", solar_system)]
assert last_two == ['Earth', 'Uranus']
List indexes can be specified as a comma delimited list.
last_and_first = [planet for planet in find("$.star.planets.outer[3, 0].name", solar_system)]
assert last_and_first == ["Neptune", "Jupiter"]
List can be access using slices.
List the first two planets.
first_two = [planet for planet in find("$.star.planets.outer[:2].name", solar_system)]
assert first_two == ["Jupiter", "Saturn"]
List the last two planets.
last_two = [planet for planet in find("$.star.planets.outer[-2:].name", solar_system)]
assert last_two == ["Uranus", "Neptune"]
List all outer planets in reverse.
last_two = [planet for planet in find("$.star.planets.outer[::-1].name", solar_system)]
assert last_two == ["Neptune", "Uranus", "Saturn", "Jupiter"]
List the last inner and outer planets.
last_two = [planet for planet in find("$.star.*.*[-1:].name", solar_system)]
assert last_two == ["Mars", "Neptune"]
The * token can be used as a list index. It is useful for iterating over attributes.
all_outer = [planet for planet in find("$.star.planets.outer[*].name", solar_system)]
assert all_outer == ["Jupiter", "Saturn", "Uranus", "Neptune"]
The .. double dot implies recursive search. It executes a preorder tree traversal. The search algorithm descends the tree hierarchy evaluating the path on each vertex until a match occurs. On each iteration it continues where it left off. This is an example that finds all the planets names.
all_planets = [p for p in find("$.star.planets..name", solar_system)]
assert all_planets == ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
Here is another example that finds all the celestial bodies names.
all_celestial_bodies = [p for p in find("$..name", solar_system)]
assert all_celestial_bodies == ['Sun', 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus',
'Neptune']
Filters are use to add additional search criteria.
The ?() is a filter that evaluates a branched off path relative to its parent path. This example finds all celestial bodies that have planets.
sun = get("$..[?(@.planets)].name", solar_system)
assert sun == "Sun"
This search finds all celestial bodies that have a has-moons attribute.
all_celestial_bodies_moon_attribute = [planet for planet in find("$..[?(@['has-moons'])].name", solar_system)]
assert all_celestial_bodies_moon_attribute == ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus',
'Neptune']
This search finds all celestial bodies that have moons. Note the operator.truth is used to exclude planets that don't have moons.
operator_truth = operator.truth
all_celestial_bodies_moon_attribute = [planet for planet in
find("$..[?(operator_truth(@['has-moons']))].name",
solar_system,
locals=locals()
)]
assert all_celestial_bodies_moon_attribute == ['Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
Filters can be specified with a comparison operator.
earth = [planet for planet in find("$..[?(@.diameter == 12756)].name", solar_system)]
assert earth == ['Earth']
earth = [planet for planet in find("$..[?(@.diameter != 12756)].name", solar_system)]
assert earth == ['Sun', 'Mercury', 'Venus', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
earth = [planet for planet in find("$..[?(@.diameter > 12756)].name", solar_system)]
assert earth == ['Sun', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
earth = [planet for planet in find("$..[?(@.diameter >= 12756)].name", solar_system)]
assert earth == ['Sun', 'Earth', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
earth = [planet for planet in find("$..[?(@.diameter < 12756)].name", solar_system)]
assert earth == ['Mercury', 'Venus', 'Mars']
earth = [planet for planet in find("$..[?(@.diameter <= 12756)].name", solar_system)]
assert earth == ['Mercury', 'Venus', 'Earth', 'Mars']
There is also a regular expression operator. This example finds all the planets that end with the letter s.
earth = [planet for planet in find(r"$..[?(@.name =~ '\w+s')].name", solar_system)]
assert earth == ['Venus', 'Mars', 'Uranus']
Sometimes the value is the wrong type for the comparison operator. In this example the attribute 'Number of Moons' is str type.
planets = [planet for planet in find("$..[?(@['Number of Moons'] > '5')].name", solar_system)]
assert planets == ['Jupiter', 'Saturn']
This is how to convert the type to an int before applying the comparison operator.
planets = [planet for planet in find("$..[?(int(@['Number of Moons']) > 5)].name", solar_system)]
assert planets == ['Jupiter', 'Saturn', 'Uranus', 'Neptune']
A filter operator can be specified as a single argument function. Here an example that searches for planets that have the same diameter as earth.
earths_diameter = partial(operator.eq, 12756)
earth = [planet for planet in find("$..[?(earths_diameter(@.diameter))].name", solar_system, locals=locals())]
assert earth == ['Earth']
Any single argument function can be used as an operator. This example uses a Regular Expression to finds planets that end with the letter s.
name_ends_with_s = re.compile(r"\w+s").match
earth = [planet for planet in find("$..[?(name_ends_with_s(@.name))].name", solar_system, locals=locals())]
assert earth == ['Venus', 'Mars', 'Uranus']
This example uses a closure to find planets that have the same diameter as earth.
def smaller_than_earth(value):
return value < 12756
earth = [planet for planet in find("$..[?(smaller_than_earth(@.diameter))].name", solar_system, locals=locals())]
assert earth == ['Mercury', 'Venus', 'Mars']
A regular express to test if the second letter in the value is 'a'.
second_letter_is_a = re.compile(r".a.*").fullmatch
The and function evaluates as the logical and operator. It is equivalent to: (arg1 and arg2 and ...)
found = [planet for planet in find("$..[?(@.diameter < 10000 and (second_letter_is_a(@.name)))].name",
solar_system,
locals=locals())
]
assert found == ['Mars']
The or function evaluates as the logical or operator. It is equivalent to: (arg1 and arg2 and ...)
found = [planet for planet in find("$..[?(@.diameter < 10000 or (second_letter_is_a(@.name)))].name",
solar_system,
locals=locals()
)
]
assert found == ['Mercury', 'Earth', 'Mars', 'Saturn']
The not function evaluates as the logical not operator. It is equivalent to: (not arg) This example find all the planets names not not equal to Earth. Note the double nots.
found = [planet for planet in find("$..[?(not (@.name != 'Earth'))].name", solar_system)]
assert found == ['Earth']
Each of the has function can be passed as arguments to any of the other has function to construct complex boolean equation. This example is equivalent to: (10000 > diameter or diameter > 20000) and second_letter_is_a(name))
found = [planet for planet in
find("$..[?((@.diameter < 10000 or @.diameter > 20000) and (second_letter_is_a(@.name)))].name",
solar_system,
locals=locals()
)
]
assert found == ['Mars', 'Saturn']
FAQs
A jsonpath implementation powered by treepath technology.
We found that jsonpath-tp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
New research reveals that LLMs often fake understanding, passing benchmarks but failing to apply concepts or stay internally consistent.
Security News
Django has updated its security policies to reject AI-generated vulnerability reports that include fabricated or unverifiable content.
Security News
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.