Package: bc-jsonpath-ng
A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic
and binary comparison operators, as defined in the originalJSONPath proposal.This packages merges bothjsonpath-rwandjsonpath-rw-extand
provides several AST API enhancements, such as the ability to update or removes nodes in the tree.AboutThis library provides a robust and significantly extended implementation
of JSONPath for Python.This library differs from other JSONPath implementations in that it is a
fulllanguageimplementation, meaning the JSONPath expressions are
first class objects, easy to analyze, transform, parse, print, and
extend.Quick StartTo install, use pip:$pipinstall--upgradejsonpath-ngUsageBasic examples:$python>>>fromjsonpath_ngimportjsonpath,parse# A robust parser, not just a regex. (Makes powerful extensions possible; see below)>>>jsonpath_expr=parse('foo[*].baz')# Extracting values is easy>>>[match.valueformatchinjsonpath_expr.find({'foo':[{'baz':1},{'baz':2}]})][1,2]# Matches remember where they came from>>>[str(match.full_path)formatchinjsonpath_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.valueformatchinparse('foo[*].id').find({'foo':[{'id':'bizzle'},{'baz':3}]})]['foo.bizzle','foo.[1]']# A handy extension: named operators like `parent`>>>[match.valueformatchinparse('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>>>fromjsonpath_ng.jsonpathimportFields>>>fromjsonpath_ng.jsonpathimportSlice>>>jsonpath_expr_direct=Fields('foo').child(Slice('*')).child(Fields('baz'))# This is equivalentUsing the extended parser:$python>>>fromjsonpath_ng.extimportparse# A robust parser, not just a regex. (Makes powerful extensions possible; see below)>>>jsonpath_expr=parse('foo[*].baz')JSONPath SyntaxThe 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|andwhereare 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:SyntaxMeaning$The root object`this`The “current” object.`foo`More generally, this syntax allows “named operators” to extend JSONPath is arbitrary waysfieldSpecified field(s), described below[field]Same asfield[idx]Array access, described below (this is always unambiguous with field access)Jsonpath operators:SyntaxMeaningjsonpath1.jsonpath2All nodes matched byjsonpath2starting at any node matchingjsonpath1jsonpath[whatever]Same asjsonpath.whateverjsonpath1..jsonpath2All nodes matched byjsonpath2that descend from any node matchingjsonpath1jsonpath1wherejsonpath2Any nodes matchingjsonpath1with a child matchingjsonpath2jsonpath1|jsonpath2Any nodes matching the union ofjsonpath1andjsonpath2Field specifiers (field):SyntaxMeaningfieldnamethe fieldfieldname(from the “current” object)"fieldname"same as above, for allowing special characters in the fieldname'fieldname'ditto*any fieldfield,fieldeither of the named fields (you can always build equivalent jsonpath using|)Array specifiers (idx):SyntaxMeaning[n]array index (may be comma-separated list)[start?:end?]array slicing (note thatstepis unimplemented only due to lack of need thus far)[*]any array indexProgrammatic JSONPathIf 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)ExtrasPath data: The result ofJsonPath.findprovide 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 setjsonpath_ng.auto_id_fieldto 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.ExtensionsnameExamplelen$.objects.`len`sub$.field.`sub(/foo\\+(.*)/, \\1)`split$.field.`split(+, 2, -1)`$.field.`split(sep, segement, maxsplit)`sorted$.objects.`sorted`$.objects[\some_field]$.objects[\some_field,/other_field]filter$.objects[?(@some_field > 5)]$.objects[?some_field = “foobar”)]$.objects[?some_field =~ “foobar”)]$.objects[?some_field > 5 & other < 2)]arithmetic
(-+*/)$.foo + “_” + $.bar$.foo * 12$.objects[*].cow + $.objects[*].catAbout arithmetic and stringOperations are done with python operators and allows types that python
allows, and return [] if the operation can be done due to incompatible types.When operators are used, a jsonpath must be be fully defined otherwise
jsonpath-rw-ext can’t known if the expression is a string or a jsonpath field,
in this case it will choice string as type.Example with data:{
    'cow': 'foo',
    'fish': 'bar'
}cow + fishreturnscowfish$.cow + $.fishreturnsfoobar$.cow + “_” + $.fishreturnsfoo_bar$.cow + “_” + fishreturnsfoo_fishAbout arithmetic and listArithmetic can be used against two lists if they have the same size.Example with data:{'objects': [
    {'cow': 2, 'cat': 3},
    {'cow': 4, 'cat': 6}
]}$.objects[*].cow + $.objects[*].catreturns[6, 9]More to exploreThere 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:JSONPath - XPath for
JSONby Stefan Goessner.Other examplesLoading json data from fileimportjsond=json.loads('{"foo": [{"baz": 1}, {"baz": 2}]}')# orwithopen('myfile.json')asf:d=json.load(f)Special note about PLY and docstringsThe main parsing toolkit underlying this library,PLY, does not work with docstrings
removed. For example,PYTHONOPTIMIZE=2andpython-OOwill both
cause a failure.ContributorsThis package was authored by:Kenn KnowlesTomas Apariciowith the help of patches submitted bythese contributors.Copyright and LicenseCopyright 2013 - Kenneth KnowlesCopyright 2017 - Tomas AparicioLicensed under the Apache License, Version 2.0 (the “License”); you may
not use this file except in compliance with the License. You may obtain
a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.