Skip to main content

A robust and significantly extended implementation of JSONPath for Python, with a clear AST for metaprogramming.

Project description

https://github.com/kennknowles/python-jsonpath-rw

Build Status Test coverage PyPi version PyPi downloads

This library provides a robust and significantly extended implementation of JSONPath for Python. It is tested with Python 2.7, 3.4, 3.5, 3.6, 3.7, pypy and pypy3.

This library differs from other JSONPath implementations in that it is a full language implementation, meaning the JSONPath expressions are first class objects, easy to analyze, transform, parse, print, and extend. (You can also execute them :-)

Quick Start

To install, use pip:

$ pip install jsonpath-rw

Then:

$ python

>>> from jsonpath_rw import jsonpath, parse

# A robust parser, not just a regex. (Makes powerful extensions possible; see below)
>>> jsonpath_expr = parse('foo[*].baz')

# Extracting values is easy
>>> [match.value for match in jsonpath_expr.find({'foo': [{'baz': 1}, {'baz': 2}]})]
[1, 2]

# Matches remember where they came from
>>> [str(match.full_path) for match in jsonpath_expr.find({'foo': [{'baz': 1}, {'baz': 2}]})]
['foo.[0].baz', 'foo.[1].baz']

# And this can be useful for automatically providing ids for bits of data that do not have them (currently a global switch)
>>> jsonpath.auto_id_field = 'id'
>>> [match.value for match in parse('foo[*].id').find({'foo': [{'id': 'bizzle'}, {'baz': 3}]})]
['foo.bizzle', 'foo.[1]']

# A handy extension: named operators like `parent`
>>> [match.value for match in parse('a.*.b.`parent`.c').find({'a': {'x': {'b': 1, 'c': 'number one'}, 'y': {'b': 2, 'c': 'number two'}}})]
['number two', 'number one']

# You can also build expressions directly quite easily
>>> from jsonpath_rw.jsonpath import Fields
>>> from jsonpath_rw.jsonpath import Slice

>>> jsonpath_expr_direct = Fields('foo').child(Slice('*')).child(Fields('baz'))  # This is equivalent

JSONPath Syntax

The JSONPath syntax supported by this library includes some additional features and omits some problematic features (those that make it unportable). In particular, some new operators such as | and where are available, and parentheses are used for grouping not for callbacks into Python, since with these changes the language is not trivially associative. Also, fields may be quoted whether or not they are contained in brackets.

Atomic expressions:

Syntax

Meaning

$

The root object

`this`

The “current” object.

`foo`

More generally, this syntax allows “named operators” to extend JSONPath is arbitrary ways

field

Specified field(s), described below

[ field ]

Same as field

[ idx ]

Array access, described below (this is always unambiguous with field access)

Jsonpath operators:

Syntax

Meaning

jsonpath1 . jsonpath2

All nodes matched by jsonpath2 starting at any node matching jsonpath1

jsonpath [ whatever ]

Same as jsonpath.whatever

jsonpath1 .. jsonpath2

All nodes matched by jsonpath2 that descend from any node matching jsonpath1

jsonpath1 where jsonpath2

Any nodes matching jsonpath1 with a child matching jsonpath2

jsonpath1 | jsonpath2

Any nodes matching the union of jsonpath1 and jsonpath2

Field specifiers ( field ):

Syntax

Meaning

fieldname

the field fieldname (from the “current” object)

"fieldname"

same as above, for allowing special characters in the fieldname

'fieldname'

ditto

*

any field

field , field

either of the named fields (you can always build equivalent jsonpath using |)

Array specifiers ( idx ):

Syntax

Meaning

[n]

array index (may be comma-separated list)

[start?:end?]

array slicing (note that step is unimplemented only due to lack of need thus far)

[*]

any array index

Programmatic JSONPath

If you are programming in Python and would like a more robust way to create JSONPath expressions that does not depend on a parser, it is very easy to do so directly, and here are some examples:

  • Root()

  • Slice(start=0, end=None, step=None)

  • Fields('foo', 'bar')

  • Index(42)

  • Child(Fields('foo'), Index(42))

  • Where(Slice(), Fields('subfield'))

  • Descendants(jsonpath, jsonpath)

Extensions

  • Path data: The result of JsonPath.find provide detailed context and path data so it is easy to traverse to parent objects, print full paths to pieces of data, and generate automatic ids.

  • Automatic Ids: If you set jsonpath_rw.auto_id_field to a value other than None, then for any piece of data missing that field, it will be replaced by the JSONPath to it, giving automatic unique ids to any piece of data. These ids will take into account any ids already present as well.

  • Named operators: Instead of using @ to reference the currently object, this library uses `this`. In general, any string contained in backquotes can be made to be a new operator, currently by extending the library.

More to explore

There are way too many jsonpath implementations out there to discuss. Some are robust, some are toy projects that still work fine, some are exercises. There will undoubtedly be many more. This one is made for use in released, maintained code, and in particular for programmatic access to the abstract syntax and extension. But JSONPath at its simplest just isn’t that complicated, so you can probably use any of them successfully. Why not this one?

The original proposal, as far as I know:

Other examples

Loading json data from file

import json
d = json.loads('{"foo": [{"baz": 1}, {"baz": 2}]}')
# or
with open('myfile.json') as f:
    d = json.load(f)

Special note about PLY and docstrings

The main parsing toolkit underlying this library, PLY, does not work with docstrings removed. For example, PYTHONOPTIMIZE=2 and python -OO will both cause a failure.

Contributors

This package is authored and maintained by:

with the help of patches submitted by these contributors.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dt-jsonpath-rw-1.4.0.tar.gz (22.3 kB view details)

Uploaded Source

Built Distribution

dt_jsonpath_rw-1.4.0-py3-none-any.whl (19.7 kB view details)

Uploaded Python 3

File details

Details for the file dt-jsonpath-rw-1.4.0.tar.gz.

File metadata

  • Download URL: dt-jsonpath-rw-1.4.0.tar.gz
  • Upload date:
  • Size: 22.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.10.11

File hashes

Hashes for dt-jsonpath-rw-1.4.0.tar.gz
Algorithm Hash digest
SHA256 3eddc0384e4053dfc4e88bb8aeaf981f37622ea3ff063dbf3ece05e1bb55f757
MD5 297fdcf1366aa5e3771fe9e58cadb1ed
BLAKE2b-256 215528040f6922f6951825add2b19b3a380f78056b6dc21c0612e762b559f3bf

See more details on using hashes here.

File details

Details for the file dt_jsonpath_rw-1.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for dt_jsonpath_rw-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d0c6335f467c7865900f10984fb0d158361b419c84bdfa55e83633d4131382db
MD5 2c2471b94614c8479b41bb492489ad7b
BLAKE2b-256 ee9c340f074bd687d4b6cdb44e068c13cdc53674965be55d8c887ff095e58ebf

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page