Python中JSON的基本使用

JSON (JavaScript Object Notation) 是一種輕量級的數據交換格式。Python3 中可以使用 json 模塊來對 JSON 數據進行編解碼,它主要提供了四個方法: dumpsdumploadsload

dump和dumps

dumpdumpspython對象進行序列化。將一個Python對象進行JSON格式的編碼。

dump函數:

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

obj: 表示是要序列化的對象。

fp: 文件描述符,將序列化的str保存到文件中。json模塊總是生成str對象,而不是字節對象;因此,fp.write()必須支持str輸入。

skipkeys: 默認爲False,如果skipkeysTrue,(默認值:False),則將跳過不是基本類型(str,int,float,bool,None)的dict鍵,不會引發TypeError

ensure_ascii: 默認值爲True,能將所有傳入的非ASCII字符轉義輸出。如果ensure_asciiFalse,則這些字符將按原樣輸出。

check_circular:默認值爲True,如果check_circularFalse,則將跳過對容器類型的循環引用檢查,循環引用將導致OverflowError

allow_nan: 默認值爲True,如果allow_nanFalse,則嚴格遵守JSON規範,序列化超出範圍的浮點值(nan,inf,-inf)會引發ValueError。 如果allow_nanTrue,則將使用它們的JavaScript等效項(NaN,Infinity,-Infinity)。

indent: 設置縮進格式,默認值爲None,選擇的是最緊湊的表示。如果indent是非負整數或字符串,那麼JSON數組元素和對象成員將使用該縮進級別進行輸入;indent爲0,負數或“”僅插入換行符;indent使用正整數縮進多個空格;如果indent是一個字符串(例如“\t”),則該字符串用於縮進每個級別。

separators: 去除分隔符後面的空格,默認值爲None,如果指定,則分隔符應爲(item_separator,key_separator)元組。如果縮進爲None,則默認爲(’,’,’:’);要獲得最緊湊的JSON表示,可以指定(’,’,’:’)以消除空格。

default: 默認值爲None,如果指定,則default應該是爲無法以其他方式序列化的對象調用的函數。它應返回對象的JSON可編碼版本或引發TypeError。如果未指定,則引發TypeError

sort_keys: 默認值爲False,如果sort_keysTrue,則字典的輸出將按鍵值排序。

dumps函數:

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

dumps函數不需要傳文件描述符,其他的參數和dump函數的一樣。

load和loads

loadloads反序列化方法,將json格式數據解碼爲python對象。

load函數:

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

fp: 文件描述符,將fp(.read()支持包含JSON文檔的文本文件或二進制文件)反序列化爲Python對象。

object_hook: 默認值爲None,object_hook是一個可選函數,此功能可用於實現自定義解碼器。指定一個函數,該函數負責把反序列化後的基本類型對象轉換成自定義類型的對象。

parse_float: 默認值爲None,如果指定了parse_float,用來對JSON float字符串進行解碼,這可用於爲JSON浮點數使用另一種數據類型或解析器。

parse_int: 默認值爲None,如果指定了parse_int,用來對JSON int字符串進行解碼,這可以用於爲JSON整數使用另一種數據類型或解析器。

parse_constant:默認值爲None,如果指定了parse_constant,對-Infinity,Infinity,NaN字符串進行調用。如果遇到了無效的JSON符號,會引發異常。

如果進行反序列化(解碼)的數據不是一個有效的JSON文檔,將會引發 JSONDecodeError異常。

loads函數:

json.loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

s: 將s(包含JSON文檔的str,bytes或bytearray實例)反序列化爲Python對象。
encoding: 指定一個編碼的格式。
loads也不需要文件描述符,其他參數的含義和load函數的一致。

格式轉化表

JSON中的數據格式和Python中的數據格式轉化關係如下:

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

實例:

dump和dumps

import json

# dumps可以格式化所有的基本數據類型爲字符串
data1 = json.dumps([])         # 列表
print(data1, type(data1))
data2 = json.dumps(2)          # 數字
print(data2, type(data2))
data3 = json.dumps('3')        # 字符串
print(data3, type(data3))
dict = {"name": "Tom", "age": 23}   # 字典
data4 = json.dumps(dict)
print(data4, type(data4))

with open("test.json", "w", encoding='utf-8') as f:
    # indent 超級好用,格式化保存字典,默認爲None,小於0爲零個空格
    f.write(json.dumps(dict, indent=4))
    json.dump(dict, f, indent=4)  # 傳入文件描述符,和dumps一樣的結果

得到的輸出結果如下:格式化所有的數據類型爲str類型

[] <class 'str'>
2 <class 'str'>
"3" <class 'str'>
{"name": "Tom", "age": 23} <class 'str'>

test.json中的內容

{
    "name": "Tom",
    "age": 23
}

load和loads

import json

dict = '{"name": "Tom", "age": 23}'   # 將字符串還原爲dict
data1 = json.loads(dict)
print(data1, type(data1))

with open("test.json", "r", encoding='utf-8') as f:
    data2 = json.loads(f.read())    # load的傳入參數爲字符串類型
    print(data2, type(data2))
    f.seek(0)                       # 將文件遊標移動到文件開頭位置
    data3 = json.load(f)
    print(data3, type(data3))

運行結果如下:

{'name': 'Tom', 'age': 23} <class 'dict'>
{'name': 'Tom', 'age': 23} <class 'dict'>
{'name': 'Tom', 'age': 23} <class 'dict'>

常見的錯誤:

讀取多行的JSON文件

假如要讀取一個多行的JSON文件:

{"": ["阪5742"]}
{"": ["構6784"]}
{"": ["共5171"]}
{"": ["鉤94a9"]}
{"": ["骯80ae"]}
{"": ["孤5b64"]}

如果直接使用:

    with open(json_path, 'r') as f:
        json_data = json.load(f)

就會報錯:拋出異常JSONDecodeError

json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 17)

表示數據錯誤,數據太多,第2行第一列
因爲json只能讀取一個文檔對象,有兩個解決辦法
1、單行讀取文件,一次讀取一行文件。
2、保存數據源的時候,格式寫爲一個對象。

單行讀取文件:

    with open(json_path, 'r') as f:
        for line in f.readlines():
            json_data = json.loads(line)

但是這種做法還有個問題,如果JSON文件中包含空行,還是會拋出JSONDecodeError異常

json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

可以先處理空行,再進行文件讀取操作:

 for line in f.readlines():
        line = line.strip()   # 使用strip函數去除空行
        if len(line) != 0:
            json_data = json.loads(line)

合併爲一個對象

json文件處理成一個對象文件。

{"dict": [
{"": ["阪5742"]},
{"": ["構6784"]},
{"": ["共5171"]},
{"": ["鉤94a9"]},
{"": ["骯80ae"]},
{"": ["孤5b64"]}
]}

然後再用:

    with open(json_path, 'r') as f:
        json_data = json.loads(f.read())

總結:

json.dumps 將 Python 對象編碼成 JSON 字符串
json.loads 將已編碼的 JSON 字符串解碼爲 Python 對象
json.dumpjson.load,需要傳入文件描述符,加上文件操作。
JSON內部的格式要注意,一個好的格式能夠方便讀取,可以用indent格式化。

參考鏈接:

https://docs.python.org/3.6/library/json.html#py-to-json-table
https://www.cnblogs.com/tjuyuan/p/6795860.html
http://liuzhijun.iteye.com/blog/1859857
https://blog.csdn.net/qq_22073849/article/details/78192289
http://www.runoob.com/python3/python3-json.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章