Skip to content

Commit f06786d

Browse files
committed
refactor: common JSON document loader
1 parent c07dbd1 commit f06786d

File tree

4 files changed

+43
-62
lines changed

4 files changed

+43
-62
lines changed

jsonpath/_data.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import json
2+
import re
3+
from io import IOBase
4+
from typing import Any
5+
6+
_RE_PROBABLY_MALFORMED = re.compile(r"[\{\}\[\]]")
7+
8+
9+
def load_data(data: object) -> Any:
10+
if isinstance(data, str):
11+
try:
12+
return json.loads(data)
13+
except json.JSONDecodeError:
14+
# Overly simple way to detect a malformed JSON document vs a
15+
# top-level string only document
16+
if _RE_PROBABLY_MALFORMED.search(data):
17+
raise
18+
return data
19+
if isinstance(data, IOBase):
20+
return json.loads(data.read())
21+
return data

jsonpath/patch.py

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,24 @@
66
from abc import ABC
77
from abc import abstractmethod
88
from io import IOBase
9-
from typing import Any
109
from typing import Dict
1110
from typing import Iterable
1211
from typing import List
1312
from typing import Mapping
1413
from typing import MutableMapping
1514
from typing import MutableSequence
16-
from typing import Sequence
1715
from typing import TypeVar
1816
from typing import Union
1917

20-
from .exceptions import JSONPatchError
21-
from .exceptions import JSONPatchTestFailure
22-
from .exceptions import JSONPointerError
23-
from .exceptions import JSONPointerIndexError
24-
from .exceptions import JSONPointerKeyError
25-
from .exceptions import JSONPointerTypeError
26-
from .pointer import UNDEFINED
27-
from .pointer import JSONPointer
18+
from jsonpath._data import load_data
19+
from jsonpath.exceptions import JSONPatchError
20+
from jsonpath.exceptions import JSONPatchTestFailure
21+
from jsonpath.exceptions import JSONPointerError
22+
from jsonpath.exceptions import JSONPointerIndexError
23+
from jsonpath.exceptions import JSONPointerKeyError
24+
from jsonpath.exceptions import JSONPointerTypeError
25+
from jsonpath.pointer import UNDEFINED
26+
from jsonpath.pointer import JSONPointer
2827

2928

3029
class Op(ABC):
@@ -537,7 +536,7 @@ def apply(
537536
JSONPatchTestFailure: When a _test_ operation does not pass.
538537
`JSONPatchTestFailure` is a subclass of `JSONPatchError`.
539538
"""
540-
_data = _load_data(data)
539+
_data = load_data(data)
541540

542541
for i, op in enumerate(self.ops):
543542
try:
@@ -598,18 +597,3 @@ def apply(
598597
unicode_escape=unicode_escape,
599598
uri_decode=uri_decode,
600599
).apply(data)
601-
602-
603-
def _load_data(
604-
data: Union[int, str, IOBase, Sequence[Any], MutableMapping[str, Any]]
605-
) -> Any:
606-
if isinstance(data, str):
607-
try:
608-
return json.loads(data)
609-
except json.JSONDecodeError:
610-
data = data.strip()
611-
if data.startswith('"') and data.endswith('"'):
612-
return data
613-
if isinstance(data, IOBase):
614-
return json.loads(data.read())
615-
return data

jsonpath/path.py

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from __future__ import annotations
33

44
import itertools
5-
import json
6-
from io import IOBase
75
from typing import TYPE_CHECKING
86
from typing import Any
97
from typing import AsyncIterable
@@ -16,10 +14,13 @@
1614
from typing import TypeVar
1715
from typing import Union
1816

19-
from .match import FilterContextVars
20-
from .match import JSONPathMatch
17+
from jsonpath._data import load_data
18+
from jsonpath.match import FilterContextVars
19+
from jsonpath.match import JSONPathMatch
2120

2221
if TYPE_CHECKING:
22+
from io import IOBase
23+
2324
from .env import JSONPathEnvironment
2425
from .selectors import JSONPathSelector
2526

@@ -114,7 +115,7 @@ def finditer(
114115
JSONPathTypeError: If a filter expression attempts to use types in
115116
an incompatible way.
116117
"""
117-
_data = _load_data(data)
118+
_data = load_data(data)
118119
matches: Iterable[JSONPathMatch] = [
119120
JSONPathMatch(
120121
filter_context=filter_context or {},
@@ -152,7 +153,7 @@ async def finditer_async(
152153
filter_context: Optional[FilterContextVars] = None,
153154
) -> AsyncIterable[JSONPathMatch]:
154155
"""An async version of `finditer()`."""
155-
_data = _load_data(data)
156+
_data = load_data(data)
156157

157158
async def root_iter() -> AsyncIterable[JSONPathMatch]:
158159
yield self.env.match_class(
@@ -408,16 +409,3 @@ async def _achain(*iterables: AsyncIterable[T]) -> AsyncIterable[T]:
408409
for it in iterables:
409410
async for element in it:
410411
yield element
411-
412-
413-
def _load_data(data: Union[str, IOBase, Sequence[Any], Mapping[str, Any]]) -> Any:
414-
if isinstance(data, str):
415-
try:
416-
return json.loads(data)
417-
except json.JSONDecodeError:
418-
data = data.strip()
419-
if data.startswith('"') and data.endswith('"'):
420-
return data
421-
if isinstance(data, IOBase):
422-
return json.loads(data.read())
423-
return data

jsonpath/pointer.py

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
from __future__ import annotations
33

44
import codecs
5-
import json
65
import re
76
from functools import reduce
8-
from io import IOBase
97
from operator import getitem
108
from typing import TYPE_CHECKING
119
from typing import Any
@@ -16,6 +14,7 @@
1614
from typing import Union
1715
from urllib.parse import unquote
1816

17+
from jsonpath._data import load_data
1918
from jsonpath.exceptions import JSONPointerError
2019
from jsonpath.exceptions import JSONPointerIndexError
2120
from jsonpath.exceptions import JSONPointerKeyError
@@ -25,6 +24,8 @@
2524
from jsonpath.exceptions import RelativeJSONPointerSyntaxError
2625

2726
if TYPE_CHECKING:
27+
from io import IOBase
28+
2829
from .match import JSONPathMatch
2930

3031

@@ -190,7 +191,7 @@ def resolve(
190191
JSONPointerTypeError: When attempting to resolve a non-index string
191192
path part against a sequence, unless a default is given.
192193
"""
193-
data = _load_data(data)
194+
data = load_data(data)
194195
try:
195196
return reduce(self._getitem, self.parts, data)
196197
except JSONPointerResolutionError:
@@ -224,7 +225,7 @@ def resolve_parent(
224225
if not self.parts:
225226
return (None, self.resolve(data))
226227

227-
_data = _load_data(data)
228+
_data = load_data(data)
228229
parent = reduce(self._getitem, self.parts[:-1], _data)
229230

230231
try:
@@ -594,19 +595,6 @@ def to(
594595
)
595596

596597

597-
def _load_data(data: Union[int, str, IOBase, Sequence[Any], Mapping[str, Any]]) -> Any:
598-
if isinstance(data, str):
599-
try:
600-
return json.loads(data)
601-
except json.JSONDecodeError:
602-
data = data.strip()
603-
if data.startswith('"') and data.endswith('"'):
604-
return data
605-
if isinstance(data, IOBase):
606-
return json.loads(data.read())
607-
return data
608-
609-
610598
def resolve(
611599
pointer: Union[str, Iterable[Union[str, int]]],
612600
data: Union[str, IOBase, Sequence[object], Mapping[str, object]],

0 commit comments

Comments
 (0)