Skip to content

Commit ef7659b

Browse files
committed
refactor: finish operator: sort
1 parent 852f9a3 commit ef7659b

File tree

2 files changed

+46
-13
lines changed

2 files changed

+46
-13
lines changed

jsonpath/__init__.py

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Author : zhangxianbing1
33
Date : 2020-12-27 09:22:14
44
LastEditors : zhangxianbing1
5-
LastEditTime : 2020-12-31 17:02:04
5+
LastEditTime : 2020-12-31 18:05:36
66
Description : JSONPath
77
"""
88
__version__ = "1.0.0"
@@ -30,13 +30,10 @@
3030
REP_DOUBLEDOT = re.compile(r"\.\.")
3131
REP_DOT = re.compile(r"(?<!\.)\.(?!\.)")
3232

33-
33+
# operators
3434
REP_SLICE_CONTENT = re.compile(r"^(-?\d*)?:(-?\d*)?(:-?\d*)?$")
3535
REP_SELECT_CONTENT = re.compile(r"^([\w.]+)(,[\w.]+)+$")
36-
# operators
37-
REP_UNION_OP = re.compile(r"(?<!\\),")
38-
39-
REP_FILTER_FIELD = re.compile(
36+
REP_FILTER_CONTENT = re.compile(
4037
r"@\.(.*?)(?=<=|>=|==|!=|>|<| in| not| is)|len\(@\.(.*?)\)"
4138
)
4239

@@ -47,6 +44,18 @@ def concat(x, y, con=SEP):
4744
return f"{x}{con}{y}"
4845

4946

47+
def _getattr(obj: dict, path: str):
48+
r = obj
49+
for k in path.split("."):
50+
try:
51+
r = r.get(k)
52+
except (AttributeError, KeyError) as err:
53+
print(err)
54+
return None
55+
56+
return r
57+
58+
5059
class ExprSyntaxError(Exception):
5160
pass
5261

@@ -150,7 +159,7 @@ def _trace(self, obj, istep: int):
150159
151160
Args:
152161
obj ([type]): current operating object
153-
idx (int): current operation specified by index in self.ops
162+
istep (int): current operation specified by index in self.steps
154163
"""
155164

156165
# store
@@ -201,20 +210,32 @@ def _trace(self, obj, istep: int):
201210
# filter
202211
if step.startswith("?(") and step.endswith(")"):
203212
step = step[2:-1]
204-
step = REP_FILTER_FIELD.sub(self._f_brackets, step)
213+
step = REP_FILTER_CONTENT.sub(self._f_brackets, step)
205214
self._traverse(self._filter, obj, istep + 1, step)
206215
return
207216

208217
# sort
209-
# elif key:
210-
# pass
218+
if step.startswith("/(") and step.endswith(")"):
219+
if isinstance(obj, list):
220+
step = step[2:-1]
221+
for sortby in step.split(",")[::-1]:
222+
if sortby.startswith("~"):
223+
obj.sort(
224+
key=lambda t, k=sortby: _getattr(t, k[1:]), reverse=True
225+
)
226+
else:
227+
obj.sort(key=lambda t, k=sortby: _getattr(t, k))
228+
229+
self._traverse(self._trace, obj, istep + 1)
230+
return
211231

212232

213233
if __name__ == "__main__":
214234
# JSONPath("$.a.'b.c'.'d e'.[f,g][h][*][j.k][l m][2:4]..d", result_type="FIELD")
215235
with open("test/data/2.json", "rb") as f:
216236
d = json.load(f)
217-
JSONPath(
218-
'$.book[?(@.title=="Herman Melville" or @.title=="Evelyn Waugh")].title'
219-
).parse(d)
237+
# JSONPath(
238+
# '$.book[?(@.title=="Herman Melville" or @.title=="Evelyn Waugh")].title'
239+
# ).parse(d)
220240
# JSONPath("$..price").parse(d)
241+
JSONPath("$.book[/(price)].price").parse(d)

test/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,30 @@
1111
"author": "Nigel Rees",
1212
"title": "Sayings of the Century",
1313
"price": 8.95,
14+
"brand": {"version": "v1.0.0"},
1415
},
1516
{
1617
"category": "fiction",
1718
"author": "Evelyn Waugh",
1819
"title": "Sword of Honour",
1920
"price": 12.99,
21+
"brand": {"version": "v0.0.1"},
2022
},
2123
{
2224
"category": "fiction",
2325
"author": "Herman Melville",
2426
"title": "Moby Dick",
2527
"isbn": "0-553-21311-3",
2628
"price": 8.99,
29+
"brand": {"version": "v1.0.2"},
2730
},
2831
{
2932
"category": "fiction",
3033
"author": "J. R. R. Tolkien",
3134
"title": "The Lord of the Rings",
3235
"isbn": "0-395-19395-8",
3336
"price": 22.99,
37+
"brand": {"version": "v1.0.3"},
3438
},
3539
],
3640
"bicycle": {"color": "red", "price": 19.95},
@@ -65,6 +69,14 @@
6569
data,
6670
["Evelyn Waugh", "Herman Melville"],
6771
),
72+
TestCase("$.book[/(price)].price", data, [8.95, 8.99, 12.99, 22.99]),
73+
TestCase("$.book[/(~price)].price", data, [22.99, 12.99, 8.99, 8.95]),
74+
TestCase("$.book[/(category,price)].price", data, [8.99, 12.99, 22.99, 8.95]),
75+
TestCase(
76+
"$.book[/(brand.version)].brand.version",
77+
data,
78+
["v0.0.1", "v1.0.0", "v1.0.2", "v1.0.3"],
79+
),
6880
]
6981
)
7082
def cases(request):

0 commit comments

Comments
 (0)