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'}}