|
1 | 1 | # jsonpath2 |
2 | 2 | [](https://travis-ci.org/pacifica/python-jsonpath2) |
3 | 3 |
|
4 | | -This repository contains an implementation of [JSONPath](http://goessner.net/articles/JsonPath/) ([XPath](https://www.w3.org/TR/xpath/all/) for [JSON](https://www.json.org/)) for the Python programming language. |
| 4 | +This repository contains an implementation of |
| 5 | +[JSONPath](http://goessner.net/articles/JsonPath/) |
| 6 | +([XPath](https://www.w3.org/TR/xpath/all/) for |
| 7 | +[JSON](https://www.json.org/)) for the Python programming |
| 8 | +language. |
5 | 9 |
|
6 | | -## API |
| 10 | +## Documentation |
7 | 11 |
|
| 12 | +For installation, configuration and usage documentation please |
| 13 | +refer to the [Read the Docs](https://jsonpath2.readthedocs.io) |
| 14 | +documentation. |
8 | 15 |
|
9 | | -### `match` shortcut function |
| 16 | +* [Installation](docs/installation.md) documentation. |
| 17 | +* [Examples](docs/exampleusage.md) documentation. |
10 | 18 |
|
11 | | -The `jsonpath2.match` function is a shortcut to match a given JSON data |
12 | | -structure against a JSONPath string |
13 | 19 |
|
14 | | -```python |
15 | | ->>> import jsonpath2 |
16 | | ->>> doc = {'hello': 'Hello, world!'} |
17 | | ->>> [x.current_value for x in jsonpath2.match('$.hello', doc)] |
18 | | -['Hello, world!'] |
19 | | -``` |
| 20 | +## Contributions |
20 | 21 |
|
21 | | -### `Path` class |
22 | | - |
23 | | -The `jsonpath2.path.Path` class represents a JSONPath. |
24 | | - |
25 | | -```python |
26 | | ->>> s = '{"hello":"Hello, world!"}' |
27 | | -'{"hello":"Hello, world!"}' |
28 | | ->>> import json |
29 | | ->>> d = json.loads(s) |
30 | | -{'hello':'Hello, world!'} |
31 | | ->>> from jsonpath2.path import Path |
32 | | ->>> p = Path.parse_str('$["hello"]') |
33 | | -<jsonpath2.path.Path object> |
34 | | ->>> [match_data.current_value for match_data in p.match(d)] |
35 | | -['Hello, world!'] |
36 | | ->>> [match_data.node.tojsonpath() for match_data in p.match(d)] |
37 | | -['$["hello"]'] |
38 | | -``` |
39 | | - |
40 | | -This class is constructed with respect to the given instance of the `jsonpath2.nodes.root.RootNode` class (viz., the `root_node` property). |
41 | | - |
42 | | -#### `parse_str(strdata)` class method |
43 | | - |
44 | | -Parse the given string and return a new instance of this class. |
45 | | - |
46 | | -#### `parse_file(fileName, encoding='ascii')` class method |
47 | | - |
48 | | -Parse the contents of the given file and return a new instance of this class. |
49 | | - |
50 | | -#### `match(root_value)` instance method |
51 | | - |
52 | | -Match the given JSON data structure against this instance. |
53 | | -For each match, yield an instance of the `jsonpath2.node.MatchData` class. |
54 | | - |
55 | | -#### `__eq__(other)` instance method |
56 | | - |
57 | | -Tests if two instances are equal. |
58 | | - |
59 | | -#### `__str__()` instance method |
60 | | - |
61 | | -Returns the string representation of this instance. |
62 | | - |
63 | | -#### `root_node` property |
64 | | - |
65 | | -The root node of the abstract syntax tree for this instance. |
66 | | - |
67 | | -### `Node` abstract class |
68 | | - |
69 | | -The `jsonpath2.node.Node` class represents the abstract syntax tree for a JSONPath. |
70 | | - |
71 | | -#### `__eq__(other)` instance method |
72 | | - |
73 | | -Tests if two instances are equal. |
74 | | - |
75 | | -#### `__jsonpath__()` instance method |
76 | | - |
77 | | -Yields the lexer tokens for the string representation of this instance. |
78 | | - |
79 | | -#### `match(root_value, current_value)` instance method |
80 | | - |
81 | | -Match the given root and current JSON data structures against this instance. |
82 | | -For each match, yield an instance of the `jsonpath2.node.MatchData` class. |
83 | | - |
84 | | -#### `tojsonpath()` instance method |
85 | | - |
86 | | -Returns the string representation of this instance. |
87 | | - |
88 | | -### `MatchData` class |
89 | | - |
90 | | -The `jsonpath2.node.MatchData` class represents the JSON value and context for a JSONPath match. |
91 | | - |
92 | | -This class is constructed with respect to a root JSON value, a current JSON value, and an abstract syntax tree node. |
93 | | - |
94 | | -#### `__eq__(other)` instance method |
95 | | - |
96 | | -Tests if two instances are equal. |
97 | | - |
98 | | -#### `root_value` property |
99 | | - |
100 | | -The root JSON value. |
101 | | - |
102 | | -#### `current_value` property |
103 | | - |
104 | | -The current JSON value (i.e., the matching JSON value). |
105 | | - |
106 | | -#### `node` property |
107 | | - |
108 | | -The abstract syntax tree node. |
109 | | - |
110 | | -## Syntax |
111 | | - |
112 | | -| XPath | JSONPath | Description | |
113 | | -| - | - | - | |
114 | | -| `/` | `$` | the root JSON value | |
115 | | -| `.` | `@` | the current JSON value | |
116 | | -| `/` | `.` or `[]` | child operator | |
117 | | -| `//` | `..` | recursive descent (depth-first search) | |
118 | | -| `*` | `*` | wildcard (all elements of a JSON array; all values of a JSON object; otherwise none) | |
119 | | -| `[]` | `[]` | subscript operator | |
120 | | -| <code>|</code> | `[,]` | union operator (for two or more subscript operators) | |
121 | | -| n/a | `[start:end:step]` | slice operator (subset of elements of a JSON array) | |
122 | | -| `[]` | `?()` | filter expression (for use with subscript operator) | |
123 | | - |
124 | | -| JSONPath Filter Expression | Description | |
125 | | -| - | - | |
126 | | -| `$` or `@` | nested JSONPath (returns `true` if any match exists; otherwise, returns `false`) | |
127 | | -| `=`, `!=`, `>`, `>=`, `<`, `<=` | binary operator, where left- and right-hand operands are nested JSONPaths or JSON values (returns `true` if any match exists; otherwise, returns `false`) | |
128 | | -| `and`, `or`, `not` | Boolean operator, where operands are JSONPath filter expressions | |
129 | | -| `(` ... `)` | parentheses | |
130 | | - |
131 | | -## Functions |
132 | | - |
133 | | -> See [#14](https://github.com/pacifica/python-jsonpath2/pull/14) for more information. |
134 | | -
|
135 | | -The syntax for a function call is the name of the function followed by the arguments in parentheses, i.e., `name(arg1, arg2, ..., argN)`, where the arguments are either JSONPaths or JSON values. |
136 | | - |
137 | | -```python |
138 | | ->>> s = '{"hello":"Hello, world!"}' |
139 | | -'{"hello":"Hello, world!"}' |
140 | | ->>> import json |
141 | | ->>> d = json.loads(s) |
142 | | -{'hello':'Hello, world!'} |
143 | | ->>> from jsonpath2.path import Path |
144 | | ->>> p = Path.parse_str('$["hello"][length()]') |
145 | | -<jsonpath2.path.Path object> |
146 | | ->>> [m.current_value for m in p.match(d)] |
147 | | -[13] |
148 | | ->>> [m.node.tojsonpath() for m in p.match(d)] |
149 | | -['$["hello"][length()]'] |
150 | | -``` |
151 | | - |
152 | | -| JavaScript Function | Signature | |
153 | | -| - | - | |
154 | | -| [`Array.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length) | `length(): int` | |
155 | | -| [`Array.prototype.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries) | `entries(): List[Tuple[int, Any]]` | |
156 | | -| [`Array.prototype.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/keys) | `keys(): List[int]` | |
157 | | -| [`Array.prototype.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values) | `values(): List[Any]` | |
158 | | -| [`Object.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) | `entries(): List[Tuple[str, Any]]` | |
159 | | -| [`Object.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) | `keys(): List[str]` | |
160 | | -| [`Object.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values) | `values(): List[Any]` | |
161 | | -| [`string.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length) | `length(): int` | |
162 | | -| [`String.prototype.charAt()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt) | `charAt(index: int): str` | |
163 | | -| [`String.prototype.substring()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring) | `substring(indexStart: int, indexEnd: Optional[int]): str` | |
164 | | - |
165 | | -<!-- | `Array.prototype.concat()` | | |
166 | | -| `Array.prototype.fill()` | | |
167 | | -| `Array.prototype.flat()` | | |
168 | | -| `Array.prototype.includes()` | | |
169 | | -| `Array.prototype.indexOf()` | | |
170 | | -| `Array.prototype.join()` | | |
171 | | -| `Array.prototype.lastIndexOf()` | | |
172 | | -| `Array.prototype.slice()` | | |
173 | | -| `Array.prototype.sort()` | | |
174 | | -| `Array.prototype.splice()` | | |
175 | | -| `JSON.parse()` | | |
176 | | -| `JSON.stringify()` | | |
177 | | -| `Math.abs()` | | |
178 | | -| `Math.acos()` | | |
179 | | -| `Math.acosh()` | | |
180 | | -| `Math.asin()` | | |
181 | | -| `Math.asinh()` | | |
182 | | -| `Math.atan()` | | |
183 | | -| `Math.atan2()` | | |
184 | | -| `Math.atanh()` | | |
185 | | -| `Math.cbrt()` | | |
186 | | -| `Math.ceil()` | | |
187 | | -| `Math.clz32()` | | |
188 | | -| `Math.cos()` | | |
189 | | -| `Math.cosh()` | | |
190 | | -| `Math.exp()` | | |
191 | | -| `Math.expm1()` | | |
192 | | -| `Math.floor()` | | |
193 | | -| `Math.fround()` | | |
194 | | -| `Math.hypot()` | | |
195 | | -| `Math.imul()` | | |
196 | | -| `Math.log()` | | |
197 | | -| `Math.log10()` | | |
198 | | -| `Math.log1p()` | | |
199 | | -| `Math.log2()` | | |
200 | | -| `Math.max()` | | |
201 | | -| `Math.min()` | | |
202 | | -| `Math.pow()` | | |
203 | | -| `Math.random()` | | |
204 | | -| `Math.round()` | | |
205 | | -| `Math.sign()` | | |
206 | | -| `Math.sin()` | | |
207 | | -| `Math.sinh()` | | |
208 | | -| `Math.sqrt()` | | |
209 | | -| `Math.tan()` | | |
210 | | -| `Math.tanh()` | | |
211 | | -| `Math.trunc()` | | |
212 | | -| `Number.isFinite()` | | |
213 | | -| `Number.isInteger()` | | |
214 | | -| `Number.isNaN()` | | |
215 | | -| `Number.isSafeInteger()` | | |
216 | | -| `Number.parseFloat()` | | |
217 | | -| `Number.parseInt()` | | |
218 | | -| `String.prototype.codeCharAt()` | | |
219 | | -| `String.prototype.codePointAt()` | | |
220 | | -| `String.prototype.concat()` | | |
221 | | -| `String.prototype.endsWith()` | | |
222 | | -| `String.prototype.includes()` | | |
223 | | -| `String.prototype.indexOf()` | | |
224 | | -| `String.prototype.lastIndexOf()` | | |
225 | | -| `String.prototype.localeCompare()` | | |
226 | | -| `String.prototype.match()` | | |
227 | | -| `String.prototype.normalize()` | | |
228 | | -| `String.prototype.padEnd()` | | |
229 | | -| `String.prototype.padStart()` | | |
230 | | -| `String.prototype.repeat()` | | |
231 | | -| `String.prototype.replace()` | | |
232 | | -| `String.prototype.search()` | | |
233 | | -| `String.prototype.slice()` | | |
234 | | -| `String.prototype.split()` | | |
235 | | -| `String.prototype.startsWith()` | | |
236 | | -| `String.prototype.toLocaleLowerCase()` | | |
237 | | -| `String.prototype.toLocaleUpperCase()` | | |
238 | | -| `String.prototype.toLowerCase()` | | |
239 | | -| `String.prototype.toUpperCase()` | | |
240 | | -| `String.prototype.trim()` | | |
241 | | -| `String.prototype.trimEnd()` | | |
242 | | -| `String.prototype.trimStart()` | | --> |
243 | | - |
244 | | -In the above table, the type aliases (`Any`, `List`, `Optional` and `Tuple`) are defined by the [`typing`](https://docs.python.org/3/library/typing.html) module from the Python Standard Library. |
245 | | - |
246 | | -## Grammar and parser |
247 | | - |
248 | | -The [ANTLR v4](https://github.com/antlr/antlr4) grammar for JSONPath is available at `jsonpath2/parser/JSONPath.g4`. |
249 | | - |
250 | | -### Installing ANTLR v4 |
251 | | - |
252 | | -Adapted from https://github.com/antlr/antlr4/blob/master/doc/getting-started.md. |
253 | | - |
254 | | -```bash |
255 | | -cd /usr/local/lib |
256 | | -curl -O http://www.antlr.org/download/antlr-4.7.1-complete.jar |
257 | | - |
258 | | -export CLASSPATH=".:/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" |
259 | | - |
260 | | -alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.Tool' |
261 | | -alias grun='java org.antlr.v4.gui.TestRig' |
262 | | -``` |
263 | | - |
264 | | -### Building the parser for the grammar |
265 | | - |
266 | | -Adapted from https://github.com/antlr/antlr4/blob/master/doc/python-target.md. |
267 | | - |
268 | | -```bash |
269 | | -antlr4 -Dlanguage=Python3 -o . -lib . jsonpath2/parser/JSONPath.g4 |
270 | | -``` |
| 22 | +Contributions are accepted on GitHub via the fork and pull request workflow. |
| 23 | +GitHub has a good [help article](https://help.github.com/articles/using-pull-requests/) |
| 24 | +if you are unfamiliar with this method of contributing. |
0 commit comments