如何用 Python 與 Pandas 高效處理 JSON 資料?

△點選上方「Python貓」關注 ,回復「2」加入交流群

作者:Peter
來源:Python程式設計時光

在實際工作中,尤其是web資料的傳輸,我們經常會遇到json資料。它不像常見的文字資料、數值資料那樣友好,而且它和Python中的字典型別資料又很相像,給很多人造成了困擾。

本文結合具體範例詳細介紹了如何利用Python和pandas(Python的第三方庫)來處理json資料,主要內容包含:

  • json資料簡介

  • 常用json資料轉化網站

  • json資料和Python資料的轉化

  • pandas處理json資料

1. JSON 簡單介紹

1.1 什麼是json資料

首先,我們看一段來自維基百科對json的解釋:

JSONJavaScript Object Notation,JavaScript物件表示法)是一種由道格拉斯·克羅克福特構想和設計、輕量級的資料交換語言,該語言以易於讓人閱讀的文字為基礎,用來傳輸由屬性值或者序列性的值組成的資料物件。

JSON 資料格式與語言無關。即便它源自JavaScript,但目前很多程式設計語言都支援 JSON 格式資料的生成和解析。副檔名是 .json

透過上面的官方介紹,我們總結3點:

  • JSON是一種文字(資料)語言,超輕量級的資料交換格式

  • JSON資料容易閱讀,易讀性強

  • 源自JavaScript,其他語言可解析JSON資料

1.2 json資料型態

JSON實際上是JavaScript的一個子集,JSON語言中僅有的6種資料型態或者它們之間的任意組合:

  • number:和JavaScript中的number一致

  • boolean:JavaScript中的true或者false

  • string:JavaScript中的string

  • null:JavaScript中的null

  • array:JavaScript的表示方式:[]

  • object:JavaScript的{…}表示方式

1.3 兩點規定

1、JSON語言中規定了編碼表必須是UTF-8

2、為了統一解析,JSON的字串規定必須是雙引號""

2. 常用json資料轉化網站

1、json.cn:https://www.json.cn/

2、json菜鳥工具:https://c.runoob.com/front-end/53

3、sojson:https://www.sojson.com/,非常全的json處理網站

4、kjson:https://www.kjson.com/

5、程式設計獅-json檢驗工具:https://www.w3cschool.cn/tools/index?name=jsoncheck

6、JSONViewer:http://jsonviewer.stack.hu/,用於檢測Json格式是否正確的一個線上應用工具

3. JSON 和 Dict 型別轉化

本小節主要講解的json型別資料和Python型別的轉化。

json物件和Python字典的轉化主要使用的是內建json包,下面詳細介紹該包的使用。詳細的學習資料見官網:https://docs.python.org/3/library/json.html

首先使用的時候直接匯入該包:

1
import json

json包中存在4中方法用來進行和Python內建資料型態的轉化:

方法 作用
json.dumps() 將python物件編碼成Json字串:字典到json
json.loads() 將Json字串解碼成python物件:json到字典
json.dump() 將python中的物件轉化成json儲存到檔案中
json.load() 將檔案中的json的格式轉化成python物件選取出來

筆記:兩個和load相關的方法只是多了一步和檔案相關的操作。

json.dumps

和dump相關的兩個函式是將Python資料型態轉成json型別,轉化對照表如下:

Python JSON
dict object
list, tuple array
str, unicode string
int, long, float number
True true
False false
None null

json.dumps方法的作用是將Python字典型別的資料轉成json格式的資料,具體的引數如下:

1
2
3
4
5
6
7
8
9
10
11
12
json.dumps(obj,   # 待轉化的物件
           skipkeys=False,  # 預設值是False,若dict的keys內的資料不是python的基本型別(str,unicode,int,long,float,bool,None),設定為False時,就會報TypeError的錯誤。此時設定成True,則會跳過這類key
           ensure_ascii=True,  # 預設是ASCII碼,若設定成False,則可以輸出中文
           check_circular=True,  # 若為False,跳過對容器型別的迴圈引用檢查
           allow_nan=True,  # 若allow_nan為假,則ValueError將序列化超出範圍的浮點值(nan、inf、-inf),嚴格遵守JSON規範,而不是使用JavaScript等效值(nan、Infinity、-Infinity)
           cls=None,
           indent=None, # 引數根據格式縮進顯示,表示縮進幾個空白
           separators=None,   # 指定分隔符;包含不同dict項之間的分隔符和key與value之間的分隔符;同時去掉`: `
           encoding="utf-8",  # 編碼
           default=None, # 預設是一個函式,應該回傳可序列化的obj版本或者引髮型別錯誤;預設值是只引髮型別錯誤
           sort_keys=False,  # 若為False,則字典的鍵不排序;設定成True,按照字典排序(a到z)
           **kw)

