Python格式化處理json數據的方式


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的值也一起獲取出來。

等有時間可以繼續完善。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM