json ——JSON编码器和解码器

源代码: Lib/json/__init__.py


JSON (JavaScript Object Notation), specified by RFC 7159 (which obsoletes RFC 4627) and by ECMA-404, is a lightweight data interchange format inspired by JavaScript 对象文本语法(尽管它不是JavaScript的严格子集 1

json 向标准库的用户公开熟悉的API marshalpickle 模块。

编码基本的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"]'

压缩编码:

>>> import json
>>> json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'

精美印刷:

>>> import json
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
{
    "4": 5,
    "6": 7
}

解码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')

延伸 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', ']']

使用 json.tool 从shell到validate和pretty print:

$ 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)

命令行界面 有关详细文档。

注解

JSON是 YAML 1.2.此模块的默认设置(特别是默认设置)生成的JSON 分离器 值)也是yaml 1.0和1.1的子集。因此,该模块也可以用作yaml序列化程序。

注解

该模块的编码器和解码器在默认情况下保持输入和输出顺序。只有底层容器无序时,订单才会丢失。

在python 3.7之前, dict 不能保证是有序的,所以输入和输出通常被置乱,除非 collections.OrderedDict 是特别要求的。从Python3.7开始 dict 变成了保序,所以不再需要指定 collections.OrderedDict 用于JSON生成和解析。

基本用法

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 (A) .write() 支持 file-like object )使用此 conversion table .

