Skip to content

Quick Start

This page gets you started using JSONPath, JSON Pointer and JSON Patch wih Python. See JSONPath Syntax for information on JSONPath selector syntax.

findall(path, data)

Find all objects matching a JSONPath with jsonpath.findall(). It takes, as arguments, a JSONPath string and some data object. It always returns a list of objects selected from data, never a scalar value.

data can be a file-like object or string containing JSON formatted data, or a Python Mapping or Sequence, like a dictionary or list. In this example we select user names from a dictionary containing a list of user dictionaries.

import jsonpath

data = {
    "users": [
        {
            "name": "Sue",
            "score": 100,
        },
        {
            "name": "John",
            "score": 86,
        },
        {
            "name": "Sally",
            "score": 84,
        },
        {
            "name": "Jane",
            "score": 55,
        },
    ]
}

user_names = jsonpath.findall("$.users.*.name", data)

Where user_names is now equal to:

["Sue", "John", "Sally", "Jane"]

If the same data were in a file called users.json, we might use findall() like this:

import jsonpath

with open("users.json") as fd:
    user_names = jsonpath.findall("$.users.*.name", fd)

finditer(path, data)

Use jsonpath.finditer() to iterate over instances of jsonpath.JSONPathMatch for every object in data that matches path. It accepts the same arguments as findall(), a path string and data from which to select matches.

import jsonpath

data = {
    "users": [
        {
            "name": "Sue",
            "score": 100,
        },
        {
            "name": "John",
            "score": 86,
        },
        {
            "name": "Sally",
            "score": 84,
        },
        {
            "name": "Jane",
            "score": 55,
        },
    ]
}

matches = jsonpath.finditer("$.users.*.name", data)
for match in matches:
    print(matches)

The string representation of a JSONPathMatch shows the matched object and the canonical path to that object.

'Sue' @ $['users'][0]['name']
'John' @ $['users'][1]['name']
'Sally' @ $['users'][2]['name']
'Jane' @ $['users'][3]['name']

The selected object is available from a JSONPathMatch as obj and its path, as a string, as path. Other useful properties of JSONPathMatch include a reference to the parent match, a list of child matches, and a parts tuple of keys and indices that make up the path.

compile(path)

When you have a JSONPath that needs to be matched against different data repeatedly, you can compile the path ahead of time using jsonpath.compile(). It takes a path as a string and returns a JSONPath instance. JSONPath has findall() and finditer() methods that behave similarly to package-level findall() and finditer(), just without the path argument.

import jsonpath

some_data = {
    "users": [
        {
            "name": "Sue",
            "score": 100,
        },
        {
            "name": "John",
            "score": 86,
        },
    ]
}

other_data = {
    "users": [
        {
            "name": "Sally",
            "score": 84,
        },
        {
            "name": "Jane",
            "score": 55,
        },
    ]
}

path = jsonpath.compile("$.users.*.name")

some_users = path.findall(some_data)
other_users = path.findall(other_data)

match(path, data)

New in version 0.8.0

Get a jsonpath.JSONPathMatch instance for the first match found in data. If there are no matches, None is returned. match() accepts the same arguments as findall().

import jsonpath

data = {
    "users": [
        {
            "name": "Sue",
            "score": 100,
        },
        {
            "name": "John",
            "score": 86,
        },
        {
            "name": "Sally",
            "score": 84,
        },
        {
            "name": "Jane",
            "score": 55,
        },
    ]
}

match = jsonpath.match("$.users[?@.score > 85].name", data)
if match:
    print(match)  # 'Sue' @ $['users'][0]['name']
    print(match.obj)  # Sue

pointer.resolve(pointer, data)

New in version 0.8.0

Resolve a JSON Pointer (RFC 6901) against some data. A JSON Pointer references a single object on a specific "path" in a JSON document. Here, pointer can be a string representation of a JSON Pointer or a list of parts that make up a pointer. data can be a file-like object or string containing JSON formatted data, or equivalent Python objects.

