Python中JSON的基本使用
JSON (JavaScript Object Notation) 是一種輕量級的資料交換格式。Python3 中可以使用 json 模組來對 JSON 資料進行編解碼,它主要提供了四個方法: dumps
、dump
、loads
、load
。
dump和dumps
dump
和dumps
對python
物件進行序列化。將一個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_ascii
False
,則這些字元將按原樣輸出。
check_circular
:預設值為True
,如果check_circular
為False
,則將跳過對容器型別的迴圈引用檢查,迴圈引用將導致OverflowError
。
allow_nan
: 預設值為True
,如果allow_nan
為False
,則嚴格遵守JSON規範,序列化超出範圍的浮點值(nan,inf,-inf)會引發ValueError
。 如果allow_nan
為True
,則將使用它們的JavaScript
等效項(NaN,Infinity,-Infinity)。
indent
: 設定縮排格式,預設值為None
,選擇的是最緊湊的表示。如果indent
indent
為0,負數或“”僅插入換行符;indent
使用正整數縮排多個空格;如果indent
是一個字串(例如“\t”),則該字串用於縮排每個級別。
separators
: 去除分隔符後面的空格,預設值為None
,如果指定,則分隔符應為(item_separator,key_separator)元組。如果縮排為None
,則預設為(’,’,’:’);要獲得最緊湊的JSON表示,可以指定(’,’,’:’)以消除空格。
default
: 預設值為None
,如果指定,則default
應該是為無法以其他方式序列化的物件呼叫的函式。它應返回物件的JSON可編碼版本或引發TypeError
。如果未指定,則引發TypeError
。
sort_keys
: 預設值為False
,如果sort_keys
為True
,則字典的輸出將按鍵值排序。
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
load
和loads
反序列化方法,將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.dump
和json.load
,需要傳入檔案描述符,加上檔案操作。
JSON
內部的格式要注意,一個好的格式能夠方便讀取,可以用indent
格式化。