如果 滑雪板 为真(默认: False ,然后是非基本类型的dict键 (strintfloatboolNone )将跳过而不是引发 TypeError .

这个 json 模块总是产生 str 对象,而不是 bytes 物体。因此, fp.write() 必须支持 str 输入。

如果 ensure_ascii 为真(默认值),输出保证对所有传入的非ASCII字符进行转义。如果 ensure_ascii 为假,这些字符将按原样输出。

如果 check_circular 为假(默认: True ,则跳过容器类型的循环引用检查,循环引用将导致 OverflowError (或更糟)。

如果 allow_nan 为假(默认: True ,那么它将是一个 ValueError 序列化超出范围 float 价值观 (naninf-inf )严格遵守JSON规范。如果 allow_nan 是真的,它们的javascript等价物 (NaNInfinity-Infinity )将被使用。

如果 缩进 是非负整数或字符串,则JSON数组元素和对象成员将以该缩进级别进行打印。0、负数或 "" 只插入换行符。 None (默认)选择最紧凑的表示。使用正整数,每级缩进多少空格。如果 缩进 是字符串(例如 "\t" ,该字符串用于缩进每个级别。

在 3.2 版更改: 允许字符串用于 缩进 除了整数。

如果有规定, 分离器 应该是一个 (item_separator, key_separator) 元组。默认值为 (', ', ': ') 如果 缩进None(',', ': ') 否则。要获得最紧凑的JSON表示,应该指定 (',', ':') 以消除空白。

在 3.4 版更改: 使用 (',', ': ') 默认为 缩进 不是 None .

如果有规定, default 应该是为无法序列化的对象调用的函数。它应该返回对象的JSON可编码版本或引发 TypeError . 如果未指定, TypeError 提高了。

如果 sort_keys 为真(默认: False ,则字典的输出将按键排序。

使用习惯 JSONEncoder 子类(例如覆盖 default() 方法来序列化其他类型),使用 cls Kwarg;否则 JSONEncoder 使用。

在 3.6 版更改: 所有可选参数现在都是 keyword-only .

注解

不像 picklemarshal ,json不是框架协议,因此尝试通过重复调用序列化多个对象 dump() 使用相同的 fp 将导致无效的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 使用此 conversion table . 这些参数的含义与 dump() .

注解

JSON的键/值对中的键总是属于 str . 当字典转换为JSON时,字典的所有键都被强制为字符串。因此,如果将字典转换为JSON,然后再转换回字典,则字典可能不等于原始字典。也就是说, loads(dumps(x)) != 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 (A) .read() 支持 text filebinary file 包含JSON文档)到使用此 conversion table .

object_hook 是一个可选函数,将使用任何对象文本解码的结果调用(a 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的字符串调用。默认情况下,这相当于 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 . 输入编码应该是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 (A) strbytesbytearray 包含JSON文档的实例)到使用此 conversion table .

其他论点的含义与 load() .

如果要反序列化的数据不是有效的JSON文档,则 JSONDecodeError 将被引发。

在 3.6 版更改: s 现在可以是类型 bytesbytearray . 输入编码应该是utf-8、utf-16或utf-32。

在 3.9 版更改: 关键字参数 编码 已删除。

编码器和解码器

class json.JSONDecoder(*, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None)

简单的JSON解码器。

默认情况下,在解码时执行以下转换:

JSON

Python

对象

双关语

数组

列表

string

STR

数字(int)

int

数字(实数)

浮动

无效的

没有

它也理解 NaNInfinity-Infinity 作为他们的对应 float 值,超出了JSON规范。

object_hook 如果指定,将调用每个已解码的JSON对象的结果,并使用其返回值代替给定的 dict . 这可用于提供自定义反序列化(例如,支持JSON-RPC类提示)。

object_pairs_hook 如果指定,则将调用每个JSON对象的结果,并用一个有序的成对列表对其进行解码。的返回值 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的字符串调用。默认情况下,这相当于 int(num_str) . 这可用于对JSON整数使用另一个数据类型或解析器(例如 float

parse_constant 如果指定,将使用以下字符串之一调用: '-Infinity''Infinity''NaN' . 如果遇到无效的JSON编号,可以使用此方法引发异常。

如果 strict 是假的 (True 是默认值),则在字符串中允许使用控制字符。此上下文中的控制字符是那些字符代码在0-31范围内的字符,包括 '\t' (选项卡) '\n''\r''\0' .

如果要反序列化的数据不是有效的JSON文档,则 JSONDecodeError 将被引发。

在 3.6 版更改: 所有参数现在都是 keyword-only .

decode(s)

返回的python表示形式 s (A) str 包含JSON文档的实例)。

JSONDecodeError 如果给定的JSON文档无效,将引发。

raw_decode(s)

从解码JSON文档 s (A) str 从JSON文档开始),并返回2元组的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编码器。

默认情况下支持以下对象和类型:

Python

JSON

双关语

对象

列表,元组

数组

STR

string

int、float、int和float派生枚举

没有

无效的

在 3.4 版更改: 添加了对int和float派生枚举类的支持。

要扩展它以识别其他对象,请子类并实现 default() 方法的另一个方法返回的可序列化对象 o 如果可能,否则它应该调用超类实现(以 TypeError

如果 滑雪板 为false(默认值),则它是 TypeError 尝试对不是 strintfloatNone . 如果 滑雪板 是的,这样的项目只是被跳过。

如果 ensure_ascii 为真(默认值),输出保证对所有传入的非ASCII字符进行转义。如果 ensure_ascii 为假,这些字符将按原样输出。

如果 check_circular 如果为true(默认值),则在编码期间将检查列表、dict和自定义编码对象的循环引用,以防止无限递归(这将导致 OverflowError )否则,不会进行此类检查。

如果 allow_nan 为真(默认值),则 NaNInfinity-Infinity 将被编码成这样。此行为不符合JSON规范,但与大多数基于JavaScript的编码器和解码器一致。否则,它将是一个 ValueError 对这种浮点数进行编码。

如果 sort_keys 为真(默认: False ,然后字典的输出将按键排序;这对于回归测试很有用,以确保可以每天比较JSON序列化。

如果 缩进 是非负整数或字符串,则JSON数组元素和对象成员将以该缩进级别进行打印。0、负数或 "" 只插入换行符。 None (默认)选择最紧凑的表示。使用正整数,每级缩进多少空格。如果 缩进 是字符串(例如 "\t" ,该字符串用于缩进每个级别。

在 3.2 版更改: 允许字符串用于 缩进 除了整数。

如果有规定, 分离器 应该是一个 (item_separator, key_separator) 元组。默认值为 (', ', ': ') 如果 缩进None(',', ': ') 否则。要获得最紧凑的JSON表示,应该指定 (',', ':') 以消除空白。

在 3.4 版更改: 使用 (',', ': ') 默认为 缩进 不是 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数据结构的json字符串表示, o . 例如::

>>> json.JSONEncoder().encode({"foo": ["bar", "baz"]})
'{"foo": ["bar", "baz"]}'
iterencode(o)

对给定对象进行编码, o ,并生成每个可用的字符串表示形式。例如::

for chunk in json.JSONEncoder().iterencode(bigobject):
    mysocket.write(chunk)

例外情况

exception json.JSONDecodeError(msg, doc, pos)

的子类 ValueError 具有以下附加属性:

msg

未格式化的错误消息。

doc

正在分析的JSON文档。

pos

的起始索引 doc 分析失败。

lineno

对应的行 pos .

colno

对应于的列 pos .

3.5 新版功能.

标准一致性和互操作性

JSON格式由 RFC 7159 并且通过 ECMA-404 . 本节详细说明了该模块与RFC的符合程度。为简单起见, JSONEncoderJSONDecoder 不考虑子类和明确提及的参数以外的参数。

此模块不严格遵守RFC,实现了一些有效的javascript但无效的JSON扩展。特别地:

  • 接受并输出无限和NaN数值;

  • 接受对象中的重复名称,只使用姓氏-值对的值。

由于RFC允许符合RFC的解析器接受不符合RFC的输入文本,因此在默认设置下,此模块的反序列化器在技术上符合RFC。

字符编码

RFC要求使用utf-8、utf-16或utf-32表示JSON,其中utf-8是最大互操作性的推荐默认值。

在RFC允许的情况下,尽管不是必需的,但此模块的序列化程序集 ensure_ascii=True 默认情况下,这样可以对输出进行转义,以便生成的字符串只包含ASCII字符。

除了 ensure_ascii 参数,此模块严格按照python对象和 Unicode strings 因此不会直接解决字符编码问题。

RFC禁止向JSON文本的开头添加字节顺序标记(bom),并且该模块的序列化程序不会向其输出添加bom。RFC允许但不要求JSON反序列化程序忽略其输入中的初始BOM。此模块的反序列化程序引发 ValueError 当存在初始物料清单时。

RFC并没有明确地禁止包含与有效的Unicode字符(如不成对的UTF-16代理项)不对应的字节序列的JSON字符串,但它注意到它们可能会导致互操作性问题。默认情况下,此模块接受并输出 str )这些序列的代码点。

无限和NaN数值

RFC不允许无限或NaN数值的表示。尽管如此,默认情况下,此模块接受并输出 Infinity-InfinityNaN 好像它们是有效的JSON数字文本值:

>>> # 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 参数可用于更改此行为。

顶层非对象、非数组值

过时的JSON指定的旧版本 RFC 4627 要求JSON文本的顶级值必须是JSON对象或数组(python dictlist ,并且不能是JSON空值、布尔值、数字或字符串值。 RFC 7159 删除了该限制,而此模块没有也从未在其序列化程序或反序列化程序中实现过该限制。

无论如何,为了最大限度地实现互操作性,您可能希望自己自愿遵守这个限制。

实施限制

一些JSON反序列化程序实现可能会设置以下限制:

  • 接受的JSON文本的大小

  • JSON对象和数组的最大嵌套级别

  • JSON数的范围和精度

  • JSON字符串的内容和最大长度

此模块不会对相关的Python数据类型本身或Python解释器本身施加任何这样的限制。

当序列化到JSON时,注意应用程序中可能使用JSON的任何此类限制。特别是,JSON数字通常被反序列化为IEEE754双精度数字,因此受到该表示的范围和精度限制。这在序列化python时尤其重要 int 非常大的值,或者当序列化“异域”数字类型的实例时,例如 decimal.Decimal .

命令行界面

源代码: Lib/json/tool.py


这个 json.tool 模块提供了一个简单的命令行接口来验证和漂亮地打印JSON对象。

如果可选 infileoutfile 未指定参数, sys.stdinsys.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 版更改: 现在输出的顺序与输入的顺序相同。使用 --sort-keys 选项按键按字母顺序对字典的输出进行排序。

命令行选项

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

如果 因循守旧 未指定,读取自 sys.stdin .

outfile

写入的输出 因循守旧 到给定的 输出文件 . 否则,将其写入 sys.stdout .

--sort-keys

按关键字的字母顺序对字典的输出进行排序。

3.5 新版功能.

--no-ensure-ascii

禁用非ascii字符转义,请参见 json.dumps() 更多信息。

3.9 新版功能.

--json-lines

将每个输入行解析为单独的JSON对象。

3.8 新版功能.

--indent, --tab, --no-indent, --compact

空格控制的互斥选项。

3.9 新版功能.

-h, --help

显示帮助消息。

脚注

1

如中所述 the errata for RFC 7159 ,json允许字符串中的文字u+2028(行分隔符)和u+2029(段落分隔符)字符,而javascript(从EcmaScript 5.1版开始)则不允许。