On this page
json — JSON 编码器和解码器
源代码: Lib/json/init.py
_7 由 RFC 7159(取代 RFC 4627)和ECMA-404指定,是一种轻量级的数据交换格式,受JavaScript对象 Literals 语法的启发(尽管它不是 JavaScript [1]的严格子集)。
json公开了标准库marshal和pickle模块的用户熟悉的 API。
编码基本的 Python 对象层次结构:
>>> import json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"foo\bar"
>>> print(json.dumps('\u1234'))
"\u1234"
>>> print(json.dumps('\\'))
"\\"
>>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
{"a": 0, "b": 0, "c": 0}
>>> from io import StringIO
>>> io = StringIO()
>>> json.dump(['streaming API'], io)
>>> io.getvalue()
'["streaming API"]'
Compact encoding:
>>> import json
>>> json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'
Pretty printing:
>>> import json
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
{
"4": 5,
"6": 7
}
Decoding JSON:
>>> import json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
'"foo\x08ar'
>>> from io import StringIO
>>> io = StringIO('["streaming API"]')
>>> json.load(io)
['streaming API']
专门研究 JSON 对象解码:
>>> 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')
Extending JSONEncoder:
>>> 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]'
>>> ComplexEncoder().encode(2 + 1j)
'[2.0, 1.0]'
>>> list(ComplexEncoder().iterencode(2 + 1j))
['[2.0', ', 1.0', ']']
从 Shell 使用json.tool进行验证并进行漂亮的打印:
$ echo '{"json":"obj"}' | python -m json.tool
{
"json": "obj"
}
$ echo '{1.2:3.4}' | python -m json.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
有关详细文档,请参见命令行界面。
Note
JSON 是YAML 1.2 的子集。该模块的默认设置(特别是默认的* separators *值)产生的 JSON 也是 YAML 1.0 和 1.1 的子集。因此,此模块也可以用作 YAML 序列化器。
Note
默认情况下,此模块的编码器和解码器保留 Importing 和输出 Sequences。仅当基础容器未排序时,订单才会丢失。
在 Python 3.7 之前,不能保证dict是有序的,因此除非特别要求collections.OrderedDict,否则通常会扰乱 Importing 和输出。从 Python 3.7 开始,常规dict成为保留 Sequences,因此不再需要为 JSON 生成和解析指定collections.OrderedDict。
Basic Usage
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 *)- 使用此conversion table将* obj 作为 JSON 格式的流序列化为 fp *(支持
.write()
的__)。
- 使用此conversion table将* obj 作为 JSON 格式的流序列化为 fp *(支持
如果* skipkeys *为 true(默认值:False
),则将跳过不是基本类型(str,int,float,bool,None
)的字典键,而不是引发TypeError。
json模块始终生成str个对象,而不是bytes个对象。因此,fp.write()
必须支持strImporting。
如果* ensure_ascii 为 true(默认值),则保证输出中所有传入的非 ASCII 字符都已转义。如果 ensure_ascii *为 false,则这些字符将原样输出。
如果* check_circular *为 false(默认值:True
),那么将跳过对容器类型的循环引用检查,而循环引用将导致OverflowError(或更糟)。
如果* allow_nan 为 false(默认值:True
),则严格遵循 JSON 规范,序列化范围float值(nan
,inf
,-inf
)之外的值将是ValueError。如果 allow_nan *为 true,则将使用它们的 JavaScript 等效项(NaN
,Infinity
,-Infinity
)。
如果* indent 是非负整数或字符串,则 JSON 数组元素和对象成员将使用该缩进级别进行漂亮打印。缩进级别 0,负数或""
只会插入换行符。 None
(默认设置)选择最紧凑的表示形式。使用正整数缩进会使每个级别缩进多个空格。如果 indent *是字符串(例如"\t"
),则该字符串用于缩进每个级别。
在 3.2 版中进行了更改:除整数外,还允许* indent *字符串。
如果指定,* separators 应该是(item_separator, key_separator)
Tuples。如果 indent *为None
,则默认值为(', ', ': ')
,否则为(',', ': ')
。为了获得最紧凑的 JSON 表示形式,您应该指定(',', ':')
以消除空格。
在版本 3.4 中更改:如果* indent *不是None
,则默认使用(',', ': ')
。
如果指定,则* default *应该是一个调用本来无法序列化的对象的函数。它应该返回该对象的 JSON 可编码版本或引发TypeError。如果未指定,则引发TypeError。
如果* sort_keys *为 true(默认值:False
),则字典的输出将按键排序。
要使用自定义的JSONEncoder子类(例如,覆盖default()
方法以序列化其他类型的子类),请使用* cls * kwarg 进行指定;否则使用JSONEncoder。
在版本 3.6 中更改:现在所有可选参数均为keyword-only。
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 *)- 使用conversion table将* obj *序列化为str格式的 JSON。参数与dump()中的含义相同。
Note
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 *)- 使用此conversion table将* fp *(支持
.read()
的text file或binary file包含 JSON 文档)反序列化为 Python 对象。
- 使用此conversion table将* fp *(支持
object_hook 是一个可选函数,它将被解码的任何对象常量(dict)的结果调用。将使用 object_hook *的返回值代替dict。此Function可用于实现自定义解码器(例如JSON-RPC类提示)。
object_pairs_hook 是一个可选函数,将使用对的有序列表解码的任何对象 Literals 的结果调用该函数。将使用 object_pairs_hook 的返回值代替dict。此Function可用于实现自定义解码器。如果还定义了 object_hook ,则 object_pairs_hook *优先。
在版本 3.1 中进行了更改:添加了对* object_pairs_hook *的支持。
parse_float *(如果指定)将与每个要解码的 JSON float 的字符串一起调用。默认情况下,它等效于
float(num_str)
。这可用于将其他数据类型或解析器用于 JSON 浮点数(例如decimal.Decimal)。parse_int *(如果指定)将与每个要解码的 JSON int 的字符串一起调用。默认情况下,它等效于
int(num_str)
。可以用于将其他数据类型或解析器用于 JSON 整数(例如float)。parse_constant *(如果已指定)将使用以下字符串之一调用:
'-Infinity'
,'Infinity'
,'NaN'
。如果遇到无效的 JSON 数字,则可以使用此方法引发异常。
在版本 3.1 中更改:* parse_constant *不再在'null','true','false'上调用。
要使用自定义的JSONDecoder子类,请使用cls
kwarg 指定它;否则使用JSONDecoder。其他关键字参数将传递给该类的构造函数。
如果要反序列化的数据不是有效的 JSON 文档,则将引发JSONDecodeError。
在版本 3.6 中更改:现在所有可选参数均为keyword-only。
在版本 3.6 中更改:* fp *现在可以是binary file。Importing 编码应为 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 *)- 使用此conversion table将* s *(包含 JSON 文档的str,bytes或bytearray实例)反序列化为 Python 对象。
其他自变量的含义与load()相同,只是* encoding *自 Python 3.1 起已被忽略和弃用。
如果要反序列化的数据不是有效的 JSON 文档,则将引发JSONDecodeError。
自 3.1 版起已弃用,将在 3.9 版中删除:* encoding *关键字参数。
在版本 3.6 中更改:* s *现在可以是bytes或bytearray类型。Importing 编码应为 UTF-8,UTF-16 或 UTF-32.
编码器和解码器
-
- class *
json.
JSONDecoder
(**, object_hook = None , parse_float = None , parse_int = None , parse_constant = None , strict = True , object_pairs_hook = None *)
- 简单的 JSON 解码器。
- class *
默认情况下在解码中执行以下转换:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
它还将NaN
,Infinity
和-Infinity
理解为它们对应的float
值,这在 JSON 规范之外。
object_hook *(如果指定)将被解码的每个 JSON 对象的结果调用,并且其返回值将代替给定的dict。这可用于提供自定义反序列化(例如,支持 JSON-RPC 类提示)。
object_pairs_hook ,如果指定的话,将以对每个有序列对的列表解码的 JSON 对象的结果进行调用。将使用 object_pairs_hook 的返回值代替dict。此Function可用于实现自定义解码器。如果还定义了 object_hook ,则 object_pairs_hook *优先。
在版本 3.1 中进行了更改:添加了对* object_pairs_hook *的支持。
parse_float *(如果指定)将与每个要解码的 JSON float 的字符串一起调用。默认情况下,它等效于
float(num_str)
。这可用于将其他数据类型或解析器用于 JSON 浮点数(例如decimal.Decimal)。parse_int *(如果指定)将与每个要解码的 JSON int 的字符串一起调用。默认情况下,它等效于
int(num_str)
。可以用于将其他数据类型或解析器用于 JSON 整数(例如float)。parse_constant *(如果已指定)将使用以下字符串之一调用:
'-Infinity'
,'Infinity'
,'NaN'
。如果遇到无效的 JSON 数字,则可以使用此方法引发异常。
如果* strict *为 false(默认值为True
),则在字符串中将允许使用控制字符。在这种情况下,控制字符是字符代码在 0-31 范围内的字符,包括'\t'
(制表符),'\n'
,'\r'
和'\0'
。
如果要反序列化的数据不是有效的 JSON 文档,则将引发JSONDecodeError。
在版本 3.6 中更改:现在所有参数均为keyword-only。
decode
(* s *)- 返回* s *(包含 JSON 文档的str实例)的 Python 表示形式。
如果给定的 JSON 文档无效,将引发JSONDecodeError。
raw_decode
(* s *)- 从* s (以 JSON 文档开头的str)中解码 JSON 文档,并返回 2Tuples 的 Python 表示形式和 s *中文档结束处的索引。
这可用于从结尾可能有无关数据的字符串中解码 JSON 文档。
-
- class *
json.
JSONEncoder
(**, skipkeys = False , ensure_ascii = True , check_circular = True , allow_nan = True , sort_keys = False , indent = None , separators = None , default = None *)
- 用于 Python 数据结构的可扩展 JSON 编码器。
- class *
默认情况下支持以下对象和类型:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int,float,int 和 float 枚举 | number |
True | true |
False | false |
None | null |
在版本 3.4 中进行了更改:增加了对从 int 和 float 派生的 Enum 类的支持。
为了将其扩展为识别其他对象,请子类化并实现default()方法,并使用另一个方法(如果可能的话)为o
返回可序列化的对象,否则应调用超类实现(引发TypeError)。
如果* skipkeys 为 false(默认值),则try对不是str,int,float或None
的键进行编码是TypeError。如果 skipkeys *为 true,则仅跳过此类项目。
如果* ensure_ascii 为 true(默认值),则保证输出中所有传入的非 ASCII 字符都已转义。如果 ensure_ascii *为 false,则这些字符将原样输出。
如果* check_circular *为 true(默认设置),则在编码过程中将检查列表,字典和自定义编码对象的循环引用,以防止无限递归(这将导致OverflowError)。否则,将不会进行此类检查。
如果* allow_nan *为 true(默认设置),则NaN
,Infinity
和-Infinity
将会被编码为此类。此行为不符合 JSON 规范,但与大多数基于 JavaScript 的编码器和解码器一致。否则,对此类浮点数进行编码将是ValueError。
如果* sort_keys *为 true(默认值:False
),则字典的输出将按 key 排序;这对于进行回归测试以确保可以每天比较 JSON 序列化很有用。
如果* indent 是非负整数或字符串,则 JSON 数组元素和对象成员将使用该缩进级别进行漂亮打印。缩进级别 0,负数或""
只会插入换行符。 None
(默认设置)选择最紧凑的表示形式。使用正整数缩进会使每个级别缩进多个空格。如果 indent *是字符串(例如"\t"
),则该字符串用于缩进每个级别。
在 3.2 版中进行了更改:除整数外,还允许* indent *字符串。
如果指定,* separators 应该是(item_separator, key_separator)
Tuples。如果 indent *为None
,则默认值为(', ', ': ')
,否则为(',', ': ')
。为了获得最紧凑的 JSON 表示形式,您应该指定(',', ':')
以消除空格。
在版本 3.4 中更改:如果* indent *不是None
,则默认使用(',', ': ')
。
如果指定,则* default *应该是一个调用本来无法序列化的对象的函数。它应该返回该对象的 JSON 可编码版本或引发TypeError。如果未指定,则引发TypeError。
在版本 3.6 中更改:现在所有参数均为keyword-only。
default
(* o *)- 在子类中实现此方法,使其返回* o *的可序列化对象,或调用基本实现(引发TypeError)。
例如,要支持任意迭代器,可以实现如下所示的默认值:
def default(self, o):
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, o)
encode
(* o *)- 返回 Python 数据结构* o *的 JSON 字符串表示形式。例如:
>>> json.JSONEncoder().encode({"foo": ["bar", "baz"]})
'{"foo": ["bar", "baz"]}'
iterencode
(* o *)- 编码给定的对象* o *,并产生每个可用的字符串表示形式。例如:
for chunk in json.JSONEncoder().iterencode(bigobject):
mysocket.write(chunk)
Exceptions
-
- exception *
json.
JSONDecodeError
(* msg , doc , pos *)
- ValueError的子类,具有以下附加属性:
- exception *
msg
- 未格式化的错误消息。
doc
- 正在解析的 JSON 文档。
pos
- 解析失败的* doc *的起始索引。
lineno
- 与* pos *对应的行。
colno
- 对应于* pos *的列。
3.5 版中的新Function。
标准符合性和互操作性
JSON 格式由 RFC 7159和ECMA-404指定。本节详细介绍了此模块与 RFC 的符合性级别。为简单起见,不考虑JSONEncoder和JSONDecoder子类以及未明确提及的参数。
该模块不严格遵循 RFC,而是实现了一些扩展,这些扩展是有效的 JavaScript,但不是有效的 JSON。特别是:
无限和 NaN 数值被接受并输出;
接受对象中的重复名称,并且仅使用姓氏/值对的值。
由于 RFC 允许符合 RFC 的解析器接受不符合 RFC 的 Importing 文本,因此该模块的反序列化器在默认设置下在技术上符合 RFC。
Character Encodings
RFC 要求使用 UTF-8,UTF-16 或 UTF-32 表示 JSON,建议使用 UTF-8 作为默认值,以实现最大的互操作性。
在 RFC 允许(尽管不是必需的)下,此模块的序列化程序默认情况下设置* ensure_ascii = True *,从而转义输出,以便结果字符串仅包含 ASCII 字符。
除了* ensure_ascii *参数之外,此模块严格根据 Python 对象和Unicode strings之间的转换定义,因此无法直接解决字符编码问题。
RFC 禁止在 JSON 文本的开头添加字节 Sequences 标记(BOM),并且此模块的序列化程序不会在其输出中添加 BOM。 RFC 允许但不要求 JSON 解串器忽略其 Importing 中的初始 BOM。存在初始 BOM 表时,此模块的反序列化器将引发ValueError。
RFC 并未明确禁止 JSON 字符串包含不与有效 Unicode 字符相对应的字节序列(例如,未配对的 UTF-16 替代),但它确实指出它们可能会导致互操作性问题。默认情况下,此模块接受并输出此类序列的代码点(如果存在于原始str中)。
无限和 NaN 数字值
RFC 不允许表示无限或 NaN 数字值。尽管如此,默认情况下,此模块仍接受并输出Infinity
,-Infinity
和NaN
,就像它们是有效的 JSON 数字 Literals 值一样:
>>> # Neither of these calls raises an exception, but the results are not valid JSON
>>> json.dumps(float('-inf'))
'-Infinity'
>>> json.dumps(float('nan'))
'NaN'
>>> # Same when deserializing
>>> json.loads('-Infinity')
-inf
>>> json.loads('NaN')
nan
在序列化程序中,* allow_nan 参数可用于更改此行为。在解串器中, parse_constant *参数可用于更改此行为。
对象中的重复名称
RFC 规定 JSON 对象中的名称应唯一,但不规定如何处理 JSON 对象中的重复名称。默认情况下,此模块不会引发异常;相反,它会忽略给定名称的除姓/值对之外的所有对:
>>> weird_json = '{"x": 1, "x": 2, "x": 3}'
>>> json.loads(weird_json)
{'x': 3}
- object_pairs_hook *参数可用于更改此行为。
顶级非对象,非数组值
过时的 RFC 4627指定的旧版 JSON 要求 JSON 文本的顶级值必须是 JSON 对象或数组(Python dict或list),并且不能为 JSON 空,布尔值,数字或字符串值。 RFC 7159删除了该限制,并且该模块没有并且从未在其序列化器或反序列化器中实现该限制。
无论如何,为了获得最大的互操作性,您可能希望自己自愿遵守该限制。
Implementation Limitations
某些 JSON 反序列化器实现可能会在以下方面设置限制:
可接受的 JSON 文本的大小
JSON 对象和数组的最大嵌套级别
JSON 数字的范围和精度
JSON 字符串的内容和最大长度
除了相关的 Python 数据类型本身或 Python 解释器本身的限制外,此模块没有施加任何此类限制。
序列化为 JSON 时,请注意可能会占用 JSON 的应用程序中的任何此类限制。特别是,通常将 JSON 数字反序列化为 IEEE 754 双精度数字,并因此受到该表示形式的范围和精度限制。当序列化非常大的 Python int值或序列化“外来”数字类型(例如decimal.Decimal)的实例时,这一点尤其重要。
命令行界面
源代码: Lib/json/tool.py
json.tool模块提供了一个简单的命令行界面来验证和打印 JSON 对象。
如果未指定可选的infile
和outfile
参数,则将分别使用sys.stdin和sys.stdout:
$ echo '{"json": "obj"}' | python -m json.tool
{
"json": "obj"
}
$ echo '{1.2:3.4}' | python -m json.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
在版本 3.5 中更改:输出现在与 Importing 的 Sequences 相同。使用--sort-keys选项可以按字母 Sequences 对字典的输出进行排序。
命令行选项
infile
``- 要验证或打印精美的 JSON 文件:
$ python -m json.tool mp_films.json
[
{
"title": "And Now for Something Completely Different",
"year": 1971
},
{
"title": "Monty Python and the Holy Grail",
"year": 1975
}
]
如果未指定* infile *,请从sys.stdin读取。
outfile
``- 将* infile 的输出写入给定的 outfile *中。否则,将其写入sys.stdout。
--sort-keys
``- 按字母 Sequences 对字典的输出进行排序。
3.5 版中的新Function。
--json-lines
``- 将每个 Importing 行解析为单独的 JSON 对象。
3.8 版的新Function。
-h
`,` `--help`
- 显示帮助信息。
Footnotes
- [1]
- 如RFC 7159 的勘误表中所述,JSON 允许字符串中的原义 U 2028(LINE SEPARATOR)和 U 2029(PARAGRAPH SEPARATOR)字符,而 JavaScript(自 ECMAScript Edition 5.1 起)不允许。