python-jsonpath 1.3.2__tar.gz → 2.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/.gitignore +3 -1
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/PKG-INFO +7 -3
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/README.md +2 -2
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/__about__.py +1 -1
- python_jsonpath-2.0.1/jsonpath/__init__.py +365 -0
- python_jsonpath-2.0.1/jsonpath/_types.py +31 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/cli.py +11 -1
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/env.py +100 -47
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/exceptions.py +78 -7
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/filter.py +78 -84
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/__init__.py +4 -2
- python_jsonpath-2.0.1/jsonpath/function_extensions/_pattern.py +112 -0
- python_jsonpath-2.0.1/jsonpath/function_extensions/keys.py +31 -0
- python_jsonpath-2.0.1/jsonpath/function_extensions/match.py +19 -0
- python_jsonpath-2.0.1/jsonpath/function_extensions/search.py +19 -0
- python_jsonpath-2.0.1/jsonpath/function_extensions/starts_with.py +21 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/lex.py +113 -64
- python_jsonpath-2.0.1/jsonpath/lru_cache.py +130 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/match.py +13 -0
- python_jsonpath-2.0.1/jsonpath/parse.py +888 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/patch.py +8 -3
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/path.py +48 -84
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/pointer.py +52 -55
- python_jsonpath-2.0.1/jsonpath/segments.py +131 -0
- python_jsonpath-2.0.1/jsonpath/selectors.py +734 -0
- python_jsonpath-2.0.1/jsonpath/stream.py +97 -0
- python_jsonpath-2.0.1/jsonpath/token.py +120 -0
- python_jsonpath-2.0.1/jsonpath/unescape.py +134 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/pyproject.toml +27 -6
- python_jsonpath-1.3.2/jsonpath/__init__.py +0 -83
- python_jsonpath-1.3.2/jsonpath/function_extensions/keys.py +0 -12
- python_jsonpath-1.3.2/jsonpath/function_extensions/match.py +0 -21
- python_jsonpath-1.3.2/jsonpath/function_extensions/search.py +0 -21
- python_jsonpath-1.3.2/jsonpath/parse.py +0 -742
- python_jsonpath-1.3.2/jsonpath/selectors.py +0 -768
- python_jsonpath-1.3.2/jsonpath/stream.py +0 -99
- python_jsonpath-1.3.2/jsonpath/token.py +0 -122
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/LICENSE.txt +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/__main__.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/_data.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/fluent_api.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/arguments.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/count.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/filter_function.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/is_instance.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/length.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/typeof.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/function_extensions/value.py +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/py.typed +0 -0
- {python_jsonpath-1.3.2 → python_jsonpath-2.0.1}/jsonpath/serialize.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-jsonpath
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: JSONPath, JSON Pointer and JSON Patch for Python.
|
|
5
5
|
Project-URL: Documentation, https://jg-rp.github.io/python-jsonpath/
|
|
6
6
|
Project-URL: Issues, https://github.com/jg-rp/python-jsonpath/issues
|
|
@@ -8,6 +8,7 @@ Project-URL: Source, https://github.com/jg-rp/python-jsonpath
|
|
|
8
8
|
Author-email: James Prior <jamesgr.prior@gmail.com>
|
|
9
9
|
License-Expression: MIT
|
|
10
10
|
License-File: LICENSE.txt
|
|
11
|
+
Keywords: JSON,JSON Patch,JSON Path,JSON Pointer,JSONPath,RFC 9535
|
|
11
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
13
|
Classifier: Intended Audience :: Developers
|
|
13
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -21,6 +22,9 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
21
22
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
23
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
23
24
|
Requires-Python: >=3.8
|
|
25
|
+
Provides-Extra: strict
|
|
26
|
+
Requires-Dist: iregexp-check>=0.1.4; extra == 'strict'
|
|
27
|
+
Requires-Dist: regex; extra == 'strict'
|
|
24
28
|
Description-Content-Type: text/markdown
|
|
25
29
|
|
|
26
30
|
<h1 align="center">Python JSONPath</h1>
|
|
@@ -91,9 +95,9 @@ conda install -c conda-forge python-jsonpath
|
|
|
91
95
|
|
|
92
96
|
## Related projects
|
|
93
97
|
|
|
94
|
-
- [JSONPath RFC 9535](https://github.com/jg-rp/python-jsonpath-rfc9535) - A Python implementation of
|
|
98
|
+
- [JSONPath RFC 9535](https://github.com/jg-rp/python-jsonpath-rfc9535) - A minimal, slightly cleanr Python implementation of RFC 9535. If you're not interested JSONPath sytax beyond that defined in RFC 9535, you might choose [jsonpath-rfc9535](https://pypi.org/project/jsonpath-rfc9535/) over [python-jsonpath](https://pypi.org/project/python-jsonpath/).
|
|
95
99
|
|
|
96
|
-
jsonpath-rfc9535
|
|
100
|
+
jsonpath-rfc9535 also includes utilities for verifying and testing the [JSONPath Compliance Test Suite](https://github.com/jsonpath-standard/jsonpath-compliance-test-suite). Most notably the nondeterministic behavior of some JSONPath selectors.
|
|
97
101
|
|
|
98
102
|
- [JSON P3](https://github.com/jg-rp/json-p3) - RFC 9535 implemented in TypeScript. JSON P3 does not include all the non-standard features of Python JSONPath, but does define some optional [extra syntax](https://jg-rp.github.io/json-p3/guides/jsonpath-extra).
|
|
99
103
|
|
|
@@ -66,9 +66,9 @@ conda install -c conda-forge python-jsonpath
|
|
|
66
66
|
|
|
67
67
|
## Related projects
|
|
68
68
|
|
|
69
|
-
- [JSONPath RFC 9535](https://github.com/jg-rp/python-jsonpath-rfc9535) - A Python implementation of
|
|
69
|
+
- [JSONPath RFC 9535](https://github.com/jg-rp/python-jsonpath-rfc9535) - A minimal, slightly cleanr Python implementation of RFC 9535. If you're not interested JSONPath sytax beyond that defined in RFC 9535, you might choose [jsonpath-rfc9535](https://pypi.org/project/jsonpath-rfc9535/) over [python-jsonpath](https://pypi.org/project/python-jsonpath/).
|
|
70
70
|
|
|
71
|
-
jsonpath-rfc9535
|
|
71
|
+
jsonpath-rfc9535 also includes utilities for verifying and testing the [JSONPath Compliance Test Suite](https://github.com/jsonpath-standard/jsonpath-compliance-test-suite). Most notably the nondeterministic behavior of some JSONPath selectors.
|
|
72
72
|
|
|
73
73
|
- [JSON P3](https://github.com/jg-rp/json-p3) - RFC 9535 implemented in TypeScript. JSON P3 does not include all the non-standard features of Python JSONPath, but does define some optional [extra syntax](https://jg-rp.github.io/json-p3/guides/jsonpath-extra).
|
|
74
74
|
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023-present James Prior <jamesgr.prior@gmail.com>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import AsyncIterable
|
|
8
|
+
from typing import Iterable
|
|
9
|
+
from typing import List
|
|
10
|
+
from typing import Optional
|
|
11
|
+
from typing import Union
|
|
12
|
+
|
|
13
|
+
from ._types import JSON
|
|
14
|
+
from ._types import JSONData
|
|
15
|
+
from ._types import JSONScalar
|
|
16
|
+
from .env import JSONPathEnvironment
|
|
17
|
+
from .exceptions import JSONPatchError
|
|
18
|
+
from .exceptions import JSONPatchTestFailure
|
|
19
|
+
from .exceptions import JSONPathError
|
|
20
|
+
from .exceptions import JSONPathIndexError
|
|
21
|
+
from .exceptions import JSONPathNameError
|
|
22
|
+
from .exceptions import JSONPathSyntaxError
|
|
23
|
+
from .exceptions import JSONPathTypeError
|
|
24
|
+
from .exceptions import JSONPointerError
|
|
25
|
+
from .exceptions import JSONPointerIndexError
|
|
26
|
+
from .exceptions import JSONPointerKeyError
|
|
27
|
+
from .exceptions import JSONPointerResolutionError
|
|
28
|
+
from .exceptions import JSONPointerTypeError
|
|
29
|
+
from .exceptions import RelativeJSONPointerError
|
|
30
|
+
from .exceptions import RelativeJSONPointerIndexError
|
|
31
|
+
from .exceptions import RelativeJSONPointerSyntaxError
|
|
32
|
+
from .filter import UNDEFINED
|
|
33
|
+
from .fluent_api import Projection
|
|
34
|
+
from .fluent_api import Query
|
|
35
|
+
from .lex import Lexer
|
|
36
|
+
from .match import JSONPathMatch
|
|
37
|
+
from .match import NodeList
|
|
38
|
+
from .parse import Parser
|
|
39
|
+
from .patch import JSONPatch
|
|
40
|
+
from .path import CompoundJSONPath
|
|
41
|
+
from .path import JSONPath
|
|
42
|
+
from .pointer import JSONPointer
|
|
43
|
+
from .pointer import RelativeJSONPointer
|
|
44
|
+
from .pointer import resolve
|
|
45
|
+
|
|
46
|
+
if TYPE_CHECKING:
|
|
47
|
+
from .match import FilterContextVars
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
__all__ = (
|
|
51
|
+
"compile",
|
|
52
|
+
"CompoundJSONPath",
|
|
53
|
+
"findall_async",
|
|
54
|
+
"findall",
|
|
55
|
+
"finditer_async",
|
|
56
|
+
"finditer",
|
|
57
|
+
"JSONPatch",
|
|
58
|
+
"JSONPatchError",
|
|
59
|
+
"JSONPatchTestFailure",
|
|
60
|
+
"JSONPath",
|
|
61
|
+
"JSONPathEnvironment",
|
|
62
|
+
"JSONPathError",
|
|
63
|
+
"JSONPathIndexError",
|
|
64
|
+
"JSONPathMatch",
|
|
65
|
+
"JSONPathNameError",
|
|
66
|
+
"JSONPathSyntaxError",
|
|
67
|
+
"JSONPathTypeError",
|
|
68
|
+
"JSONPointer",
|
|
69
|
+
"JSONPointerError",
|
|
70
|
+
"JSONPointerIndexError",
|
|
71
|
+
"JSONPointerKeyError",
|
|
72
|
+
"JSONPointerResolutionError",
|
|
73
|
+
"JSONPointerTypeError",
|
|
74
|
+
"Lexer",
|
|
75
|
+
"NodeList",
|
|
76
|
+
"match",
|
|
77
|
+
"Parser",
|
|
78
|
+
"Projection",
|
|
79
|
+
"query",
|
|
80
|
+
"Query",
|
|
81
|
+
"RelativeJSONPointer",
|
|
82
|
+
"RelativeJSONPointerError",
|
|
83
|
+
"RelativeJSONPointerIndexError",
|
|
84
|
+
"RelativeJSONPointerSyntaxError",
|
|
85
|
+
"resolve",
|
|
86
|
+
"JSON",
|
|
87
|
+
"JSONData",
|
|
88
|
+
"JSONScalar",
|
|
89
|
+
"UNDEFINED",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# For convenience and to delegate to strict or non-strict environments.
|
|
94
|
+
DEFAULT_ENV = JSONPathEnvironment()
|
|
95
|
+
_STRICT_ENV = JSONPathEnvironment(strict=True)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def compile(path: str, *, strict: bool = False) -> Union[JSONPath, CompoundJSONPath]: # noqa: A001
|
|
99
|
+
"""Prepare a path string ready for repeated matching against different data.
|
|
100
|
+
|
|
101
|
+
Arguments:
|
|
102
|
+
path: A JSONPath as a string.
|
|
103
|
+
strict: When `True`, compile the path for strict compliance with RFC 9535.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
A `JSONPath` or `CompoundJSONPath`, ready to match against some data.
|
|
107
|
+
Expect a `CompoundJSONPath` if the path string uses the _union_ or
|
|
108
|
+
_intersection_ operators.
|
|
109
|
+
|
|
110
|
+
Raises:
|
|
111
|
+
JSONPathSyntaxError: If _path_ is invalid.
|
|
112
|
+
JSONPathTypeError: If filter functions are given arguments of an
|
|
113
|
+
unacceptable type.
|
|
114
|
+
"""
|
|
115
|
+
return _STRICT_ENV.compile(path) if strict else DEFAULT_ENV.compile(path)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def findall(
|
|
119
|
+
path: str,
|
|
120
|
+
data: JSONData,
|
|
121
|
+
*,
|
|
122
|
+
filter_context: Optional[FilterContextVars] = None,
|
|
123
|
+
strict: bool = False,
|
|
124
|
+
) -> List[object]:
|
|
125
|
+
"""Find all objects in _data_ matching the JSONPath _path_.
|
|
126
|
+
|
|
127
|
+
If _data_ is a string or a file-like objects, it will be loaded
|
|
128
|
+
using `json.loads()` and the default `JSONDecoder`.
|
|
129
|
+
|
|
130
|
+
Arguments:
|
|
131
|
+
path: The JSONPath as a string.
|
|
132
|
+
data: A JSON document or Python object implementing the `Sequence`
|
|
133
|
+
or `Mapping` interfaces.
|
|
134
|
+
filter_context: Arbitrary data made available to filters using
|
|
135
|
+
the _filter context_ selector.
|
|
136
|
+
strict: When `True`, compile and evaluate with strict compliance with
|
|
137
|
+
RFC 9535.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
A list of matched objects. If there are no matches, the list will
|
|
141
|
+
be empty.
|
|
142
|
+
|
|
143
|
+
Raises:
|
|
144
|
+
JSONPathSyntaxError: If the path is invalid.
|
|
145
|
+
JSONPathTypeError: If a filter expression attempts to use types in
|
|
146
|
+
an incompatible way.
|
|
147
|
+
"""
|
|
148
|
+
return (
|
|
149
|
+
_STRICT_ENV.findall(path, data, filter_context=filter_context)
|
|
150
|
+
if strict
|
|
151
|
+
else DEFAULT_ENV.findall(path, data, filter_context=filter_context)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
async def findall_async(
|
|
156
|
+
path: str,
|
|
157
|
+
data: JSONData,
|
|
158
|
+
*,
|
|
159
|
+
filter_context: Optional[FilterContextVars] = None,
|
|
160
|
+
strict: bool = False,
|
|
161
|
+
) -> List[object]:
|
|
162
|
+
"""Find all objects in _data_ matching the JSONPath _path_.
|
|
163
|
+
|
|
164
|
+
If _data_ is a string or a file-like objects, it will be loaded
|
|
165
|
+
using `json.loads()` and the default `JSONDecoder`.
|
|
166
|
+
|
|
167
|
+
Arguments:
|
|
168
|
+
path: The JSONPath as a string.
|
|
169
|
+
data: A JSON document or Python object implementing the `Sequence`
|
|
170
|
+
or `Mapping` interfaces.
|
|
171
|
+
filter_context: Arbitrary data made available to filters using
|
|
172
|
+
the _filter context_ selector.
|
|
173
|
+
strict: When `True`, compile and evaluate with strict compliance with
|
|
174
|
+
RFC 9535.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
A list of matched objects. If there are no matches, the list will
|
|
178
|
+
be empty.
|
|
179
|
+
|
|
180
|
+
Raises:
|
|
181
|
+
JSONPathSyntaxError: If the path is invalid.
|
|
182
|
+
JSONPathTypeError: If a filter expression attempts to use types in
|
|
183
|
+
an incompatible way.
|
|
184
|
+
"""
|
|
185
|
+
return (
|
|
186
|
+
await _STRICT_ENV.findall_async(path, data, filter_context=filter_context)
|
|
187
|
+
if strict
|
|
188
|
+
else await DEFAULT_ENV.findall_async(path, data, filter_context=filter_context)
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def finditer(
|
|
193
|
+
path: str,
|
|
194
|
+
data: JSONData,
|
|
195
|
+
*,
|
|
196
|
+
filter_context: Optional[FilterContextVars] = None,
|
|
197
|
+
strict: bool = False,
|
|
198
|
+
) -> Iterable[JSONPathMatch]:
|
|
199
|
+
"""Generate `JSONPathMatch` objects for each match of _path_ in _data_.
|
|
200
|
+
|
|
201
|
+
If _data_ is a string or a file-like objects, it will be loaded using
|
|
202
|
+
`json.loads()` and the default `JSONDecoder`.
|
|
203
|
+
|
|
204
|
+
Arguments:
|
|
205
|
+
path: The JSONPath as a string.
|
|
206
|
+
data: A JSON document or Python object implementing the `Sequence`
|
|
207
|
+
or `Mapping` interfaces.
|
|
208
|
+
filter_context: Arbitrary data made available to filters using
|
|
209
|
+
the _filter context_ selector.
|
|
210
|
+
strict: When `True`, compile and evaluate with strict compliance with
|
|
211
|
+
RFC 9535.
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
An iterator yielding `JSONPathMatch` objects for each match.
|
|
215
|
+
|
|
216
|
+
Raises:
|
|
217
|
+
JSONPathSyntaxError: If the path is invalid.
|
|
218
|
+
JSONPathTypeError: If a filter expression attempts to use types in
|
|
219
|
+
an incompatible way.
|
|
220
|
+
"""
|
|
221
|
+
return (
|
|
222
|
+
_STRICT_ENV.finditer(path, data, filter_context=filter_context)
|
|
223
|
+
if strict
|
|
224
|
+
else DEFAULT_ENV.finditer(path, data, filter_context=filter_context)
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
async def finditer_async(
|
|
229
|
+
path: str,
|
|
230
|
+
data: JSONData,
|
|
231
|
+
*,
|
|
232
|
+
filter_context: Optional[FilterContextVars] = None,
|
|
233
|
+
strict: bool = False,
|
|
234
|
+
) -> AsyncIterable[JSONPathMatch]:
|
|
235
|
+
"""Find all objects in _data_ matching the JSONPath _path_.
|
|
236
|
+
|
|
237
|
+
If _data_ is a string or a file-like objects, it will be loaded
|
|
238
|
+
using `json.loads()` and the default `JSONDecoder`.
|
|
239
|
+
|
|
240
|
+
Arguments:
|
|
241
|
+
path: The JSONPath as a string.
|
|
242
|
+
data: A JSON document or Python object implementing the `Sequence`
|
|
243
|
+
or `Mapping` interfaces.
|
|
244
|
+
filter_context: Arbitrary data made available to filters using
|
|
245
|
+
the _filter context_ selector.
|
|
246
|
+
strict: When `True`, compile and evaluate with strict compliance with
|
|
247
|
+
RFC 9535.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
A list of matched objects. If there are no matches, the list will
|
|
251
|
+
be empty.
|
|
252
|
+
|
|
253
|
+
Raises:
|
|
254
|
+
JSONPathSyntaxError: If the path is invalid.
|
|
255
|
+
JSONPathTypeError: If a filter expression attempts to use types in
|
|
256
|
+
an incompatible way.
|
|
257
|
+
"""
|
|
258
|
+
return (
|
|
259
|
+
await _STRICT_ENV.finditer_async(path, data, filter_context=filter_context)
|
|
260
|
+
if strict
|
|
261
|
+
else await DEFAULT_ENV.finditer_async(path, data, filter_context=filter_context)
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def match(
|
|
266
|
+
path: str,
|
|
267
|
+
data: JSONData,
|
|
268
|
+
*,
|
|
269
|
+
filter_context: Optional[FilterContextVars] = None,
|
|
270
|
+
strict: bool = False,
|
|
271
|
+
) -> Union[JSONPathMatch, None]:
|
|
272
|
+
"""Return a `JSONPathMatch` instance for the first object found in _data_.
|
|
273
|
+
|
|
274
|
+
`None` is returned if there are no matches.
|
|
275
|
+
|
|
276
|
+
Arguments:
|
|
277
|
+
path: The JSONPath as a string.
|
|
278
|
+
data: A JSON document or Python object implementing the `Sequence`
|
|
279
|
+
or `Mapping` interfaces.
|
|
280
|
+
filter_context: Arbitrary data made available to filters using
|
|
281
|
+
the _filter context_ selector.
|
|
282
|
+
strict: When `True`, compile and evaluate with strict compliance with
|
|
283
|
+
RFC 9535.
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
A `JSONPathMatch` object for the first match, or `None` if there were
|
|
287
|
+
no matches.
|
|
288
|
+
|
|
289
|
+
Raises:
|
|
290
|
+
JSONPathSyntaxError: If the path is invalid.
|
|
291
|
+
JSONPathTypeError: If a filter expression attempts to use types in
|
|
292
|
+
an incompatible way.
|
|
293
|
+
"""
|
|
294
|
+
return (
|
|
295
|
+
_STRICT_ENV.match(path, data, filter_context=filter_context)
|
|
296
|
+
if strict
|
|
297
|
+
else DEFAULT_ENV.match(path, data, filter_context=filter_context)
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def query(
|
|
302
|
+
path: str,
|
|
303
|
+
data: JSONData,
|
|
304
|
+
*,
|
|
305
|
+
filter_context: Optional[FilterContextVars] = None,
|
|
306
|
+
strict: bool = False,
|
|
307
|
+
) -> Query:
|
|
308
|
+
"""Return a `Query` iterator over matches found by applying _path_ to _data_.
|
|
309
|
+
|
|
310
|
+
`Query` objects are iterable.
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
for match in jsonpath.query("$.foo..bar", data):
|
|
314
|
+
...
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
You can skip and limit results with `Query.skip()` and `Query.limit()`.
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
matches = (
|
|
321
|
+
jsonpath.query("$.foo..bar", data)
|
|
322
|
+
.skip(5)
|
|
323
|
+
.limit(10)
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
for match in matches
|
|
327
|
+
...
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
`Query.tail()` will get the last _n_ results.
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
for match in jsonpath.query("$.foo..bar", data).tail(5):
|
|
334
|
+
...
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Get values for each match using `Query.values()`.
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
for obj in jsonpath.query("$.foo..bar", data).limit(5).values():
|
|
341
|
+
...
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Arguments:
|
|
345
|
+
path: The JSONPath as a string.
|
|
346
|
+
data: A JSON document or Python object implementing the `Sequence`
|
|
347
|
+
or `Mapping` interfaces.
|
|
348
|
+
filter_context: Arbitrary data made available to filters using
|
|
349
|
+
the _filter context_ selector.
|
|
350
|
+
strict: When `True`, compile and evaluate with strict compliance with
|
|
351
|
+
RFC 9535.
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
A query iterator.
|
|
355
|
+
|
|
356
|
+
Raises:
|
|
357
|
+
JSONPathSyntaxError: If the path is invalid.
|
|
358
|
+
JSONPathTypeError: If a filter expression attempts to use types in
|
|
359
|
+
an incompatible way.
|
|
360
|
+
"""
|
|
361
|
+
return (
|
|
362
|
+
_STRICT_ENV.query(path, data, filter_context=filter_context)
|
|
363
|
+
if strict
|
|
364
|
+
else DEFAULT_ENV.query(path, data, filter_context=filter_context)
|
|
365
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from io import IOBase
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Mapping
|
|
6
|
+
from typing import Sequence
|
|
7
|
+
from typing import Union
|
|
8
|
+
|
|
9
|
+
JSONScalar = Union[str, int, float, bool, None]
|
|
10
|
+
"""A scalar JSON-like value.
|
|
11
|
+
|
|
12
|
+
This includes primitive types that can appear in JSON:
|
|
13
|
+
string, number, boolean, or null.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
JSON = Union[JSONScalar, Sequence[Any], Mapping[str, Any]]
|
|
17
|
+
"""A JSON-like data structure.
|
|
18
|
+
|
|
19
|
+
This covers scalars, sequences (e.g. lists, tuples), and mappings (e.g.
|
|
20
|
+
dictionaries with string keys). Values inside may be untyped (`Any`) rather
|
|
21
|
+
than recursively constrained to `JSON` for flexibility.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
JSONData = Union[str, IOBase, JSON]
|
|
25
|
+
"""Input representing JSON content.
|
|
26
|
+
|
|
27
|
+
Accepts:
|
|
28
|
+
- a JSON-like object (`JSON`),
|
|
29
|
+
- a raw JSON string,
|
|
30
|
+
- or a file-like object containing JSON data.
|
|
31
|
+
"""
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""JSONPath, JSON Pointer and JSON Patch command line interface."""
|
|
2
|
+
|
|
2
3
|
import argparse
|
|
3
4
|
import json
|
|
4
5
|
import sys
|
|
@@ -59,6 +60,15 @@ def path_sub_command(parser: argparse.ArgumentParser) -> None: # noqa: D103
|
|
|
59
60
|
help="Disables filter expression well-typedness checks.",
|
|
60
61
|
)
|
|
61
62
|
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--strict",
|
|
65
|
+
action="store_true",
|
|
66
|
+
help=(
|
|
67
|
+
"Compile and evaluate JSONPath expressions with strict "
|
|
68
|
+
"compliance with RFC 9535."
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
|
|
62
72
|
|
|
63
73
|
def pointer_sub_command(parser: argparse.ArgumentParser) -> None: # noqa: D103
|
|
64
74
|
parser.set_defaults(func=handle_pointer_command)
|
|
@@ -248,6 +258,7 @@ def handle_path_command(args: argparse.Namespace) -> None: # noqa: PLR0912
|
|
|
248
258
|
path = jsonpath.JSONPathEnvironment(
|
|
249
259
|
unicode_escape=not args.no_unicode_escape,
|
|
250
260
|
well_typed=not args.no_type_checks,
|
|
261
|
+
strict=args.strict,
|
|
251
262
|
).compile(query)
|
|
252
263
|
except JSONPathSyntaxError as err:
|
|
253
264
|
if args.debug:
|
|
@@ -289,7 +300,6 @@ def handle_pointer_command(args: argparse.Namespace) -> None:
|
|
|
289
300
|
if args.pointer is not None:
|
|
290
301
|
pointer = args.pointer
|
|
291
302
|
else:
|
|
292
|
-
# TODO: is a property with a trailing newline OK?
|
|
293
303
|
pointer = args.pointer_file.read().strip()
|
|
294
304
|
|
|
295
305
|
try:
|