透過範例來解釋上面幾個常見引數的作用

1、當我們的Python型別資料中存在中文

1
2
3
4
5
6
7
8
9
10
11
information1 = {
    'name': '小明',
    'age': 18,
    'address': 'shenzhen'
}
# 字典轉成json資料
information2 = json.dumps(information1)

print(type(information1))
print(type(information2))
print(information2)

加上ensure_ascii=False引數即可顯示中文:

1
2
# 字典轉成json資料
information3 = json.dumps(information1,ensure_ascii=False)

??透過結果我們發現:json資料中全部變成了雙引號,原來的字典型別資料中使用的是單引號,再看一個關於引號變化的範例:

1
2
3
4
5
6
7
8
>>> import json
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))  # python中的鍵是字串,用單引號

# 結果顯示
{
    "4": 5,  # 變成雙引號
    "6": 7
}

2、對json資料透過縮進符美觀輸出,使用indent引數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
information4 = {
    'name': '小明',
    'age': 18,
    'skills': 'python',
    'english': 'CET6',
    'major': '會計',
    'address': '深圳'
}

information5 = json.dumps(information4, ensure_ascii=False)   # 不縮進
information6 = json.dumps(information4, ensure_ascii=False, indent=2)  # 縮進2個空白  
information7 = json.dumps(information4, ensure_ascii=False, indent=5)  # 縮進5個空白


print(information5)
print(information6)
print(information7)

3、對Python資料型態中鍵進行排序輸出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
information4 = {
    'name': '小明',
    'age': 18,
    'skills': 'python',
    'english': 'CET6',
    'major': '會計',
    'address': '深圳'
}

information8 = json.dumps(information4, ensure_ascii=False, indent=2)  #
information9 = json.dumps(information4, ensure_ascii=False, indent=2,sort_keys=True)  #  鍵的排序設定成True

print(information8)
print(information9)

透過sort_keys=True的設定,可以觀察到輸出的結果進行了首寫字母的排序;當首寫字母相同,按照第二個字母再進行排序。

4、輸出分隔符的控制

使用separators引數來設定不同的輸出分隔符;不同的dic元素之間預設是,鍵值對之間預設是:

1
2
3
4
5
6
7
8
9
10
11
information1 = {
    'name': '小明',
    'age': 18,
    'address': 'shenzhen'
}

information2 = json.dumps(information1,ensure_ascii=False)
information10 = json.dumps(information1,ensure_ascii=False,separators=('+','@'))  # 改變分隔符

print(information2)  # 預設連接符
print(information10)

json.dump

json.dump功能和json.dumps類似,只是需要將資料存入到檔案中,二者引數相同

我們嘗試將下面的個人訊息寫入到檔案中

1
2
3
4
5
6
7
8
information = {
    'name': '小明',
    'age': 18,
    'skills': 'python',
    'english': 'CET6',
    'major': '會計',
    'address': '深圳'
}

1、如果不使用indent引數,全部訊息顯示為一行

1
2
3
4
5
6
7
8
# 使用json.dump;json資料一定是雙引號

with open("information_1_to_json.json", "w", encoding='utf-8') as f:
    # json.dump(dic_, f) # 全部寫入一行資料,不換行
    json.dump(information,   # 待寫入資料
              f, # File物件
              sort_keys=True,  # 鍵的排序
              ensure_ascii=False)  # 顯示中文

看看實際的儲存效果:

加入indent引數,會顯示成多行資料:

1
2
3
4
5
6
with open("information_2_to_json.json", "w", encoding='utf-8') as f:
    json.dump(information,
              f,
              indent=2,  # 空白縮進符,寫入多行
              sort_keys=True,
              ensure_ascii=False)

json.loads

load相關的兩個函式是將json轉成Python資料型態,轉化對照表如下:

JSON Python
object dict
array list
string unicode
number (int) int, long
number (real) float
true True
false False
null None

json.loads的作用是將json格式的資料轉成Python字典型別的資料。

1
2
3
4
5
6
7
8
9
10
information1 = {
    'name': '小明',
    'age': 18,
    'address': 'shenzhen'
}
# 字典轉成json資料
information3 = json.dumps(information1,ensure_ascii=False)

information11 = json.loads(information3)  # json轉成字典資料
print(information11)

json.load

開啟json檔案再轉成字典形式的資料

1
2
3
4
5
6
# 使用json.load

with open("information_to_json.json",encoding="utf-8") as f:
    json_to_dict = json.load(f)  # json轉成字典

print(json_to_dict)

4. JSON 和 非 Dict 型別的轉化

上面介紹的主要是json格式資料和Python字典之間的轉化,下面講解了Python其他資料型態透過json.dumps方法轉成json個資料:

1、元組轉化

2、串列轉化

3、布林值轉化

4、數值型資料轉化

