11"""
2- Author : zhangxianbing1
2+ Author : zhangxianbing
33Date : 2020-12-27 09:22:14
4- LastEditors : zhangxianbing1
5- LastEditTime : 2021-01-04 14:34:35
4+ LastEditors : zhangxianbing
5+ LastEditTime : 2021-01-04 15:25:08
66Description : JSONPath
77"""
88__version__ = "0.0.3"
99__author__ = "zhangxianbing"
1010
1111import json
12+ import logging
1213import os
1314import re
14- import logging
1515from collections import defaultdict
1616from typing import Union
1717
@@ -46,7 +46,6 @@ class ExprSyntaxError(Exception):
4646class JSONPath :
4747 RESULT_TYPE = {
4848 "VALUE" : "A list of specific values." ,
49- "FIELD" : "A dict with specific fields." ,
5049 "PATH" : "All path of specific values." ,
5150 }
5251
@@ -70,7 +69,7 @@ class JSONPath:
7069 steps : list
7170 lpath : int
7271 subx = defaultdict (list )
73- result : Union [ list , dict ]
72+ result : list
7473 result_type : str
7574
7675 def __init__ (self , expr : str ):
@@ -82,16 +81,14 @@ def __init__(self, expr: str):
8281 def parse (self , obj , result_type = "VALUE" ):
8382 if not isinstance (obj , (list , dict )):
8483 raise TypeError ("obj must be a list or a dict." )
84+
8585 if result_type not in JSONPath .RESULT_TYPE :
8686 raise ValueError (
8787 f"result_type must be one of { tuple (JSONPath .RESULT_TYPE .keys ())} "
8888 )
8989 self .result_type = result_type
90- if self .result_type == "FIELD" :
91- self .result = {}
92- else :
93- self .result = []
9490
91+ self .result = []
9592 self ._trace (obj , 0 , "$" )
9693
9794 return self .result
@@ -188,8 +185,6 @@ def _trace(self, obj, i: int, path):
188185 self .result .append (obj )
189186 elif self .result_type == "PATH" :
190187 self .result .append (path )
191- elif self .result_type == "FIELD" :
192- pass
193188 LOG .debug (f"path: { path } | value: { obj } " )
194189 return
195190
@@ -240,7 +235,7 @@ def _trace(self, obj, i: int, path):
240235 self ._traverse (self ._filter , obj , i + 1 , path , step )
241236 return
242237
243- # sort
238+ # sorter
244239 if step .startswith ("/(" ) and step .endswith (")" ):
245240 if isinstance (obj , list ):
246241 obj = list (enumerate (obj ))
@@ -253,12 +248,24 @@ def _trace(self, obj, i: int, path):
253248 for k , v in obj :
254249 self ._trace (v , i + 1 , f"{ path } { JSONPath .SEP } { k } " )
255250 else :
256- raise ExprSyntaxError ("sort operate must acting on list or dict" )
251+ raise ExprSyntaxError ("sorter must acting on list or dict" )
257252 return
258253
254+ # field-extractor
255+ if step .startswith ("(" ) and step .endswith (")" ):
256+ if isinstance (obj , dict ):
257+ obj_ = {}
258+ for k in step [1 :- 1 ].split ("," ):
259+ obj_ [k ] = obj .get (k )
260+ self ._trace (obj_ , i + 1 , path )
261+ else :
262+ raise ExprSyntaxError ("field-extractor must acting on list or dict" )
263+
259264
260265if __name__ == "__main__" :
261266 with open ("test/data/2.json" , "rb" ) as f :
262267 d = json .load (f )
263- D = JSONPath ("$.book[/(price)].price " ).parse (d , "PATH " )
268+ D = JSONPath ("$.book[*].(title) " ).parse (d , "VALUE " )
264269 print (D )
270+ for v in D :
271+ print (v )
0 commit comments