Skip to content

Commit dfa414c

Browse files
committed
refactor: save paren patterns
1 parent 122fa54 commit dfa414c

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

jsonpath/__init__.py

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Author : zhangxianbing
33
Date : 2020-12-27 09:22:14
44
LastEditors : zhangxianbing
5-
LastEditTime : 2021-02-07 10:10:55
5+
LastEditTime : 2021-03-02 14:50:49
66
Description : JSONPath
77
"""
88
__version__ = "1.0.3"
@@ -36,7 +36,7 @@ def create_logger(name: str = None, level: Union[int, str] = logging.INFO):
3636
return logger
3737

3838

39-
LOG = create_logger("jsonpath", os.getenv("PYLOGLEVEL", "INFO"))
39+
logger = create_logger("jsonpath", os.getenv("PYLOGLEVEL", "INFO"))
4040

4141

4242
class ExprSyntaxError(Exception):
@@ -49,15 +49,19 @@ class JSONPath:
4949
"PATH": "All path of specific values.",
5050
}
5151

52+
# common patterns
5253
SEP = ";"
53-
# regex patterns
54-
REP_PICKUP_QUOTE = re.compile(r"['](.*?)[']")
55-
REP_PICKUP_BRACKET = re.compile(r"[\[](.*?)[\]]")
56-
REP_PUTBACK_QUOTE = re.compile(r"#Q(\d+)")
57-
REP_PUTBACK_BRACKET = re.compile(r"#B(\d+)")
5854
REP_DOUBLEDOT = re.compile(r"\.\.")
5955
REP_DOT = re.compile(r"(?<!\.)\.(?!\.)")
6056

57+
# save special patterns
58+
REP_GET_QUOTE = re.compile(r"['](.*?)[']")
59+
REP_PUT_QUOTE = re.compile(r"#Q(\d+)")
60+
REP_GET_BRACKET = re.compile(r"[\[](.*?)[\]]")
61+
REP_PUT_BRACKET = re.compile(r"#B(\d+)")
62+
REP_GET_PAREN = re.compile(r"[\(](.*?)[\)]")
63+
REP_PUT_PAREN = re.compile(r"#P(\d+)")
64+
6165
# operators
6266
REP_SLICE_CONTENT = re.compile(r"^(-?\d*)?:(-?\d*)?(:-?\d*)?$")
6367
REP_SELECT_CONTENT = re.compile(r"^([\w.']+)(, ?[\w.']+)+$")
@@ -76,7 +80,7 @@ def __init__(self, expr: str):
7680
expr = self._parse_expr(expr)
7781
self.segments = expr.split(JSONPath.SEP)
7882
self.lpath = len(self.segments)
79-
LOG.debug(f"segments : {self.segments}")
83+
logger.debug(f"segments : {self.segments}")
8084

8185
def parse(self, obj, result_type="VALUE"):
8286
if not isinstance(obj, (list, dict)):
@@ -94,36 +98,46 @@ def parse(self, obj, result_type="VALUE"):
9498
return self.result
9599

96100
def _parse_expr(self, expr):
97-
LOG.debug(f"before expr : {expr}")
101+
logger.debug(f"before expr : {expr}")
98102

99-
expr = JSONPath.REP_PICKUP_QUOTE.sub(self._f_pickup_quote, expr)
100-
expr = JSONPath.REP_PICKUP_BRACKET.sub(self._f_pickup_bracket, expr)
103+
expr = JSONPath.REP_GET_QUOTE.sub(self._get_quote, expr)
104+
expr = JSONPath.REP_GET_BRACKET.sub(self._get_bracket, expr)
105+
expr = JSONPath.REP_GET_PAREN.sub(self._get_paren, expr)
101106
expr = JSONPath.REP_DOUBLEDOT.sub(f"{JSONPath.SEP}..{JSONPath.SEP}", expr)
102107
expr = JSONPath.REP_DOT.sub(JSONPath.SEP, expr)
103-
expr = JSONPath.REP_PUTBACK_BRACKET.sub(self._f_putback_bracket, expr)
104-
expr = JSONPath.REP_PUTBACK_QUOTE.sub(self._f_putback_quote, expr)
108+
expr = JSONPath.REP_PUT_PAREN.sub(self._put_paren, expr)
109+
expr = JSONPath.REP_PUT_BRACKET.sub(self._put_bracket, expr)
110+
expr = JSONPath.REP_PUT_QUOTE.sub(self._put_quote, expr)
105111
if expr.startswith("$;"):
106112
expr = expr[2:]
107113

108-
LOG.debug(f"after expr : {expr}")
114+
logger.debug(f"after expr : {expr}")
109115
return expr
110116

111-
def _f_pickup_quote(self, m):
117+
def _get_quote(self, m):
112118
n = len(self.subx["#Q"])
113119
self.subx["#Q"].append(m.group(1))
114120
return f"#Q{n}"
115121

116-
def _f_pickup_bracket(self, m):
122+
def _put_quote(self, m):
123+
return self.subx["#Q"][int(m.group(1))]
124+
125+
def _get_bracket(self, m):
117126
n = len(self.subx["#B"])
118127
self.subx["#B"].append(m.group(1))
119128
return f".#B{n}"
120129

121-
def _f_putback_quote(self, m):
122-
return self.subx["#Q"][int(m.group(1))]
123-
124-
def _f_putback_bracket(self, m):
130+
def _put_bracket(self, m):
125131
return self.subx["#B"][int(m.group(1))]
126132

133+
def _get_paren(self, m):
134+
n = len(self.subx["#P"])
135+
self.subx["#P"].append(m.group(1))
136+
return f"(#P{n})"
137+
138+
def _put_paren(self, m):
139+
return self.subx["#P"][int(m.group(1))]
140+
127141
@staticmethod
128142
def _f_brackets(m):
129143
ret = "__obj"
@@ -147,7 +161,7 @@ def _getattr(obj: dict, path: str):
147161
try:
148162
r = r.get(k)
149163
except (AttributeError, KeyError) as err:
150-
LOG.error(err)
164+
logger.error(err)
151165
return None
152166

153167
return r
@@ -167,7 +181,7 @@ def _filter(self, obj, i: int, path: str, step: str):
167181
try:
168182
r = eval(step, None, {"__obj": obj})
169183
except Exception as err:
170-
LOG.error(err)
184+
logger.error(err)
171185
if r:
172186
self._trace(obj, i, path)
173187

@@ -185,7 +199,7 @@ def _trace(self, obj, i: int, path):
185199
self.result.append(obj)
186200
elif self.result_type == "PATH":
187201
self.result.append(path)
188-
LOG.debug(f"path: {path} | value: {obj}")
202+
logger.debug(f"path: {path} | value: {obj}")
189203
return
190204

191205
step = self.segments[i]
@@ -259,15 +273,15 @@ def _trace(self, obj, i: int, path):
259273
obj_[k] = obj.get(k)
260274
self._trace(obj_, i + 1, path)
261275
else:
262-
raise ExprSyntaxError("field-extractor must acting on list or dict")
276+
raise ExprSyntaxError("field-extractor must acting on dict")
263277

264278
return
265279

266280

267281
if __name__ == "__main__":
268282
with open("test/data/2.json", "rb") as f:
269283
d = json.load(f)
270-
D = JSONPath("$[bicycle, scores]").parse(d, "VALUE")
284+
D = JSONPath("$.scores[/(score)].(score)").parse(d, "VALUE")
271285
print(D)
272286
for v in D:
273287
print(v)

0 commit comments

Comments
 (0)