# `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` 提供了与标准库 `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"]'

紧凑编码:

    >>> 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` 来验证并美化输出：

    $ 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 and 1.1 的一个子集。因此该模块也能够用于序列化为 YAML。

注解

这个模块的编码器和解码器默认保护输入和输出的顺序。仅当底层的容器未排序时才会失去顺序。

在 Python 3.7 之前，`dict` 并不保证有序，因此输入和输出通常都是乱序的，除非是明确地请求 `collections.OrderedDict`。 从 Python 3.7 开始，普通的 `dict` 会保留顺序，因此不必再为 JSON 的生成和解析指定使用 `collections.OrderedDict`。

## 基本使用

`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，这些字符会原样输出。

  If check_circular is false (default: `True`), then the circular reference check for container types will be skipped and a circular reference will result in an `RecursionError` (or worse).

  如果 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 已被移除。

## 编码器和解码器

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

  简单的JSON解码器。

  默认情况下，解码执行以下翻译:

  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`。 这一特性可被用于实现自定义解码器。 如果还定义了 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 数字则可以使用它引发异常。

  如果 strict 为 false （默认为 `True` ），那么控制字符将被允许在字符串内。在此上下文中的控制字符编码在范围 0--31 内的字符，包括 `'\t'` (制表符）， `'\n'` ， `'\r'` 和 `'\0'` 。

  如果反序列化的数据不是有效 JSON 文档，引发 `JSONDecodeError` 错误。

  在 3.6 版更改: 所有形参现在都是 仅限关键字参数。

  `decode`(s)

    返回 s 的 Python 表示形式（包含一个 JSON 文档的 `str` 实例）。

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

  `raw_decode`(s)

    从 s 中解码出 JSON 文档（以 JSON 文档开头的一个 `str` 对象）并返回一个 Python 表示形式为 2 元组以及指明该文档在 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
  --- | ---
  dict | object
  list, tuple | array
  str | string
  int, float, int 和 float 派生的枚举 | number
  True | true
  False | false
  None | null

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

  为了将其拓展至识别其他对象，需要子类化并实现 `default()` 方法于另一种返回 `o` 的可序列化对象的方法如果可行，否则它应该调用超类实现（来引发 `TypeError` ）。

  如果 skipkeys 为假值（默认），则当尝试对非 `str`, `int`, `float` 或 `None` 的键进行编码时将会引发 `TypeError`。 如果 skipkeys 为真值，这些条目将被直接跳过。

  如果 ensure_ascii 是 true （即默认值），输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false，这些字符会原样输出。

  If check_circular is true (the default), then lists, dicts, and custom encoded objects will be checked for circular references during encoding to prevent an infinite recursion (which would cause an `RecursionError`). Otherwise, no such check takes place.

  如果 allow_nan 为 true （默认），那么 `NaN` ， `Infinity` ，和 `-Infinity` 进行编码。此行为不符合 JSON 规范，但与大多数的基于 Javascript 的编码器和解码器一致。否则，它将是一个 `ValueError` 来编码这些浮点数。

  如果 sort_keys 为 true （默认为： `False` ），那么字典的输出是按照键排序；这对回归测试很有用，以确保可以每天比较 JSON 序列化。

  如果 indent 是一个非负整数或者字符串，那么 JSON 数组元素和对象成员会被美化输出为该值指定的缩进等级。 如果缩进等级为零、负数或者 `""`，则只会添加换行符。 `None` (默认值) 选择最紧凑的表达。 使用一个正整数会让每一层缩进同样数量的空格。 如果 indent 是一个字符串 (比如 `"\t"`)，那个字符串会被用于缩进每一层。

  在 3.2 版更改: 允许使用字符串作为 indent 而不再仅仅是整数。

  当指定时，separators 应当是一个 `(item_separator, key_separator)` 元组。当 indent 为 `None` 时，默认值取 `(', ', ': ')`，否则取 `(',', ': ')`。为了得到最紧凑的 JSON 表达式，你应该指定其为 `(',', ':')` 以消除空白字符。

  在 3.4 版更改: 现当 indent 不是 `None` 时，采用 `(',', ': ')` 作为默认值。

  当 default 被指定时，其应该是一个函数，每当某个对象无法被序列化时它会被调用。它应该返回该对象的一个可以被 JSON 编码的版本或者引发一个 `TypeError`。如果没有被指定，则会直接引发 `TypeError`。

  在 3.6 版更改: 所有形参现在都是 仅限关键字参数。

  `default`(o)

    在子类中实现这种方法使其返回 o 的可序列化对象，或者调用基础实现（引发 `TypeError` ）。

    例如，为了支持任意的迭代器，你可以这样来实现 `default()`:

        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)

## 异常

exception `json.``JSONDecodeError`(msg, doc, pos)

  拥有以下附加属性的 `ValueError` 的子类：

  `msg`

    未格式化的错误消息。

  `doc`

    正在解析的 JSON 文档。

  `pos`

    The start index of doc where parsing failed.

  `lineno`

    The line corresponding to pos.

  `colno`

    The column corresponding to pos.

  3.5 新版功能.

## 标准符合性和互操作性

The JSON format is specified by RFC 7159 and by ECMA-404. This section details this module's level of compliance with the RFC. For simplicity, `JSONEncoder` and `JSONDecoder` subclasses, and parameters other than those explicitly mentioned, are not considered.

此模块不严格遵循于 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 禁止添加字符顺序标记（ BOM ）在 JSON 文本的开头，这个模块的序列化器不添加 BOM 标记在它的输出上。 RFC，准许 JSON 反序列化器忽略它们输入中的初始 BOM 标记，但不要求。此模块的反序列化器引发 `ValueError` 当存在初始 BOM 标记。

RFC 不会明确禁止包含字节序列的 JSON 字符串这不对应有效的 Unicode 字符（比如 不成对的 UTF-16 的替代物），但是它确实指出它们可能会导致互操作性问题。默认下，模块对这样的序列接受和输出（当在原始 `str` 存在时）代码点。

### Infinite 和 NaN 数值

RFC 不允许 infinite 或者 NaN 数值的表达方式。尽管这样，默认情况下，此模块接受并且输出 `Infinity` ， `-Infinity`，和 `NaN` 好像它们是有效的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}

The object_pairs_hook parameter can be used to alter this behavior.

### 顶级非对象，非数组值

过时的 RFC 4627 指定的旧版本 JSON 要求 JSON 文本顶级值必须是 JSON 对象或数组（ Python `dict` 或 `list` ），并且不能是 JSON null 值，布尔值，数值或者字符串值。 RFC 7159 移除这个限制，此模块没有并且从未在序列化器和反序列化器中实现这个限制。

无论如何，为了最大化地获取互操作性，你可能希望自己遵守该原则。

### 实现限制

一些 JSON 反序列化器的实现应该在以下方面做出限制：

- 可接受的 JSON 文本大小

- 嵌套 JSON 对象和数组的最高水平

- JSON 数字的范围和精度

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

此模块不强制执行任何上述限制，除了相关的 Python 数据类型本身或者 Python 解释器本身的限制以外。

当序列化为 JSON ，在应用中当心此类限制这可能破坏你的 JSON 。特别是，通常将 JSON 数字反序列化为 IEEE 754 双精度数字，从而受到该表示方式的范围和精度限制。这是特别相关的，当序列化非常大的 Python `int` 值时，或者当序列化 "exotic" 数值类型的实例时比如 `decimal.Decimal` 。

## 命令行界面

源代码： Lib/json/tool.py

The `json.tool` module provides a simple command line interface to validate and pretty-print JSON objects.

如果未指定可选的 `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 版更改: 输出现在将与输入顺序保持一致。 请使用 `--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
          }
      ]

  如果 infile 未指定，则从 `sys.stdin` 读取。

`outfile```

  将 infile 输出写入到给定的 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

  正如 RFC 7159 的勘误表 所说明的，JSON 允许以字符串表示字面值字符 U+2028 (LINE SEPARATOR) 和 U+2029 (PARAGRAPH SEPARATOR)，而 JavaScript (在 ECMAScript 5.1 版中) 不允许。