19.2。 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 object literal syntax (although it is not a strict subset of JavaScript [1] ).

json显示标准库marshalpickle模块的用户熟悉的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"]'

紧凑编码:

>>> 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验证和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)

有关详细文档,请参见Command Line Interface

注意

JSON是YAML 1.2的子集。由此模块的默认设置(特别是默认的分隔符值)生成的JSON也是YAML 1.0和1.1的子集。因此,该模块也可以用作YAML串行器。

19.2.1. 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)

obj序列化为fp(a .write() - 支持file-like object使用此conversion table

If skipkeys is true (default: False), then dict keys that are not of a basic type (str, int, float, bool, None) will be skipped instead of raising a TypeError.

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

如果ensure_ascii为true(默认值),则输出将保证所有传入的非ASCII字符都转义。如果ensure_ascii为false,则这些字符将按原样输出。

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

如果allow_nan为false(默认值:True),则将是ValueError序列化超出范围float值(naninf-inf),严格遵守JSON规范。如果allow_nan为true,则将使用与其等效的JavaScript代码(NaNInfinity-Infinity)。

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

在版本3.2中更改:允许缩进的字符串以及整数。

如果指定,分隔符应为(item_separator, key_separator)元组。The default is (', ', ': ') if indent is None and (',', ': ') otherwise. 要获得最紧凑的JSON表示,应指定(',', ':')

在版本3.4中更改:使用(',', ': ')作为默认值,如果缩进不是None

如果指定,默认应该是一个函数,为不能被序列化的对象调用。它应该返回对象的JSON可编码版本或引发TypeError如果未指定,则会引发TypeError

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

要使用自定义JSONEncoder子类(例如覆盖default()方法以序列化其他类型),使用cls kwarg指定它;否则使用JSONEncoder

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 tableobj序列化为JSON格式的str参数具有与dump()中相同的含义。

注意

Unlike pickle and marshal, JSON is not a framed protocol, so trying to serialize multiple objects with repeated calls to dump() using the same fp will result in an invalid JSON file.

注意

JSON的键/值对中的键始终为str类型。当字典转换为JSON时,字典的所有键都会强制转换为字符串。因此,如果字典转换为JSON然后回到字典,字典可能不等于原始字典。也就是说,如果x具有非字符串键,则载入(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)

Deserialize fp (a .read()-supporting file-like object containing a JSON document) to a Python object using this conversion table.

object_hook是一个可选的函数,它将被任何对象字面值解码(dict)的结果调用。将使用object_hook的返回值而不是dict该特征可以用于实现定制解码器(例如,JSON-RPC类提示)。

object_pairs_hook是一个可选的函数,它将使用任何对象字面值的结果进行调用,并使用对的有序列表进行解码。将使用object_pairs_hook的返回值,而不是dict该特征可以用于实现依赖于键和值对被解码的顺序的自定义解码器(例如,collections.OrderedDict()将记住插入的顺序)。如果还定义了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

json.loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

使用此conversion table将包含JSON文档的s(a str实例)解压缩为Python对象。

其他参数与load()中含义相同,除了编码,它被忽略和弃用。

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

19.2.2. Encoders and Decoders

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

简单的JSON解码器。

默认情况下,在解码时执行以下翻译:

JSONPython
目的命令
数组列表
str
number(int)int
数字(实数)浮动
真正真正
空值没有

它还将NaNInfinity-Infinity理解为它们对应的float值, 。

object_hook(如果指定)将使用每个解析的JSON对象的结果进行调用,其返回值将用于替换给定的dict这可以用于提供定制反序列化(例如,以支持JSON-RPC类提示)。

object_pairs_hook(如果指定)将使用对的有序列表解码的每个JSON对象的结果进行调用。将使用object_pairs_hook的返回值,而不是dict该特征可以用于实现依赖于键和值对被解码的顺序的自定义解码器(例如,collections.OrderedDict()将记住插入的顺序)。如果还定义了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''null''true''false'这可以用于引发异常,如果遇到无效的JSON数字。

如果strict为false(True是默认值),则在字符串中将允许控制字符。在此上下文中的控制字符是具有在0-31范围内的字符代码的字符,包括'\t'(tab),'\n''\r''\0'

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

decode(s)

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

如果给定的JSON文档无效,则会引发JSONDecodeError

raw_decode(s)

s(以JSON文档开头的str)解码JSON文档,并返回一个2元组的Python表示形式和s t4 >文档结束。

这可以用于从可能在末尾有无关数据的字符串解码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编码器。

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

PythonJSON
命令目的
列表,元组数组
str
int,float,int-&float-derived枚举
真正真正
没有空值

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

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

如果skipkeys为false(默认值),则会尝试对非str,int,float或None的键进行编码的TypeError如果skipkeys为true,则此类项目将被直接跳过。

如果ensure_ascii为true(默认值),则输出将保证所有传入的非ASCII字符都转义。如果ensure_ascii为false,则这些字符将按原样输出。

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

If allow_nan is true (the default), then NaN, Infinity, and -Infinity will be encoded as such. 此行为不符合JSON规范,但与大多数基于JavaScript的编码器和解码器一致。否则,将对此类浮点进行编码为ValueError

如果sort_keys为真(默认值:False),那么字典的输出将按键排序;这对于回归测试非常有用,以确保JSON序列化可以在每天的基础上进行比较。

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

在版本3.2中更改:允许缩进的字符串以及整数。

如果指定,分隔符应为(item_separator, key_separator)元组。The default is (', ', ': ') if indent is None and (',', ': ') otherwise. 要获得最紧凑的JSON表示,应指定(',', ':')

在版本3.4中更改:使用(',', ': ')作为默认值,如果缩进不是None

如果指定,默认应该是一个函数,为不能被序列化的对象调用。它应该返回对象的JSON可编码版本或引发TypeError如果未指定,则会引发TypeError

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)

