Json模塊主要用來進行Python對象的序列化和反序列化。
該模塊中經常使用的方法有如下四個:python
json.dump
將Python對象序列化爲Json格式的數據流並寫入文件類型的對象中json
json.dumps
將Python對象序列化爲Json格式的字符串數組
json.load
從文件類型的對象中讀取Json格式的數據並反序列化成Python對象ide
json.loads
將包含Json格式數據的字符串反序列化成Python對象函數
進行序列化時,Python類型與Json類型的轉換關係以下表所示:this
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
進行反序列化時,Json類型與Python類型的轉換關係以下:編碼
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number(int) | int |
number(real) | float |
true | True |
false | False |
null | None |
因爲 json.dump 和 json.dumps這兩個方法、的做用與使用方法相似,故只對其中之一詳細介紹。
一樣地,json.load 和 json.loads這兩個方法的做用與使用方法相似,故也只對其中之一詳細介紹。spa
該方法包含一個位置參數和多個僅限關鍵字參數,分別以下所示:.net
obj
要序列化的Python對象code
skipkeys=False
是否跳過要序列化的對象中字典元素的key不是基本類型的數據;
若是爲True,則跳過,若是爲False,將拋出TypeError異常。
>>> emp_info = {'name': 'bob', b'age': 24} # 包含key爲bytes類型的元素 >>> json.dumps(emp_info) # skipkeys參數爲默認值False Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) TypeError: keys must be str, int, float, bool or None, not bytes >>> json.dumps(emp_info, skipkeys=True) # skipkeys參數設置爲True時則可成功序列化 '{"name": "bob"}'
ensure_ascii=True
是否將要序列化的對象中的字符串中的非ascii字符進行轉義。
若是該參數爲True,則將字符串中的非ascii字符轉義成unicode字符串,不然,將不會進行轉義。
>>> message = '我愛Python3' >>> json.dumps(message) # ensure_ascii參數默認值爲True,將會把非ascii字符轉移成unicode字符串 '"\\u6211\\u7231Python3"' >>> json.dumps(message, ensure_ascii=False) # ensure_ascii參數設置爲False時,不會進行轉義 '"我愛Python3"'
check_circular=True
是否進行容器類型的循環引用檢查。
若是該參數設置爲False,則不進行檢查,可是可能會引起OverflowError或更嚴重的狀況。
若是該參數設置爲True,則將進行容器類型的循環引用檢查,並在發現循環引用時拋出異常。
emp_dict = {'id': 1, 'dept': 'sales'} >>> emp_dict['info'] = emp_dict # 字典中包含循環引用 >>> json.dumps(emp_dict) # 默認進行循環引用的檢查,將引起ValueError異常 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) ValueError: Circular reference detected >>> json.dumps(emp_dict, check_circular=False) # 設置爲不進行循環引用的檢查,可是在編碼Json對象時仍然引起了異常 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps **kw).encode(obj) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) RecursionError: maximum recursion depth exceeded while encoding a JSON object
allow_nan=True
是否容許序列化超出範圍的float類型的值(如float(‘inf’)、float(’-inf’)、float(‘nan’))。
若是該參數設置爲True,則上面列出的那些值將依次使用JavaScript中等價的值(Infinity、-Infinity、NaN)來進 行替代;
若是該參數設置爲False,而且要序列化的對象中出現了那些超出範圍的值,則將引起ValueError異常。
>>> num_list = [2, 5, float('inf'), float('-inf'), float('nan')] >>> json.dumps(num_list) # allow_nan的值默認爲True,列表中後三個值將被替換爲js中等價的值 '[2, 5, Infinity, -Infinity, NaN]' >>> json.dumps(num_list, allow_nan=False) # allow_nan設置爲False,引起ValueError異常 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps **kw).encode(obj) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) ValueError: Out of range float values are not JSON compliant
indent=None
是否在數組元素和對象成員前增長縮進以便使格式更加美觀。
若是該參數設置爲大於等於1的整數,則添加換行符和對應數量的空格表示縮進,若是設置爲0,則表示只添加換行符,若是設置爲None,則表示無縮進。
>>> response = {'status': 'success', 'code': 200, 'data': ['002', 'json', 5000]} >>> print(json.dumps(response)) # 默認值None,不縮進 {"status": "success", "code": 200, "data": ["002", "json", 5000]} >>> print(json.dumps(response, indent=0)) # 設置爲0,則只添加換行 { "status": "success", "code": 200, "data": [ "002", "json", 5000 ] } >>> print(json.dumps(response, indent=4)) # 設置爲4,添加換行和縮進 { "status": "success", "code": 200, "data": [ "002", "json", 5000 ] }
separators=None
設置Json中各項之間、對象的鍵和值之間的分隔符;
該參數必須是一個2元組,元組第一個元素表示Json數據中各項之間的分隔符,元組的第二個元素表示Json對象的鍵和值之間的分隔符。默認的分隔符爲(’,’, ‘:’)
>>> response = {'status': 'success', 'code': 200, 'data': ['002', 'json', 5000]} >>> print(json.dumps(response, separators=(';', '!'))) >>> print(json.dumps(response, indent = 4, separators=(';', '!'))) { "status"!"success"; "code"!200; "data"![ "002"; "json"; 5000 ] }
default=None
指定一個函數,用來將不可進行序列化的Python對象轉化爲可序列化的Python對象
>>> json.dumps(b'hello world') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type bytes is not JSON serializable >>> json.dumps(b'hello world', default=list) '[104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]' >>> json.dumps(b'hello world', default=str) '"b\'hello world\'"'
sort_keys=False
是否要將對象中字典元素按照key進行排序。
默認爲False,即不進行排序,若指定爲True,則會進行排序。
>>> emp_info = {'name': 'bob', 'age': 23, 'dept': 'sales', 'gender': 'male'} >>> print(json.dumps(emp_info, indent = 4)) # 不按照key排序 { "name": "bob", "age": 23, "dept": "sales", "gender": "male" } >>> print(json.dumps(emp_info, indent = 4, sort_keys=True)) # 按照key進行排序 { "age": 23, "dept": "sales", "gender": "male", "name": "bob" }
cls=None
指定一個定製的JSONEncoder的子類(例如,重寫了.default()方法用來序列化附加的類型),指定該參數時請使用cls關鍵字參數。若是未指定該參數,則將使用默認的JSONEncoder。
>>> class IteratorEncoder(json.encoder.JSONEncoder): ... def default(self, o): ... try: ... iterable = iter(o) ... except TypeError: ... pass ... else: ... return list(iterable) ... return super().default(self, o) ... >>> def get_nums(n): ... if not isinstance(n, int): ... raise TypeError('Expected int object') ... while n > 0: ... yield n ... n -= 1 ... >>> print(json.dumps(get_nums(10), indent=4, cls=IteratorEncoder)) [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
下面演示下該方法的簡單用法:
>>> response = {'status': 'success', 'code': 200, 'data': {'username': 'bob', 'user_level': 6, 'nickname': 'playboy'}} >>> with open('res.json', 'w', encoding='utf-8') as f: ... json.dump(response, f, indent=4) ... >>> os.system('cat res.json') { "status": "success", "code": 200, "data": { "username": "bob", "user_level": 6, "nickname": "playboy" } }0 >>>
該方法包含一個位置參數和多個僅限關鍵字參數,分別以下所示:
s
encoding=None
該參數已棄用,將會被忽略
cls=None
指定一個定製的JsonDecoder子類,以便實現特定的反序列化需求;
object_hook=None
接受一個可調用對象,用於處理解碼後生成的Python對象中dict類型的值。
注意,這個處理過程是遞歸進行的,即返回的Python對象內部全部的字典結構都將被這個方法處理
>>> emp_info = {'name': 'bob', 'age': 25, 'gender': 'Male'} >>> def obj_hook(_dict): ... return list(_dict.items()) ... >>> json.loads(json.dumps(emp_info)) {'name': 'bob', 'age': 25, 'gender': 'Male'} >>> json.loads(json.dumps(emp_info), object_hook=obj_hook) [('name', 'bob'), ('age', 25), ('gender', 'Male')] >>> emp_list = [25, emp_info] >>> emp_list [25, {'name': 'bob', 'age': 25, 'gender': 'Male'}] >>> json.loads(json.dumps(emp_list),object_hook=obj_hook) [25, [('name', 'bob'), ('age', 25), ('gender', 'Male')]] >>> emp_d = [25, {'name': 'bob', 'age': 25, 'gender': 'Male', 'emp_info': {'count': 9, 'total_salary': 120000}}] >>> json.loads(json.dumps(emp_d),object_hook=obj_hook) [25, [('name', 'bob'), ('age', 25), ('gender', 'Male'), ('emp_info', [('count', 9), ('total_salary', 120000)])]]
parse_float=None
用於處理解碼後的Python對象中的float類型的值。
>>> json.loads('[23.5, 43.32, 5.934]', parse_float=lambda x: int(x)) # 將解碼後的全部的float類型的值轉成int類型 [23, 43, 5] >>> json.loads('[23.5, 43.32, 5.934]', parse_float=lambda x: str(x)) # 將解碼後的全部的float類型的值轉成str類型 ['23.5', '43.32', '5.934']
parse_constant=None
接受一個可調用對象,用於解碼時對Infinity、-Infinity、NaN或其餘非法的Json數值的處理。
>>> def parse_cons(cons): ... if cons == 'Infinity': ... return 100000000 ... elif cons == '-Infinity': ... return -100000000 ... elif cons == 'NaN': ... return None ... else: ... raise Value(f"Can't convert this value {cons}") ... >>> json.loads('[Infinity, -Infinity, NaN]', parse_constant=parse_cons) [100000000, -100000000, None]
object_parse_hook=None
若是指定了該參數而且設置爲一個可調用對象,那麼Json對象將被解碼成一個元素爲二元組的列表,二元組的兩個元素分別爲Json對象中的鍵值對的鍵和值,而且列表中元素的順序與Json對象中鍵值對的順序一致。
>>> emp_info = {'name': 'bob', 'age': 23, 'dept': 'sales', 'gender': 'male'} >>> json.loads(json.dumps(emp_info), object_pairs_hook=str) "[('name', 'bob'), ('age', 23), ('dept', 'sales'), ('gender', 'male')]" >>> from collections import OrderedDict >>> json.loads(json.dumps(emp_info), object_pairs_hook=OrderedDict) OrderedDict([('name', 'bob'), ('age', 23), ('dept', 'sales'), ('gender', 'male')])
下面演示下該方法的簡單用法:
>>> with open('res.json', encoding='utf-8') as f: ... json.load(f) ... {'status': 'success', 'code': 200, 'data': {'username': 'bob', 'user_level': 6, 'nickname': 'playboy'}}