from jsonpath import pointer

data = {
    "users": [
        {
            "name": "Sue",
            "score": 100,
        },
        {
            "name": "John",
            "score": 86,
        },
        {
            "name": "Sally",
            "score": 84,
        },
        {
            "name": "Jane",
            "score": 55,
        },
    ]
}

sue_score = pointer.resolve("/users/0/score", data)
print(sue_score)  # 100

jane_score = pointer.resolve(["users", 3, "score"], data)
print(jane_score)  # 55

If the pointer can't be resolved against the target JSON document - due to missing keys/properties or out of range indices - a JSONPointerIndexError, JSONPointerKeyError or JSONPointerTypeError will be raised, each of which inherit from JSONPointerResolutionError. A default value can be given, which will be returned in the event of a JSONPointerResolutionError.

from jsonpath import pointer

data = {
    "users": [
        {
            "name": "Sue",
            "score": 100,
        },
        {
            "name": "John",
            "score": 86,
        },
    ]
}

sue_score = pointer.resolve("/users/99/score", data, default=0)
print(sue_score)  # 0

See also JSONPathMatch.pointer(), which builds a JSONPointer from a JSONPathMatch.

patch.apply(patch, data)

New in version 0.8.0

Apply a JSON Patch (RFC 6902) to some data. A JSON Patch defines update operation to perform on a JSON document.

patch can be a string or file-like object containing a valid JSON Patch document, or an iterable of dictionaries.

data is the target JSON document to modify. If data is a string or file-like object, it will be loaded with json.loads. Otherwise data should be a JSON-like data structure and will be modified in place.

from jsonpath import patch

patch_operations = [
    {"op": "add", "path": "/some/foo", "value": {"foo": {}}},
    {"op": "add", "path": "/some/foo", "value": {"bar": []}},
    {"op": "copy", "from": "/some/other", "path": "/some/foo/else"},
    {"op": "add", "path": "/some/foo/bar/-", "value": 1},
]

data = {"some": {"other": "thing"}}
patch.apply(patch_operations, data)
print(data) # {'some': {'other': 'thing', 'foo': {'bar': [1], 'else': 'thing'}}}

Use the JSONPatch class to create a patch for repeated application.

from jsonpath import JSONPatch

patch = JSONPatch(
    [
        {"op": "add", "path": "/some/foo", "value": {"foo": {}}},
        {"op": "add", "path": "/some/foo", "value": {"bar": []}},
        {"op": "copy", "from": "/some/other", "path": "/some/foo/else"},
        {"op": "add", "path": "/some/foo/bar/-", "value": 1},
    ]
)

data = {"some": {"other": "thing"}}
patch.apply(data)
print(data)  # {'some': {'other': 'thing', 'foo': {'bar': [1], 'else': 'thing'}}}

JSONPatch also offers a builder API for constructing JSON patch documents. We use strings as JSON Pointers in this example, but existing JSONPointer instances are OK too.

from jsonpath import JSONPatch

patch = (
    JSONPatch()
    .add("/some/foo", {"foo": []})
    .add("/some/foo", {"bar": []})
    .copy("/some/other", "/some/foo/else")
    .add("/some/foo/bar/-", "/some/foo/else")
)

data = {"some": {"other": "thing"}}
patch.apply(data)
print(data)  # {'some': {'other': 'thing', 'foo': {'bar': [1], 'else': 'thing'}}}

What's Next?

Read about the Query Iterators API or user-defined filter functions. Also see how to make extra data available to filters with Extra Filter Context.

findall(), finditer() and compile() are shortcuts that use the defaultJSONPathEnvironment. jsonpath.findall(path, data) is equivalent to:

jsonpath.JSONPathEnvironment().compile(path).findall(data)

If you would like to customize Python JSONPath, see Advanced Usage.