Содержание страницы
19.2. json – кодировщик и декодировщик JSON¶json – JSON encoder and decoder
Исходный код: Lib/json/__init__.py
JSON (JavaScript Object Notation), описанный в RFC 7159 (который заменяет RFC 4627) и в ECMA-404, является легковесным форматом обмена данными, вдохновлённым синтаксисом литералов объектов JavaScript (хотя он не является строгим подмножеством JavaScript 1).
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))
{
"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 -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, создаваемый настройками модуля по умолчанию (в частности, значением separators по умолчанию), также является подмножеством 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 в поток в формате 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), то будетValueErrorсериализовать значенияfloat, выходящие за пределы (nan,inf,-inf), в строгом соответствии со спецификацией JSON. Если allow_nan имеет значение true, будут использоваться их эквиваленты из JavaScript (NaN,Infinity,-Infinity).Если indent – неотрицательное целое число или строка, то элементы JSON-массивов и члены объектов выводятся с отступами, соответствующими указанному уровню. Уровень отступа 0, отрицательное значение или
""вставляет только переводы строк.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: Все необязательные параметры теперь являются только ключевыми.
-
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, а затем обратно в словарь, полученный словарь может не совпадать с исходным. То есть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 подсказки класса).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-документом, будет вызвано
JSONDecodeError.Изменено в версии 3.6: Все необязательные параметры теперь являются только ключевыми.
Изменено в версии 3.6: fp теперь может быть двоичным файлом. Кодировка ввода должна быть UTF-8, UTF-16 или UTF-32.
-
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,bytesилиbytearrayэкземпляр, содержащий документ JSON) в объект Python с помощью этой таблицы преобразования.Остальные аргументы имеют тот же смысл, что и в
load(), за исключением encoding, который игнорируется и считается устаревшим.Если десериализуемые данные не являются корректным 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-декодер.
По умолчанию выполняет следующие преобразования при декодировании:
JSON
Python
объект
dict
массив
list
строка
str
число (int)
int
число (вещественное)
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. Эта возможность может быть использована для реализации собственных декодеров, которые полагаются на порядок декодирования пар ключ-значение (например,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.Если strict равно false (по умолчанию
True), то управляющие символы допускаются внутри строк. Под управляющими символами здесь понимаются символы с кодами в диапазоне 0–31, включая'\t'(табуляция),'\n','\r'и'\0'.Если десериализуемые данные не являются корректным JSON-документом, будет вызвано
JSONDecodeError.Изменено в версии 3.6: Все параметры теперь только ключевые.
-
decode(s)¶ Возвращает представление s в Python (экземпляр
str, содержащий JSON-документ).JSONDecodeErrorбудет вызвано, если переданный JSON-документ не является корректным.
-
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, перечисления, производные от int и float
число
True
true
False
false
None
null
Изменено в версии 3.4: Добавлена поддержка классов Enum, производных от int и float.
Чтобы расширить функциональность на другие объекты, создайте подкласс и реализуйте метод
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 в дополнение к целым числам.
Если указан, то 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) # Пусть метод базового класса по умолчанию возбуждает 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)
-
19.2.3. Исключения¶Exceptions
-
exception
json.JSONDecodeError(msg, doc, pos)¶ Подкласс
ValueErrorсо следующими дополнительными атрибутами:-
msg¶ Неформатированное сообщение об ошибке.
-
doc¶ Разбираемый JSON-документ.
-
pos¶ Начальный индекс doc, в котором произошла ошибка разбора.
-
lineno¶ Строка, соответствующая pos.
-
colno¶ Столбец, соответствующий pos.
Новое в версии 3.5.
-
19.2.4. Соответствие стандартам и интероперабельность¶Standard Compliance and Interoperability
Формат JSON определяется RFC 7159 и ECMA-404.
В этом разделе подробно описывается степень соответствия модуля RFC.
Для простоты JSONEncoder и JSONDecoder подклассы, а также параметры, не указанные явно, не рассматриваются.
Этот модуль не полностью соответствует RFC, реализуя некоторые расширения, которые являются допустимым JavaScript, но недопустимым JSON. В частности:
Бесконечные и NaN числовые значения принимаются и выводятся;
Повторяющиеся имена в объекте принимаются, и используется только значение последней пары.
Поскольку RFC разрешает совместимым с RFC анализаторам принимать входные тексты, которые не соответствуют RFC, десериализатор этого модуля технически соответствует RFC при настройках по умолчанию.
19.2.4.1. Кодировки символов¶Character Encodings
RFC требует, чтобы JSON был представлен с использованием UTF-8, UTF-16 или UTF-32, причём 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) кодовые точки таких последовательностей.
19.2.4.2. Бесконечные и 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 можно использовать для изменения этого поведения.
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
Старая версия JSON, определённая устаревшим RFC 4627, требовала, чтобы
значение верхнего уровня JSON-текста было либо JSON-объектом, либо массивом
(Python dict или list), и не могло быть null, boolean,
числом или строкой. 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-объектов.
Если необязательные аргументы 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 для сортировки вывода словарей по ключу в алфавитном порядке.
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) – нет.