1.問題
在遇到json數據的過程中,我們經常需要獲取json數據中某個值的操作,如果是用get方法去取比較繁瑣,接下來介紹兩種方式來取值。
2.jsonpath來格式化處理json數據
2.1介紹
JsonPath是一種信息抽取類庫,是從JSON文檔中抽取指定信息的工具,提供多種語言實現版本,包括JavaScript、Python、PHP和Java。JsonPath對於JSON來說,就相當於XPATH對於XML。
JsonPath結構清晰,可讀性高,復雜度低,非常容易匹配,下表中對應了XPath的用法。
2.2安裝
pip安裝:
pip install jsonpath
官網文檔:http://goessner.net/articles/JsonPath
2.3使用
使用方法: # 導入 import jsonpath # 結果會以列表形式返回,如下請求接口返回數據提取例子 jsonpath.jsonpath(參數1,參數2)[] # 參數 參數1:數據對象 參數2:jsonpath表達式
[]:如果有重復的鍵,需要獲取第幾個鍵的值
2.4使用示例:
import jsonpath json_data = { "resultcode":"200", "reason":"成功的返回", "result": { "company":"順豐", "com":"sf", "no":"575677355677", "list":[ { "datetime":"2013-06-25 10:44:05", "remark":"已收件", "zone":"台州市" }, { "datetime":"2013-06-25 11:05:21", "remark":"快件在 台州 ,准備送往下一站 台州集散中心 ", "zone":"台州市" } ], "status":1 }, "error_code":0 } resultcode = jsonpath.jsonpath(json_data,"$..resultcode")[0] print("返回的code:",resultcode) company = jsonpath.jsonpath(json_data, "$..company")[0] print("快遞公司:",company) remark = jsonpath.jsonpath(json_data,"$..remark")[-1] print("快遞目前到達的地點:",remark) 結果: 返回的code: 200 快遞公司: 順豐 快遞目前到達的地點: 快件在 台州 ,准備送往下一站 台州集散中心
3.jmespath來格式化處理json數據
jmespath是另一種用來處理json數據的庫。
3.1安裝
pip安裝:
pip install jmespath
官網文檔:https://jmespath.org/tutorial.html
3.2基本操作
import jmespath source = {"a": "foo", "b": "bar", "c": "baz"} result = jmespath.search('b', source) print(repr(result)) 結果: 'bar'
3.3 .操作符
import jmespath source1 = {"a": {"b": {"c": {"d": "value"}}}} result1 = jmespath.search('a.b.c', source1) print(repr(result1)) 結果: {'d': 'value'}
3.4下標操作(僅用於數組)
import jmespath source_2 = ["a", "b", "c", "d", "e", "f"] index_result = jmespath.search("[1]",source_2) print(repr(index_result)) 結果: 'b'
3.5下標和.操作符混合操作
import jmespath source3 = {"a": { "b": { "c": [ {"d": [0, [1, 2]]}, {"d": [3, 4]} ] } }} result3 = jmespath.search('a.b.c[0].d[1][0]',source3) print(repr(result3)) 結果: 1
3.6接下來用實際的json數據測試一下
import jmespath json_data = { "resultcode":"200", "reason":"成功的返回", "result": { "company":"順豐", "com":"sf", "no":"575677355677", "list":[ { "datetime":"2013-06-25 10:44:05", "remark":"已收件", "zone":"台州市" }, { "datetime":"2013-06-25 11:05:21", "remark":"快件在 台州 ,准備送往下一站 台州集散中心 ", "zone":"台州市" } ], "status":1 }, "error_code":0 } resultcode = jmespath.search("resultcode",json_data) print("返回的code:",resultcode) company = jmespath.search("result.company",json_data) print("快遞公司:",company) remark = jmespath.search("result.list[1].remark",json_data) print("快遞目前到達的地點:",remark) 結果: 返回的code: 200 快遞公司: 順豐 快遞目前到達的地點: 快件在 台州 ,准備送往下一站 台州集散中心
3.7jmespath的其他使用方式
•切片
import jmespath source_4 = ["a", "b", "c", "d", "e", "f"] result4 = jmespath.search("[1:3]",source_4) print(repr(result4)) 結果: ['b', 'c']
•投影
投影其實就是初始時定義好格式,然后按照格式的方式進行取值。
投影主要包括以下幾種:
List Projections列表投影
Slice Projections切片投影
Object Projections對象投影
Flatten Projections正則投影
Filter Projections過濾條件投影
注意:取列表用[],取字典用.
列表和切片投影
import jmespath source5 = { "people": [ {"first": "James", "last": "d"}, {"first": "Jacob", "last": "e"}, {"first": "Jayden", "last": "f"}, {"missing": "different"} ], "foo": {"bar": "baz"} } result5 = jmespath.search('people[*].first', source5) print(result5) 結果: ['James', 'Jacob', 'Jayden']
對象投影
列表投影是為JSON數組定義的,而對象投影是為JSON對象定義的。
import jmespath source6 = { "ops": { "functionA": {"numArgs": 2}, "functionB": {"numArgs": 3}, "functionC": {"variadic": True} } } result6 = jmespath.search('ops.*.numArgs', source6) print(repr(result6)) 結果: [2, 3]
Filter Projections 帶過濾條件投影
格式[? <expression> <comparator> <expression>]
支持 ==, !=, <, <=, >, >=
import jmespath source7 = { "people": [ { "general": { "id": 100, "age": 20, "other": "foo", "name": "Bob" }, "history": { "first_login": "2014-01-01", "last_login": "2014-01-02" } }, { "general": { "id": 101, "age": 30, "other": "bar", "name": "Bill" }, "history": { "first_login": "2014-05-01", "last_login": "2014-05-02" } } ] } result7 = jmespath.search("people[?general.age > `20`].general | [0]", source7) print(repr(result7)) 結果: {'id': 101, 'age': 30, 'other': 'bar', 'name': 'Bill'}
4.自己寫個類來處理json數據
class ExtractData: def traverse_take_field(data,fields,values=[],currentKye=None): ''' 遍歷嵌套字典列表,取出某些字段的值 :param data: 嵌套字典列表 :param fields: 列表,某些字段 :param values: 返回的值 :param currentKye: 當前的鍵值 :return: 列表 ''' if isinstance(data,list): for i in data: ExtractData.traverse_take_field(i,fields,values,currentKye) elif isinstance(data,dict): for key,value in data.items(): ExtractData.traverse_take_field(value,fields,values,key) else: if currentKye in fields: values.append(data) return values if __name__ == '__main__': json_data = { "resultcode":"200", "reason":"成功的返回", "result":{ "company":"順豐", "com":"sf", "no":"575677355677", "list":[ { "datetime":"2013-06-25 10:44:05", "remark":"已收件", "zone":"台州市" }, { "datetime":"2013-06-25 11:05:21", "remark":"快件在 台州 ,准備送往下一站 台州集散中心 ", "zone":"台州市" } ], "status":1 }, "error_code":0 } resultcode = ExtractData.traverse_take_field(data=json_data,fields="resultcode") print("返回的code:",resultcode) 結果: 返回的code: ['200']
目前自己寫的這個類還不完善,有以下幾個缺點:
1、只能獲取最底層的值
2、重復的鍵例如:remark,獲取值后,會把所有的值都獲取出來。
3、對於包含的鍵,無法做出區分,列如:想要獲取鍵company的值,會吧鍵com的值也一起獲取出來。
等有時間可以繼續完善。