Содержание страницы
18.2. json – кодировщик и декодировщик JSON¶json – JSON encoder and decoder
JSON (JavaScript Object Notation), определённый в RFC 4627, это легковесный формат обмена данными, основанный на подмножестве синтаксиса JavaScript (ECMA-262, 3-е издание).
json предоставляет API, знакомый пользователям модулей marshal и pickle из стандартной библиотеки.
Кодирование иерархий базовых объектов 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, separators=(',', ': ')))
{
"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]
... # Пусть метод базового класса по умолчанию возбуждает 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 -mjson.tool
{
"json": "obj"
}
$ echo '{1.2:3.4}' | python -mjson.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Примечание
JSON является подмножеством YAML 1.2. JSON, создаваемый настройками модуля по умолчанию (в частности, значением separators по умолчанию), также является подмножеством YAML 1.0 и 1.1. Таким образом, этот модуль можно использовать как сериализатор YAML.
18.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 в поток в формате JSON в fp (объект, поддерживающий .write() файлоподобный объект).
Если skipkeys равно True (по умолчанию: False), то ключи словаря, не являющиеся базовыми типами (str, int, float, bool, None), будут пропущены вместо возбуждения исключения TypeError.
Модуль json всегда создает объекты str, а не bytes. Поэтому fp.write() должен поддерживать ввод str.
Если ensure_ascii равен True (по умолчанию), то гарантируется, что все входящие не-ASCII символы будут экранированы. Если ensure_ascii равен False, эти символы будут выводиться как есть.
Если check_circular равно False (по умолчанию: True), то проверка циклических ссылок для контейнерных типов будет пропущена, и циклическая ссылка приведет к OverflowError (или хуже).
Если allow_nan равно False (по умолчанию: True), то сериализация значений float вне допустимого диапазона (nan, inf, -inf) будет вызывать ValueError в строгом соответствии со спецификацией JSON, вместо использования JavaScript-эквивалентов (NaN, Infinity, -Infinity).
Если indent – неотрицательное целое число или строка, то элементы массива JSON и члены объекта будут выводиться с отступами на указанный уровень. Уровень отступа 0, отрицательный или "" приведёт только к вставке новых строк. None (по умолчанию) выбирает наиболее компактное представление. Использование положительного целого числа задаёт отступ в указанное количество пробелов на уровень. Если indent – строка (например, "\t"), то эта строка используется для отступа на каждом уровне.
Изменено в версии 3.2: Теперь допускаются строки для indent в дополнение к целым числам.
Примечание
Поскольку разделителем элементов по умолчанию является ', ', в выводе может появиться конечный пробел, если указан параметр indent. Чтобы этого избежать, можно использовать separators=(',', ': ').
Если separators является кортежем (item_separator, dict_separator), то он будет использоваться вместо разделителей по умолчанию (', ', ': '). (',', ':') – это наиболее компактное представление JSON.
default(obj) – это функция, которая должна возвращать сериализуемую версию obj или возбуждать TypeError. По умолчанию просто возбуждается TypeError.
Если sort_keys равно True (по умолчанию: False), то вывод словарей будет отсортирован по ключам.
Чтобы использовать пользовательский подкласс JSONEncoder (например, переопределяющий метод default() для сериализации дополнительных типов), укажите его в аргументе cls; в противном случае используется 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)¶
Сериализует obj в строку str в формате JSON. Аргументы имеют тот же смысл, что и в dump().
Примечание
В отличие от pickle и marshal, JSON не является протоколом с обрамлением, поэтому попытка сериализовать несколько объектов с помощью повторных вызовов dump() с одним и тем же fp приведет к созданию недопустимого JSON-файла.
Примечание
Ключи в парах ключ-значение 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 (файлоподобный объект, поддерживающий .read() и содержащий JSON-документ) в объект Python.
object_hook – необязательная функция, которая будет вызвана с результатом декодирования любого объектного литерала (словаря dict). Возвращаемое значение object_hook будет использовано вместо dict. Эта возможность может использоваться для реализации собственных декодеров (например, JSON-RPC class hinting).
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(num_str). Это можно использовать для применения другого типа данных или парсера для JSON целых чисел (например, float).
parse_constant, если указан, будет вызываться с одной из следующих строк: '-Infinity', 'Infinity', 'NaN'. Это можно использовать для возбуждения исключения при обнаружении недопустимых чисел JSON.
Изменено в версии 3.1: parse_constant больше не вызывается для ‘null’, ‘true’, ‘false’.
Чтобы использовать пользовательский подкласс JSONDecoder, укажите его в аргументе cls; в противном случае используется JSONDecoder. Дополнительные ключевые аргументы будут переданы конструктору класса.
- json.loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)¶
Десериализует s (экземпляр str, содержащий JSON-документ) в объект Python.
Остальные аргументы имеют тот же смысл, что и в load(), за исключением encoding, который игнорируется и является устаревшим.
18.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-декодер.
По умолчанию выполняет следующие преобразования при декодировании:
JSON Python объект dict массив список строка str число (int) int число (вещественное) float истина True ложь False null None Он также понимает NaN, Infinity и -Infinity как соответствующие значения float, что выходит за рамки спецификации JSON.
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(num_str). Это можно использовать для применения другого типа данных или парсера для JSON целых чисел (например, float).
parse_constant, если указан, будет вызван с одной из следующих строк: '-Infinity', 'Infinity', 'NaN', 'null', 'true', 'false'. Это может быть использовано для возбуждения исключения при обнаружении недопустимых JSON чисел.
Если strict равен False (True – значение по умолчанию), то управляющие символы будут разрешены внутри строк. Управляющие символы в данном контексте – это символы с кодами в диапазоне 0–31, включая '\t' (табуляция), '\n' (новая строка), '\r' (возврат каретки) и '\0'.
- raw_decode(s)¶
Декодирует JSON-документ из s (экземпляр str, начинающийся с JSON-документа) и возвращает кортеж из двух элементов: представление 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)¶
Расширяемый JSON-кодировщик для структур данных Python.
По умолчанию поддерживает следующие объекты и типы:
Python JSON dict объект list, tuple массив str строка int, float число True истина False ложь None null Чтобы расширить это для распознавания других объектов, создайте подкласс и реализуйте метод default(): с помощью другого метода он должен возвращать сериализуемый объект для o, если это возможно; в противном случае следует вызвать реализацию суперкласса (чтобы возбудить TypeError).
Если skipkeys равен False (значение по умолчанию), то попытка кодирования ключей, не являющихся 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), то вывод словарей будет отсортирован по ключам; это полезно для регрессионного тестирования, чтобы гарантировать, что JSON-сериализации можно сравнивать изо дня в день.
Если indent – неотрицательное целое число или строка, то элементы массива JSON и члены объекта будут выводиться с отступами на указанный уровень. Уровень отступа 0, отрицательный или "" приведёт только к вставке новых строк. None (по умолчанию) выбирает наиболее компактное представление. Использование положительного целого числа задаёт отступ в указанное количество пробелов на уровень. Если indent – строка (например, "\t"), то эта строка используется для отступа на каждом уровне.
Изменено в версии 3.2: Теперь в качестве indent можно передавать строки, а не только целые числа.
Примечание
Поскольку разделителем элементов по умолчанию является ', ', в выводе может появиться конечный пробел, если указан параметр indent. Чтобы этого избежать, можно использовать separators=(',', ': ').
Если указано, separators должны быть кортежем вида (item_separator, key_separator). По умолчанию – (', ', ': '). Чтобы получить наиболее компактное представление JSON, укажите (',', ':'), чтобы убрать пробелы.
Если указан, default – это функция, которая вызывается для объектов, которые иначе не могут быть сериализованы. Она должна возвращать версию объекта, пригодную для кодирования в JSON, или возбуждать TypeError.
- default(o)¶
Реализуйте этот метод в подклассе так, чтобы он возвращал сериализуемый объект для o или вызывал базовую реализацию (чтобы возбудить TypeError).
Например, чтобы поддерживать произвольные итераторы, можно реализовать default следующим образом:
def default(self, o): try: iterable = iter(o) except TypeError: pass else: return list(iterable) # Пусть метод базового класса по умолчанию возбуждает 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)
18.2.3. Соответствие стандартам¶Standard Compliance
Формат JSON определён спецификацией RFC 4627. В этом разделе описывается степень соответствия модуля требованиям RFC. Для простоты подклассы JSONEncoder и JSONDecoder, а также параметры, не указанные явно, не рассматриваются.
Этот модуль не полностью соответствует RFC, реализуя некоторые расширения, которые являются допустимым JavaScript, но недопустимым JSON. В частности:
- Принимаются и выводятся значения верхнего уровня, не являющиеся объектами или массивами;
- Бесконечные и NaN числовые значения принимаются и выводятся;
- Повторяющиеся имена в объекте принимаются, и используется только значение последней пары.
Поскольку RFC разрешает совместимым с RFC анализаторам принимать входные тексты, которые не соответствуют RFC, десериализатор этого модуля технически соответствует RFC при настройках по умолчанию.
18.2.3.1. Кодировки символов¶Character Encodings
RFC рекомендует представлять JSON в кодировках UTF-8, UTF-16 или UTF-32, причём UTF-8 используется по умолчанию.
Согласно RFC это допускается, но не требуется; сериализатор данного модуля по умолчанию использует ensure_ascii=True, экранируя вывод так, чтобы результирующие строки содержали только ASCII-символы.
За исключением параметра ensure_ascii, данный модуль строго определён в терминах преобразования между объектами Python и Unicode strings, поэтому иным образом не затрагивает вопрос кодировок символов.
18.2.3.2. Значения верхнего уровня, не являющиеся объектами или массивами¶Top-level Non-Object, Non-Array Values
RFC определяет, что значение верхнего уровня JSON-текста должно быть либо объектом JSON, либо массивом (Python dict или list). Десериализатор этого модуля также принимает входные тексты, состоящие только из значения JSON null, boolean, number или string:
>>> just_a_json_string = '"spam and eggs"' # Сам по себе не является корректным текстом JSON
>>> json.loads(just_a_json_string)
'spam and eggs'
Сам модуль не предоставляет способа считать такие входные тексты недопустимыми. Аналогично, сериализатор модуля также принимает в качестве входных данных отдельные значения Python None, bool, числовые и str и генерирует выходные тексты, состоящие только из значения JSON верхнего уровня null, boolean, number или string, без возбуждения исключения:
>>> neither_a_list_nor_a_dict = "spam and eggs"
>>> json.dumps(neither_a_list_nor_a_dict) # Результат не является корректным текстом JSON
'"spam and eggs"'
Сериализатор этого модуля сам по себе не включает средства принудительного соблюдения упомянутого ограничения.
18.2.3.3. Бесконечные и NaN-значения чисел¶Infinite and NaN Number Values
RFC не допускает представление бесконечных или NaN числовых значений. Несмотря на это, по умолчанию данный модуль принимает и выводит Infinity, -Infinity и NaN так, как если бы они были допустимыми JSON-литералами чисел:
>>> # Ни один из этих вызовов не возбуждает исключение, но результаты не являются корректным JSON
>>> json.dumps(float('-inf'))
'-Infinity'
>>> json.dumps(float('nan'))
'NaN'
>>> # То же самое при десериализации
>>> json.loads('-Infinity')
-inf
>>> json.loads('NaN')
nan
В сериализаторе параметр allow_nan можно использовать для изменения этого поведения. В десериализаторе параметр parse_constant можно использовать для изменения этого поведения.
18.2.3.4. Повторяющиеся имена внутри объекта¶Repeated Names Within an Object
RFC определяет, что имена внутри объекта JSON должны быть уникальными, но не указывает, как следует обрабатывать повторяющиеся имена. По умолчанию модуль не возбуждает исключение; вместо этого он игнорирует все пары «имя-значение», кроме последней для данного имени:
>>> weird_json = '{"x": 1, "x": 2, "x": 3}'
>>> json.loads(weird_json)
{'x': 3}
Параметр object_pairs_hook можно использовать для изменения этого поведения.