Python Json模块完全总结
Posted 嵌入式软件实战派
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Json模块完全总结相关的知识,希望对你有一定的参考价值。
前言
JSON (JavaScript Object Notation),由 RFC 7159 (which obsoletes RFC 4627) 和 ECMA-404 指定,是一个受 JavaScript 的对象字面量语法启发的轻量级数据交换格式。
在Python中,常用的JSON模块相关API就4个:load
、loads
、dump
、dumps
其中,使用load
或loads
时,相当于将下表内容反序列化成Python数据类型。
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
而使用dump
或dumps
时,相当于将下表内容序列化成JSON数据类型。
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int 和 float等 | number |
True | true |
False | false |
None | null |
以下通过几个简单案例来理解这几个API的功能和用法。
load和loads
load
就是从文件load一个json格式的内容,然后转换成Python类型的内容,用法很简单
with open('test.json', 'r') as f:
js = json.load(f)
print(type(js))
print(js)
输出:
<class 'dict'>
{'LiLei': [98, 80, 88], 'HanMeiMei': [100, 90, 80]}
loads
干嘛的呢?
d1 = '{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}'
js1 = json.loads(d1)
print(type(js1))
print(js1)
输出:
<class 'dict'>
{'LiLei': [98, 80, 88], 'HanMeiMei': [100, 90, 80]}
从上面两个例子可以看出load
和loads
的区别,即load
针对的是文件处理,而loads
的针对的是字符串的处理。实际上,除了字符串,load
还支持StringIO类型,loads
还支持对bytes
和bytearray
。
from io import StringIO
io = StringIO('["streaming API"]')
json.load(io)
d1 = b'{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}'
js1 = json.loads(d1)
其实这两个函数的区别,可以参考其参数(详见最后一小节的函数描述)
另外,有个奇怪的现象,看下面例子
d1 = "{'LiLei': [98, 80, 88], 'HanMeiMei': [100, 90, 80]}"
js1 = json.loads(d1)
print(type(js1))
print(js1)
提示错误
JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
可以理解为:只能单引号包含双引号('"abc"123'
),而双引号包含单引号("'ABC'123"
)就不认了。
除此之外,还可以识别特殊对象,例如复数。
import json
def as_complex(dct):
if '__complex__' in dct:
return complex(dct['real'], dct['imag'])
return dct
json.loads('{"__complex__": true, "real": 1, "imag": 2}', object_hook=as_complex) # (1+2j)
import decimal
json.loads('1.1', parse_float=decimal.Decimal) # Decimal('1.1')
dump和dumps
dump
和dumps
跟load``loads
是相对应的,直接看例子
with open('test2.json', 'w') as f:
js = json.dump({"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]},f)
输出的文件内容为:
{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}
dump
函数有几个参数,separators和indent
with open('test2.json', 'w') as f:
js = json.dump({"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]},f, separators=(',', ':'),indent = 4)
{
"LiLei": [
98,
80,
88
],
"HanMeiMei": [
100,
90,
80
]
}
实际上这个separators参数默认是separators=(',', ':')
,不管它也是可以的。
同样地,dumps
函数时针对具体的Python类型内容,而不是文件
d6 = {"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}
js6 = json.dumps(d6)
print(type(js6))
print(js6)
<class 'str'>
{"LiLei": [98, 80, 88], "HanMeiMei": [100, 90, 80]}
对于特殊JSON对象
import json
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, complex):
return [obj.real, obj.imag]
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, obj)
json.dumps(2 + 1j, cls=ComplexEncoder) # '[2.0, 1.0]'
其他更详细的参数使用,请见下面章节
函数参数说明
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 序列化为 JSON 格式化流形式的 fp (支持
.write()
的 file-like object)。如果 skipkeys 是 true (默认为
False
),那么那些不是基本对象(包括str
,int
、float
、bool
、None
)的字典的键会被跳过;否则引发一个TypeError
。
json
模块始终产生str
对象而非bytes
对象。因此,fp.write()
必须支持str
输入。如果 ensure_ascii 是 true (即默认值),输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false,这些字符会原样输出。如果 check_circular 是为假值 (默认为
True
),那么容器类型的循环引用检验会被跳过并且循环引用会引发一个OverflowError
(或者更糟的情况)。如果 allow_nan 是 false(默认为
True
),那么在对严格 JSON 规格范围外的float
类型值(nan
、inf
和-inf
)进行序列化时会引发一个ValueError
。如果 allow_nan 是 true,则使用它们的 javascript 等价形式(
NaN
、Infinity
和-Infinity
)。如果 indent 是一个非负整数或者字符串,那么 JSON 数组元素和对象成员会被美化输出为该值指定的缩进等级。 如果缩进等级为零、负数或者
""
,则只会添加换行符。None
(默认值) 选择最紧凑的表达。 使用一个正整数会让每一层缩进同样数量的空格。 如果 indent 是一个字符串 (比如"\\t"
),那个字符串会被用于缩进每一层。在 3.2 版更改: 允许使用字符串作为 indent 而不再仅仅是整数。
当指定时,separators 应当是一个
(item_separator, key_separator)
元组。当 indent 为None
时,默认值取(', ', ': ')
,否则取(',', ': ')
。为了得到最紧凑的 JSON 表达式,你应该指定其为(',', ':')
以消除空白字符。在 3.4 版更改: 现当 indent 不是
None
时,采用(',', ': ')
作为默认值。当 default 被指定时,其应该是一个函数,每当某个对象无法被序列化时它会被调用。它应该返回该对象的一个可以被 JSON 编码的版本或者引发一个
TypeError
。如果没有被指定,则会直接引发TypeError
。如果 sort_keys 是 true(默认为
False
),那么字典的输出会以键的顺序排序。为了使用一个自定义的
JSONEncoder
子类(比如:覆盖了default()
方法来序列化额外的类型), 通过 cls 关键字参数来指定;否则将使用JSONEncoder
。在 3.6 版更改: 所有的可选参数现在是 keyword-only 的了。
注解: 与
pickle
和marshal
不同,JSON 不是一个具有框架的协议,所以尝试多次使用同一个 fp 调用dump()
来序列化多个对象会产生一个不合规的 JSON 文件。
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*)
使用这个 转换表 将 obj 序列化为 JSON 格式的
str
。 其参数的含义与dump()
中的相同。注解: JSON 中的键-值对中的键永远是
str
类型的。当一个对象被转化为 JSON 时,字典中所有的键都会被强制转换为字符串。这所造成的结果是字典被转换为 JSON 然后转换回字典时可能和原来的不相等。换句话说,如果 x 具有非字符串的键,则有loads(dumps(x)) != x
。
json.load(*fp*, ***,
*cls=None*,
*object_hook=None*,
*parse_float=None*,
*parse_int=None*,
*parse_constant=None*,
*object_pairs_hook=None*, ***kw*)
使用这个 转换表将 fp (一个支持
.read()
并包含一个 JSON 文档的 text file 或者 binary file) 反序列化为一个 Python 对象。object_hook 是一个可选的函数,它会被调用于每一个解码出的对象字面量(即一个
dict
)。object_hook 的返回值会取代原本的dict
。这一特性能够被用于实现自定义解码器(如 JSON-RPC 的类型提示)。object_pairs_hook 是一个可选的函数,它会被调用于每一个有序列表对解码出的对象字面量。 object_pairs_hook 的返回值将会取代原本的
dict
。这一特性能够被用于实现自定义解码器。如果 object_hook 也被定义, object_pairs_hook 优先。在 3.1 版更改: 添加了对 object_pairs_hook 的支持。
parse_float ,如果指定,将与每个要解码 JSON 浮点数的字符串一同调用。默认状态下,相当于
float(num_str)
。可以用于对 JSON 浮点数使用其它数据类型和语法分析程序 (比如decimal.Decimal
)。parse_int ,如果指定,将与每个要解码 JSON 整数的字符串一同调用。默认状态下,相当于
int(num_str)
。可以用于对 JSON 整数使用其它数据类型和语法分析程序 (比如float
)。parse_constant ,如果指定,将要与以下字符串中的一个一同调用:
'-Infinity'
,'Infinity'
,'NaN'
。如果遇到无效的 JSON 数字则可以使用它引发异常。在 3.1 版更改: parse_constant 不再调用 ‘null’ , ‘true’ , ‘false’ 。
要使用自定义的
JSONDecoder
子类,用cls
指定他;否则使用JSONDecoder
。额外的关键词参数会通过类的构造函数传递。如果反序列化的数据不是有效 JSON 文档,引发
JSONDecodeError
错误。在 3.6 版更改: 所有的可选参数现在是 keyword-only 的了。
在 3.6 版更改: fp 现在可以是 binary file 。输入编码应当是 UTF-8 , UTF-16 或者 UTF-32 。
json.loads(*s*, ***,
*cls=None*,
*object_hook=None*,
*parse_float=None*,
*parse_int=None*,
*parse_constant=None*,
*object_pairs_hook=None*, ***kw*)
使用这个 转换表将 s (一个包含 JSON 文档的
str
,bytes
或bytearray
实例) 反序列化为 Python 对象。其他参数的含义与
load()
中的相同。如果反序列化的数据不是有效 JSON 文档,引发
JSONDecodeError
错误。在 3.6 版更改: s 现在可以为
bytes
或bytearray
类型。 输入编码应为 UTF-8, UTF-16 或 UTF-32。在 3.9 版更改: 关键字参数 encoding 已被移除。
以上是关于Python Json模块完全总结的主要内容,如果未能解决你的问题,请参考以下文章