5. 利用 Demjson 來解析

DemjsonPython的第三方庫,能夠用於編碼和解碼json資料:

  • encode:將 Python 物件編碼成 JSON 字串

  • decode:將已編碼的 JSON 字串解碼為 Python 物件

安裝demjson

直接使用pip install demjson安裝,kan'dao看到如下介面表示安裝成功。

使用demjson

使用之前先進行匯入:

1
import demjson   # 匯入包

1、編碼功能

2、解碼功能

demjson包一個明顯的缺點就是不能直接解析中文資料:

如果我們想看到中文資料,可以使用eval函式:

6. Pandas處理 json

下面介紹pandas庫對json資料的處理:

  • read_json:從json檔案中讀取資料

  • to_json:將pandas中的資料寫入到json檔案中

  • json_normalize:對json資料進行規範化處理

https://geek-docs.com/pandas/pandas-read-write/pandas-reading-and-writing-json.html

6.1 read_json

首先看看官網中read_json的引數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pandas.read_json(
  path_or_buf=None,  # json檔案路徑
  orient=None,  # 重點引數,取值為:"split"、"records"、"index"、"columns"、"values"
  typ='frame',   # 要恢復的物件型別(系列或框架),預設』框架』.
  dtype=None, # boolean或dict,預設為True
  convert_axes=None,
  convert_dates=True,
  keep_default_dates=True,
  numpy=False,
  precise_float=False,
  date_unit=None,
  encoding=None,
  lines=False,  # 布林值,預設為False,每行讀取該檔案作為json物件
  chunksize=None,
  compression='infer',
  nrows=None,
  storage_options=None)

詳細的引數解析可以參考文章:https://blog.csdn.net/qq_41562377/article/details/90203805

假設我們現在有一份json資料,如下圖所示:

我們將上面的資料讀取進來,由於資料是比較規範的,所以直接填寫檔案路徑即可讀取:

重點講解下引數orient

1、oriden='split'

1
split』 : dict like {index -> [index], columns -> [columns], data -> [values]}

json檔案的key的名字只能為index,cloumns,data這三個,另外多一個key都不行,少一個也不行。舉例說明:

2、orient='records'

1
『records』 : list like [{column -> value}, … , {column -> value}]

3、orient='index'

1
dict like {index -> {column -> value}}

4、orient='columns'

1
dict like {column -> {index -> value}}

轉置之後就是上面orient='index'的結果

5、orient='values'

1
『values』 : just the values array

6.2 to_json

to_json方法就是將DataFrame檔案儲存成json檔案:

1
df.to_json("個人訊息.json")   # 直接儲存成json檔案

如果按照上面的程式碼儲存,中文是沒有顯示的:

當然我們可以透過json.load將json檔案再次讀取進行,顯示中文,我們也可以直接在儲存的時候顯示中文:

1
df.to_json("個人訊息1.json",force_ascii=False)   # 顯示中文

6.3 json_normalize

https://www.jianshu.com/p/a84772b994a0

上面介紹的json資料的儲存和讀取中json資料都是串列形式的;但是json檔案中的資料通常不一定全部是串列形式,那麼我們需要將字典結構的檔案轉成串列形式,這個過程就叫做規範化。

pandas中的json_normalize()函式能夠將字典或串列轉成表格,使用之前先進行匯入:

1
from pandas.io.json import json_normalize

透過官網和一個實際的範例來同時進行學習,首先看看官網的範例:

1、層級字典透過屬性的形式顯示資料:

2、如果加入max_level引數則會顯示不同的效果:

若max_level=0,則巢狀的字典會當做整體,顯示在資料框中

若max_level=1,則巢狀的字典會被拆解,裡面的鍵會被單獨出來:

3、讀取層級巢狀中的部分內容:

4、讀取全部內容

7. 總結一下

json資料是工作中經常會遇到的一種資料格式,也是很重要的一種資料。

本文首先對json資料及格式進行了簡介,重新認識json資料;其次,結合各種實際範例,將jsonPython的各種資料型態,尤其是字典型別進行了轉化;最後,重要講解了json資料的讀取、寫入和規範化的操作。

希望這篇文章的詳細講解,能夠幫助到各位搞定json資料~

近兩年里,我原創和翻譯了130+技術文章,主要關注Python進階、小技巧、程式設計設計、PEP翻譯、Python哲學等話題。現已集結出了一本電子書《優雅的Python》,請回復數值『1』,取得下載地址。

近期熱門文章推薦:

好的程式設計語言具備哪些屬性?

深入理解Python的TLS機制和Threading.local()

Python 為什麼用 # 號作註解符?

耗時兩年,我終於出了一本電子書!

Linux 日誌切割神器 Logrotate 原理和配置詳解(附多生產例項)

分享在看是對我最大的支援!