19.2.3. Exceptions

exception json.JSONDecodeError(msg, doc, pos, end=None)

Subclass of ValueError with the following additional attributes:

msg

The unformatted error message.

doc

The JSON document being parsed.

pos

The start index of doc where parsing failed.

lineno

The line corresponding to pos.

colno

The column corresponding to pos.

版本3.5中的新功能。

19.2.4. Standard Compliance and Interoperability

JSON格式由 RFC 7159ECMA-404指定。本节详细说明此模块符合RFC的级别。为了简单起见,不考虑JSONEncoderJSONDecoder子类以及除明确提及的参数之外的参数。

此模块以严格的方式不符合RFC,实现一些有效的JavaScript但不是有效的JSON的扩展。尤其是:

  • 接受和输出无限和NaN数值;
  • 接受对象内的重复名称,并且仅使用最后名称/值对的值。

由于RFC允许RFC兼容的解析器接受不符合RFC的输入文本,所以该模块的解串器在默认设置下技术上符合RFC。

19.2.4.1. Character Encodings

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。当存在初始BOM时,此模块的解串器引发ValueError

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

19.2.4.2. Infinite and NaN Number Values

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

19.2.4.3. Repeated Names Within an Object

RFC指定JSON对象中的名称应该是唯一的,但不要求如何处理JSON对象中的重复名称。默认情况下,此模块不引发异常;相反,它忽略除了给定名称的最后一个名称/值对之外的所有值:

>>> weird_json = '{"x": 1, "x": 2, "x": 3}'
>>> json.loads(weird_json)
{'x': 3}

可以使用object_pairs_hook参数更改此行为。

19.2.4.4. Top-level Non-Object, Non-Array Values

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

无论如何,为了实现最大的互操作性,您可能希望自愿遵守该限制。

19.2.4.5. Implementation Limitations

一些JSON解串器实现可能设置以下限制:

  • 接受的JSON文本的大小
  • JSON对象和数组的最大嵌套级别
  • JSON数字的范围和精度
  • JSON字符串的内容和最大长度

除了相关的Python数据类型本身或Python解释器本身之外,此模块不强加任何此类限制。

当序列化为JSON时,请注意可能会消耗您的JSON的应用程序中的任何此类限制。特别地,通常将JSON数字反序列化为IEEE 754双精度数字,并且因此服从于该表示的范围和精度限制。当序列化非常大的Python int值或者序列化“异常”数值类型的实例(例如decimal.Decimal)时,这一点尤其重要。

19.2.5. Command Line Interface

源代码: 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选项按字母顺序对字典的输出进行排序。

19.2.5.1. Command line options

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

按字母顺序按字母顺序排序字典的输出。

版本3.5中的新功能。

-h, --help

显示帮助消息。

脚注

[1]正如RFC 7159的勘误中所述,JSON允许字符串中的字面值U + 2028(LINE SEPARATOR)和U + 2029(PARAGRAPH SEPARATOR)字符,而JavaScript(ECMAScript Edition 5.1版) 。