Json decode: PHP: json_decode — Manual

json — кодировщик и декодер JSON — документация по Python 3.11.4

Исходный код: Lib/json/__init__.py


JSON (обозначение объекта JavaScript), указанный
RFC 7159 (который заменяет RFC 4627 ) и
ЭКМА-404,
это облегченный формат обмена данными, вдохновленный
Синтаксис литерала объекта JavaScript
(хотя это не строгое подмножество JavaScript 1 ).

Предупреждение

Будьте осторожны при анализе данных JSON из ненадежных источников. злонамеренный
Строка JSON может привести к тому, что декодер потребляет значительное количество ресурсов ЦП и памяти.
Ресурсы. Рекомендуется ограничить размер анализируемых данных.

json предоставляет API, знакомый пользователям стандартной библиотеки
модули маршал и пикл .

Кодирование базовых иерархий объектов Python:

 >>> импорт json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1. 0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"фу\бар"
>>> печать (json.dumps ('\ u1234'))
"\u1234"
>>> печать (json.dumps ('\\'))
"\\"
>>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
{"а": 0, "б": 0, "в": 0}
>>> из io импортировать StringIO
>>> ио = StringIO()
>>> json.dump(['API потоковой передачи'], io)
>>> io.getvalue()
'["API потоковой передачи"]'
 

Компактная кодировка:

 >>> импорт json
>>> json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'
 

Красивая печать:

 >>> импорт json
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, отступ=4))
{
    «4»: 5,
    «6»: 7
}
 

Декодирование JSON:

 >>> импорт json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
'"foo\x08ar'
>>> из io импортировать StringIO
>>> io = StringIO('["API потоковой передачи"]')
>>> json.load(io)
['API потоковой передачи']
 

Специализация декодирования объектов JSON:

 >>> импорт json
>>> определение as_complex(dct):
. .. если '__complex__' в dct:
... возвращаемый комплекс (dct['real'], dct['imag'])
... возврат ДКП
...
>>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
... object_hook=as_complex)
(1+2к)
>>> импорт десятичного
>>> json.loads('1.1', parse_float=decimal.Decimal)
Десятичный ('1.1')
 

Расширение JSONEncoder :

 >>> импортировать json
>>> класс ComplexEncoder(json.JSONEncoder):
... по умолчанию (я, объект):
... если isinstance (obj, комплекс):
... вернуть [obj.real, obj.imag]
... # Пусть метод по умолчанию базового класса вызовет TypeError
... вернуть 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 из оболочки для проверки и красивой печати:

 $ эхо '{"json":"obj"}' | питон-м json.tool
{
    "json": "объект"
}
$ эхо '{1.2:3. 4}' | питон-м json.tool
Ожидается имя свойства, заключенное в двойные кавычки: строка 1 столбец 2 (char 1)
 

Подробную документацию см. в разделе Интерфейс командной строки.

Примечание

JSON является подмножеством YAML 1.2. JSON, созданный
настройки этого модуля по умолчанию (в частности, по умолчанию сепараторы
value) также является подмножеством YAML 1.0 и 1.1. Таким образом, этот модуль также может быть
используется как сериализатор YAML.

Примечание

Кодеры и декодеры этого модуля сохраняют порядок ввода и вывода,
по умолчанию. Порядок теряется только в том случае, если базовые контейнеры неупорядочены.

Основное использование

json.dump( obj , fp , * , skipkeys=False , sure_ascii=True , check_circular=True , allow_nan=Истина , cls=Нет , отступ=Нет , разделители=Нет , default=Нет , sort_keys=Ложь 90 063, **квт )

Сериализация obj в виде потока в формате JSON в fp (поддержка . write()
файлоподобный объект), используя эту таблицу преобразования.

Если skipkeys имеет значение true (по умолчанию: False ), то ключи dict, которые не
базового типа ( str , int , float , bool ,
None ) будет пропущен вместо того, чтобы вызывать TypeError .

Модуль json всегда создает объекты str , а не
байт объектов. Следовательно, fp.write() должен поддерживать str
вход.

Если обеспечить_ascii истинно (по умолчанию), вывод гарантированно
экранировать все входящие не-ASCII-символы. Если обеспечить_ascii есть
false, эти символы будут выводиться как есть.

Если check_circular имеет значение false (по умолчанию: True ), то круговой
проверка ссылок для типов контейнеров будет пропущена, а циклическая ссылка
приведет к ошибке RecursionError (или хуже).

Если allow_nan имеет значение false (по умолчанию: True ), то это будет
ValueError для сериализации вне диапазона float значений ( nan ,
inf , -inf ) в строгом соответствии со спецификацией JSON.
Если allow_nan истинно, их эквиваленты в JavaScript ( NaN ,
Infinity , -Infinity ).

Если отступ является неотрицательным целым числом или строкой, то элементы массива JSON и
члены объекта будут красиво напечатаны с этим уровнем отступа. Уровень отступа
0, отрицательный или "" будет вставлять только новые строки. Нет (по умолчанию)
выбирает наиболее компактное представление. Использование положительного целочисленного отступа
отступов столько пробелов на уровень. Если отступ является строкой (например, "\t" ),
эта строка используется для отступа каждого уровня.

Изменено в версии 3.2: Разрешены строки для с отступом в дополнение к целым числам.

Если указано, разделители должны быть (item_separator, key_separator)
кортеж. По умолчанию (', ', ':') , если отступ равен Нет и
(',', ':') иначе. Чтобы получить наиболее компактное представление JSON,
вы должны указать (',', ':') для устранения пробелов.

Изменено в версии 3.4: Используйте (',', ': ') по умолчанию, если отступ не равен Нет .

Если указано, по умолчанию должна быть функцией, которая вызывается для объектов, которые
иначе не может быть сериализован. Он должен возвращать закодированную версию JSON
объект или поднимите Ошибка типа . Если не указано, TypeError
Поднялся.

Если sort_keys равно true (по умолчанию: False ), то вывод
словари будут отсортированы по ключу.

Чтобы использовать пользовательский подкласс JSONEncoder (например, тот, который переопределяет
default() для сериализации дополнительных типов), укажите его с помощью параметра
класс кварг; в противном случае используется JSONEncoder .

Изменено в версии 3.6: Все необязательные параметры теперь содержат только ключевые слова.

Примечание

В отличие от pickle и marshal , JSON не является фреймовым протоколом,
поэтому попытка сериализовать несколько объектов с повторными вызовами
dump() с использованием того же fp приведет к созданию недопустимого файла JSON.

json.dumps( obj , * , skipkeys=False , sure_ascii=True , check_circular=True , allow_nan=True 9006 3, клс=Нет , отступ=нет , разделители=нет , по умолчанию=нет , sort_keys=ложь , **kw )

Сериализация obj в формате JSON str с помощью этого преобразования
стол. Аргументы имеют тот же смысл, что и в
дамп() .

Примечание

Ключи в парах ключ/значение JSON всегда имеют тип str . Когда
словарь конвертируется в JSON, все ключи словаря
принуждают к струнам. В результате этого, если словарь преобразуется
в JSON, а затем обратно в словарь, словарь может не совпадать
оригинальный. то есть load(dumps(x)) != x , если x имеет нестроковый
ключи.

json.load( fp , * , cls=Нет , object_hook=Нет , parse_float=Нет , parse_int=Нет , 9 0062 parse_constant=Нет , object_pairs_hook=Нет , * *квт )

Десериализовать fp (поддерживающий текстовый файл .read() или
двоичный файл, содержащий документ JSON) в объект Python, используя
эта таблица преобразования.

object_hook — необязательная функция, которая будет вызываться с результатом
декодируется любой объектный литерал ( dict ). Возвращаемое значение
object_hook будет использоваться вместо dict . Эту функцию можно использовать
для реализации пользовательских декодеров (например, JSON-RPC
подсказка класса).

object_pairs_hook — необязательная функция, которая будет вызываться с
результат любого литерала объекта, декодированного с помощью упорядоченного списка пар.
возвращаемое значение object_pairs_hook будет использоваться вместо
дикт . Эту функцию можно использовать для реализации пользовательских декодеров.
Если object_hook также определен, object_pairs_hook имеет приоритет.

Изменено в версии 3.1: Добавлена ​​поддержка object_pairs_hook .

parse_float , если указано, будет вызываться со строкой каждого JSON
float для декодирования. По умолчанию это эквивалентно float(num_str) ..
Это можно использовать для использования другого типа данных или парсера для JSON с плавающей запятой.
(например, десятичный. Десятичный ).

parse_int , если указано, будет вызываться со строкой каждого JSON int
быть расшифрованным. По умолчанию это эквивалентно int(num_str) . Это может
использоваться для использования другого типа данных или парсера для целых чисел JSON
(например, с плавающей запятой ).

Изменено в версии 3.11: По умолчанию parse_int из int() теперь ограничивает максимальную длину
целочисленная строка через целочисленную строку интерпретатора
ограничение длины конверсии, чтобы избежать отказа
сервисных атак.

parse_constant , если указано, будет вызываться с одним из следующих
строки: '-Бесконечность' , 'Бесконечность' , '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 , * , cls=Нет , object_hook=Нет , parse_float=Нет , parse_int=Нет , разбор _constant=Нет , object_pairs_hook=Нет , **kw )

Десериализовать s (a str , байт или bytearray
экземпляр, содержащий документ JSON) в объект Python, используя этот
таблица преобразования.

Остальные аргументы имеют то же значение, что и в загрузка() .

Если десериализуемые данные не являются действительным документом JSON,
JSONDecodeError будет вызвано.

Изменено в версии 3.6: s теперь может иметь тип bytes или bytearray .
входная кодировка должна быть UTF-8, UTF-16 или UTF-32.

Изменено в версии 3.9: Аргумент ключевого слова , кодирующий , был удален.

Кодировщики и декодеры

класс json.JSONDecoder( * , object_hook = Нет , parse_float = Нет , parse_int = Нет , parse_constant = Нет , strict=Истина , object_pairs_hook=Нет )

Простой декодер JSON.

По умолчанию выполняет следующие преобразования при декодировании:

JSON

Питон

объект

дикт

массив

список

строка

ул

номер (внутренний)

внутр.

номер (реальный)

поплавок

правда

Правда

ложный

Ложь

ноль

Нет

Он также понимает NaN , Infinity и -Infinity как их
соответствующие значения с плавающей запятой , что выходит за рамки спецификации JSON.

object_hook , если указано, будет вызываться с результатом каждого JSON
объект декодируется, и его возвращаемое значение будет использоваться вместо заданного
дикт . Это можно использовать для предоставления пользовательских десериализаций (например, для
поддержка подсказок класса JSON-RPC).

object_pairs_hook , если указано, будет вызываться с результатом каждого
Объект JSON декодируется с помощью упорядоченного списка пар. Возвращаемое значение
object_pairs_hook будет использоваться вместо dict . Этот
функция может использоваться для реализации пользовательских декодеров. Если object_hook также
Определено, object_pairs_hook имеет приоритет.

Изменено в версии 3.1: Добавлена ​​поддержка object_pairs_hook .

parse_float , если указано, будет вызываться со строкой каждого JSON
float для декодирования. По умолчанию это эквивалентно float(num_str) .
Это можно использовать для использования другого типа данных или парсера для JSON с плавающей запятой.
(например, десятичный. Десятичный ).

parse_int , если указано, будет вызываться со строкой каждого JSON int
быть расшифрованным. По умолчанию это эквивалентно целое(число_стр) . Это может
использоваться для использования другого типа данных или парсера для целых чисел JSON
(например, с плавающей запятой ).

parse_constant , если указано, будет вызываться с одним из следующих
строки: '-Бесконечность' , 'Бесконечность' , 'NaN' .
Это можно использовать для создания исключения, если недопустимые числа JSON
встречаются.

Если strict равно false ( True по умолчанию), то управляющие символы
будут разрешены внутри строк. Управляющие символы в этом контексте
те, у которых коды символов находятся в диапазоне 0–31, включая '\t' (вкладка),
'\n' , '\r' и '\0' .

Если десериализуемые данные не являются действительным документом JSON,
JSONDecodeError будет вызвано.

Изменено в версии 3.6: Все параметры теперь содержат только ключевые слова.

декодировать ( с )

Вернуть представление Python s (экземпляр str
содержащий документ JSON).

JSONDecodeError будет поднято, если данный документ JSON не
действительный.

raw_decode( с )

Декодировать документ JSON из s ( str , начинающийся с
документ JSON) и вернуть 2-кортеж представления Python
и индекс в s , где документ закончился.

Это можно использовать для декодирования документа JSON из строки, которая может иметь
лишние данные в конце.

class json.JSONEncoder( * , skipkeys=False , sure_ascii=True , check_circular=True , allow_nan=True , sort_keys=False , отступ=нет , разделители= Нет , по умолчанию = Нет )

Расширяемый кодировщик JSON для структур данных Python.

По умолчанию поддерживает следующие объекты и типы:

Питон

JSON

дикт

объект

список, кортеж

массив

ул

строка

int, float, int и производные от float перечисления

номер

Правда

правда

Ложь

ложный

Нет

ноль

Изменено в версии 3. 4: Добавлена ​​поддержка классов Enum, производных от int и float.

Чтобы расширить это, чтобы распознавать другие объекты, создать подкласс и реализовать
метод default() с другим методом, который возвращает сериализуемый объект
для или , если возможно, в противном случае следует вызвать реализацию суперкласса
(поднять Ошибка типа ).

Если skipkeys имеет значение false (по умолчанию), TypeError будет вызвано, когда
попытка закодировать ключи, которые не являются str , int , float
или Нет . Если skipkeys истинно, такие элементы просто пропускаются.

Если обеспечить_ascii истинно (по умолчанию), вывод гарантированно
экранировать все входящие не-ASCII-символы. Если обеспечить_ascii
false, эти символы будут выводиться как есть.

Если check_circular имеет значение true (по умолчанию), то списки, словари и пользовательские
закодированные объекты будут проверяться на циклические ссылки во время кодирования, чтобы
предотвратить бесконечную рекурсию (что вызовет RecursionError ).
В противном случае такой проверки не происходит.

Если allow_nan равно true (по умолчанию), то NaN , Infinity и
-Infinity будет закодирован как таковой. Это поведение не является JSON
соответствует спецификации, но совместим с большинством основанных на JavaScript
кодеры и декодеры. В противном случае будет ValueError для кодирования
такие поплавки.

Если sort_keys равно true (по умолчанию: False ), то вывод словарей
будет отсортирован по ключу; это полезно для регрессионных тестов, чтобы убедиться, что
Сериализации JSON можно сравнивать изо дня в день.

Если отступ является неотрицательным целым числом или строкой, то элементы массива JSON и
члены объекта будут красиво напечатаны с этим уровнем отступа. Уровень отступа
из 0, отрицательный или "" будет вставлять только новые строки. Нет (по умолчанию)
выбирает наиболее компактное представление. Использование положительного целочисленного отступа
отступов столько пробелов на уровень. Если отступ является строкой (например, "\t" ),
эта строка используется для отступа каждого уровня.

Изменено в версии 3.2: Разрешены строки для с отступом в дополнение к целым числам.

Если указано, разделители должны быть (item_separator, key_separator)
кортеж. По умолчанию (', ', ': ') , если отступ равен Нет и
(',', ':') иначе. Чтобы получить наиболее компактное представление JSON,
вы должны указать (',', ':') для устранения пробелов.

Изменено в версии 3.4: Используйте (',', ': ') по умолчанию, если отступ не равен Нет .

Если указано, по умолчанию должна быть функцией, которая вызывается для объектов, которые
иначе не может быть сериализован. Он должен возвращать закодированную версию JSON
объект или поднимите Ошибка типа . Если не указано, TypeError
Поднялся.

Изменено в версии 3.6: Все параметры теперь содержат только ключевые слова.

по умолчанию ( или )

Реализуйте этот метод в подклассе таким образом, чтобы он возвращал сериализуемый
объект для o или вызывает базовую реализацию (чтобы поднять
TypeError ).

Например, для поддержки произвольных итераторов можно реализовать
по умолчанию() вот так:

 по умолчанию (я, о):
   пытаться:
       итерируемый = итер (о)
   кроме TypeError:
       проходить
   еще:
       список возврата (повторяемый)
   # Пусть метод по умолчанию базового класса вызовет TypeError
   вернуть json.JSONEncoder.default (я, о)
 
кодировать ( или )

Возвращает строковое представление структуры данных Python в формате JSON, или . Для
пример:

 >>> json.JSONEncoder().encode({"foo": ["бар", "баз"]})
'{"foo": ["бар", "баз"]}'
 
iterencode ( или )

Закодируйте данный объект, или , и выведите каждое строковое представление как
доступный. Например:

 для чанка в json.JSONEncoder().iterencode(bigobject):
    mysocket.write(чанк)
 

Исключения

исключение json.JSONDecodeError ( msg , doc , pos )

Подкласс ValueError со следующими дополнительными атрибутами:

сообщение

Неформатированное сообщение об ошибке.

документ

Анализируется документ JSON.

поз.

Начальный индекс документа , синтаксический анализ которого завершился неудачно.

Линено

Строка, соответствующая поз. .

столбец

Столбец, соответствующий pos .

Новое в версии 3.5.

Соответствие стандартам и совместимость

Формат JSON указан в RFC 7159 и
ЭКМА-404.
В этом разделе подробно описывается уровень соответствия этого модуля RFC.
Для простоты подклассы JSONEncoder и JSONDecoder и
параметры, кроме явно упомянутых, не учитываются.

Этот модуль строго не соответствует RFC, реализуя некоторые
расширения, которые являются действительным JavaScript, но не действительным JSON. В частности:

  • Принимаются и выводятся бесконечные и числовые значения NaN;

  • Повторяющиеся имена внутри объекта допускаются, и только значение последнего
    используется пара имя-значение.

Поскольку RFC разрешает синтаксическим анализаторам, совместимым с RFC, принимать входные тексты, которые не
RFC-совместимый десериализатор этого модуля технически соответствует RFC в
настройки по умолчанию.

Кодировки символов

RFC требует, чтобы JSON был представлен с использованием UTF-8, UTF-16 или
UTF-32, при этом UTF-8 рекомендуется по умолчанию для максимальной совместимости.

Как разрешено, хотя и не требуется RFC, сериализатор этого модуля устанавливает
sure_ascii=True по умолчанию, что позволяет избежать вывода, чтобы результирующий
строки содержат только символы ASCII.

Кроме параметра sure_ascii , этот модуль определен строго в
условия преобразования между объектами Python и
строк Unicode , и, таким образом, напрямую не адресует
вопрос кодировки символов.

RFC запрещает добавлять метку порядка байтов (BOM) в начало текста JSON,
и сериализатор этого модуля не добавляет спецификацию к своему выводу.
RFC разрешает, но не требует, чтобы десериализаторы JSON игнорировали начальный
BOM на их входе. Десериализатор этого модуля поднимает ЗначениеОшибка
при наличии начальной спецификации.

RFC явно не запрещает строки JSON, содержащие последовательности байтов.
которые не соответствуют допустимым символам Unicode (например, непарные символы UTF-16
суррогаты), но отмечает, что они могут вызвать проблемы совместимости.
По умолчанию этот модуль принимает и выводит (при наличии в исходном
str ) кодовые точки для таких последовательностей.

Бесконечные и числовые значения NaN

RFC не разрешает представление бесконечных или числовых значений NaN.
Несмотря на это, по умолчанию этот модуль принимает и выводит Бесконечность ,
-Infinity и NaN , как если бы они были действительными литеральными значениями числа JSON:

 >>> # Ни один из этих вызовов не вызывает исключение, но результаты недействительны JSON
>>> json.dumps(с плавающей запятой('-inf'))
'-Бесконечность'
>>> json.dumps(float('nan'))
'НаН'
>>> # То же самое при десериализации
>>> json.loads('-Бесконечность')
-инф
>>> json.loads('NaN')
нан
 

В сериализаторе параметр allow_nan можно использовать для изменения этого
поведение. В десериализаторе параметр parse_constant можно использовать для
изменить это поведение.

Повторяющиеся имена внутри объекта

RFC указывает, что имена в объекте JSON должны быть уникальными, но
не указывает, как следует обрабатывать повторяющиеся имена в объектах JSON. К
по умолчанию этот модуль не вызывает исключения; вместо этого он игнорирует все, кроме
последняя пара имя-значение для данного имени:

 >>> странный_json = '{"х": 1, "х": 2, "х": 3}'
>>> json.loads(weird_json)
{'х': 3}
 

Параметр object_pairs_hook можно использовать для изменения этого поведения.

Значения верхнего уровня, не являющиеся объектами, не являющиеся массивами

Старая версия JSON, указанная в устаревшем RFC 4627 , требовала, чтобы
значение верхнего уровня текста JSON должно быть либо объектом JSON, либо массивом
(Python dict или list ) и не может быть нулевым JSON,
логическое, числовое или строковое значение. RFC 7159 снял это ограничение, и
этот модуль не реализует и никогда не реализовывал это ограничение ни в
сериализатор или его десериализатор.

Несмотря на это, для максимальной совместимости вы можете добровольно присоединиться к
к ограничению самостоятельно.

Ограничения реализации

Некоторые реализации десериализатора JSON могут устанавливать ограничения на:

  • размер принимаемых текстов JSON

  • максимальный уровень вложенности объектов и массивов JSON

  • диапазон и точность чисел JSON

  • содержание и максимальная длина строк JSON

Этот модуль не налагает никаких таких ограничений, кроме соответствующих
Сами типы данных Python или сам интерпретатор Python.

При сериализации в JSON помните о любых таких ограничениях в приложениях, которые могут
потребляйте свой JSON. В частности, номера JSON часто бывают
десериализованы в числа двойной точности IEEE 754 и, таким образом, подлежат этому
диапазон представления и ограничения точности. Это особенно актуально
при сериализации Python int значений чрезвычайно большой величины, или
при сериализации экземпляров «экзотических» числовых типов, таких как
десятичный. Десятичный .

Интерфейс командной строки

Исходный код: Lib/json/tool.py


Модуль json.tool предоставляет простой интерфейс командной строки для проверки
и красиво печатать объекты JSON.

Если необязательные аргументы infile и outfile не
указано, sys.stdin и sys.stdout будет использоваться соответственно:

 $ эхо '{"json": "obj"}' | питон-м json.tool
{
    "json": "объект"
}
$ эхо '{1.2:3.4}' | питон-м json.tool
Ожидается имя свойства, заключенное в двойные кавычки: строка 1 столбец 2 (char 1)
 

Изменено в версии 3.5: вывод теперь в том же порядке, что и ввод. Использовать
--sort-keys опция для сортировки вывода словарей
в алфавитном порядке по ключу.

Параметры командной строки

профиль

Файл JSON для проверки или корректной печати:

 $ python -m json.tool mp_films. json
[
    {
        "title": "А теперь кое-что совершенно другое",
        "год": 1971
    },
    {
        "title": "Монти Пайтон и Святой Грааль",
        "год": 1975
    }
]
 

Если infile не указан, читать из sys.stdin .

аутфайл

Записать вывод infile в данный outfile . В противном случае напишите это
на sys.stdout .

—sort-ключи

Сортировка вывода словарей в алфавитном порядке по ключу.

Новое в версии 3.5.

—no-обеспечить-ascii

Отключить экранирование символов, отличных от ASCII, см. json.dumps() для получения дополнительной информации.

Новое в версии 3.9.

—json-линии

Анализировать каждую строку ввода как отдельный объект JSON.

Новое в версии 3.8.

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

Взаимоисключающие опции для управления пробелами.

Новое в версии 3.9.

-ч, —help

Показать справочное сообщение.

Сноски

1

Как отмечено в исправлениях для RFC 7159,
JSON допускает использование букв U+2028 (LINE SEPARATOR) и
U+2029(PARAGRAPH SEPARATOR) символов в строках, тогда как JavaScript
(начиная с ECMAScript Edition 5.1) нет.

— Начало Elm

В разделе «Извлечение данных с помощью GET» мы узнали, как получить простую строку с HTTP-сервера. В настоящее время большинство клиентских приложений ожидают, что серверы будут отправлять данные в формате JSON. В этом разделе мы изменим формат ответа нашего сервера со строкового на JSON и используем различные функции в Elm для преобразования этого JSON в значения Elm.

Создание локального сервера JSON

Локальный HTTP-сервер, который мы создали в предыдущем разделе, также может отправлять JSON. Все, что нам нужно сделать, это структурировать наши данные как JSON вместо обычной строки, например:

.

Но есть способ лучше. Мы можем создать другой сервер, настроенный для обслуживания JSON вместо статических файлов, используя пакет NPM с именем json-server. Идите вперед и установите его глобально, используя параметр -g , чтобы его можно было запустить из любого места в терминале.

 $ npm install json-server -g 

Теперь создайте новый файл с именем old-school.json внутри begin-elm/server .

Добавьте следующий JSON в файл old-school.json .

 {
    "прозвища": ["Крестный отец", "Танк", "Шапочка", "Сыр"]
} 

Давайте запустим сервер JSON, выполнив следующую команду из каталога begin-elm в терминале. Вы можете остановить созданный нами HTTP-сервер в разделе «Извлечение данных с помощью GET», если он все еще работает, нажав 9.}/ привет!
Загрузка сервера/old-school.json
Сделанный
Ресурсы
http://localhost:5019/псевдонимы
Дом
http://локальный: 5019
Введите s + enter в любое время, чтобы создать снимок базы данных.
Смотрю…

Нравится http-server , json-server требует от нас указать файл, из которого будут отдаваться данные. В нашем случае это server/old-school.json . Опция --watch указывает серверу наблюдать за любыми изменениями, внесенными в old-school.json . Если мы не используем эту опцию, нам придется перезапускать сервер каждый раз, когда этот файл изменяется. 9Опция 0018 -p указывает порт. Здесь мы используем другой порт ( 5019 ), чтобы избежать конфликта с сервером, который мы создали в разделе «Извлечение данных с помощью GET», если он все еще работает.

Перейдите по адресу http://localhost:5019/nicknames в браузере. Если вы видите список псевдонимов, как показано ниже, значит, сервер работает должным образом.

 [
  "Крестный отец",
  "Танк",
  "Шапочка",
  "Сыр"
] 

Обратите внимание, что URL-адрес для получения псевдонимов изменился по сравнению с тем, что был раньше в разделе «Извлечение данных с помощью GET»:

  • Новый URL-адрес с json-сервером : http://localhost:5019/псевдонимы
  • Старый URL-адрес с http-сервером : http://localhost:5016/old-school. txt

Со старым URL-адресом мы указывали имя файла, потому что он обслуживал содержимое статического файла. Новый URL указывает, какой ресурс мы хотим получить. Вместо того, чтобы обслуживать все содержимое файла, json-server позволяет нам определять ресурсы, которые являются просто способом назвать часть информации. Добавив следующий JSON в old-school.json , присваиваем имя ников ресурсу ["Крестный отец", "Танк", "Шапочка", "Сыр"] .

 {
    "прозвища": ["Крестный отец", "Танк", "Шапочка", "Сыр"]
} 

Ресурсы могут быть намного сложнее, чем просто список строк. Вот пример, полученный из страницы документации json-server :

 {
  "сообщения": [
    {
      "идентификатор": 1,
      "название": "json-сервер",
      "автор": "типикод"
    },
    {
      "идентификатор": 2,
      "title": "http-сервер",
      "автор": "индексноль"
    }
  ],
  "Комментарии": [
    {
      "идентификатор": 1,
      "тело": "какой-то комментарий",
      "Идентификатор сообщения": 1
    }
  ],
  "профиль": {
    "имя": "типикод"
  }
} 

Приведенный выше JSON определяет три разных ресурса: сообщений , комментариев и профиль . Ресурс может быть либо коллекцией, либо отдельной сущностью. постов и комментариев являются подборками, тогда как профиль представляет собой единое целое. Каждый ресурс имеет уникальное место, откуда мы можем получить к нему доступ.

Эта концепция станет понятнее, если мы попытаемся получить эти ресурсы из браузера. Идите вперед и добавьте вышеуказанный JSON в новый файл с именем 9.0018 db.json в каталоге begin-elm/server . db — это сокращение от базы данных.

Теперь остановите сервер JSON, нажав Ctrl + c , и перезапустите его, чтобы вместо него использовался файл db.json .

 $ json-server --watch server/db.json -p 5019 

Обратите внимание, что в выходных данных перечислены все доступные ресурсы.

 Ресурсы
http://локальный: 5019/сообщений
http://локальный:5019/комментарии
http://локальный: 5019/profile 

json-server фактически создал для нас REST API. Давайте получим ресурс сообщений , загрузив http://localhost:5019/posts в браузере. Ваш вывод должен выглядеть так:

 [
  {
    "идентификатор": 1,
    "название": "json-сервер",
    "автор": "типикод"
  },
  {
    "идентификатор": 2,
    "title": "http-сервер",
    "автор": "индексноль"
  }
] 

posts также является ресурсом, даже если он содержит внутри себя другие ресурсы. Мы можем получить отдельный ресурс внутри публикует , указав id . Если вы загрузите URL-адрес http://localhost:5019/posts/1 в браузере, вы должны увидеть только одно сообщение.

 {
  "идентификатор": 1,
  "название": "json-сервер",
  "автор": "типикод"
} 

Надеюсь, теперь вы понимаете, как работает json-server . Нам действительно не нужно было изучать все это только для того, чтобы вернуть какой-то JSON с нашего сервера. Хорошая новость заключается в том, что все эти знания пригодятся, когда мы будем создавать, обновлять и удалять ресурсы в главе 7, используя POST , PATCH и DELETE методы, определенные в протоколе HTTP.

Получение JSON из приложения Elm

Давайте вернемся к приложению Elm, которое мы написали в разделе «Извлечение данных с помощью GET». В файле HttpExamples.elm , расположенном внутри begin-elm/src , мы получили строку и использовали функцию String.split для извлечения отдельных псевдонимов из этой строки.

Обновление

: Msg -> Model -> (Model, Cmd Msg)
обновить модель сообщения =
    дело сообщение из
        ОтправитьHttpRequest ->
            (модель, getNicknames)
        DataReceived (Ok никнеймыStr) ->
            позволять
                прозвища =
                    String.split "," прозвищаStr
            в
            ( { модель | прозвища = прозвища }, Cmd.none )
        .
        . 

Нам придется переписать часть этой логики, чтобы получать псевдонимы в формате JSON и декодировать их. Остановите сервер JSON, нажав Ctrl + c , если он запущен, и перезапустите его, чтобы использовать файл old-school. json .

 $ json-server --watch server/old-school.json -p 5019 

Первое, что нам нужно изменить в HttpExamples.elm , это URL-адрес.

 URL-адрес: строка
URL =
    "http://localhost:5019/nicknames" 

Процесс получения JSON с сервера ничем не отличается от получения строки. Хотя мы извлекаем JSON, базовый формат данных, отправляемый сервером, по-прежнему имеет формат 9.0062 необработанная строка . Если это так, то как клиентское приложение узнает, как правильно анализировать ответ, если он всегда приходит в виде строки? Он не может использовать ту же технику для извлечения псевдонимов из строки, а также JSON.

К счастью, сервер указывает, в каком формате должен интерпретироваться ответ, используя заголовок Content-Type . Для JSON сервер использует application/json в качестве значения заголовка Content-Type . Принимая во внимание, что для строки используется текстовый/обычный .

Декодирование JSON

Elm предоставляет пакет под названием elm/json , который включает модули для кодирования и декодирования значений JSON. Мы установили этот пакет в разделе Type System, выполнив следующую команду.

 $ elm install elm/json 

Если он еще не установлен, запустите указанную выше команду из каталога begin-elm в терминале. Не запускайте его из того же окна терминала, где мы запускали json-сервер ранее. Создайте новый. Когда elm install запросит ваше разрешение, ответьте y . После этого импортируйте модуль Json.Decode в HttpExamples.elm .

 модуль HttpExamples выставление (основной)
импортировать Json.Decode, раскрывающий (декодер, ошибка (..), decodeString, список, строка)
.
. 

Далее нам нужно определить декодер, который умеет преобразовывать JSON в значения Elm. Добавьте следующий код над обновлением . функция в HttpExamples.elm .

 псевдонимовDecoder : Декодер (строка списка)
прозвищаДекодер =
    list string 

Выражение list string создает декодер, который знает, как преобразовать массив JSON в список строк Elm. Звучит запутанно, не так ли? Давайте поэкспериментируем с этим выражением, чтобы лучше понять его. Запустите elm repl из каталога begin-elm в терминале и введите следующий код.

 > импортировать Json.Decode, раскрывающий (..)
> список
<функция> : Декодер a -> Декодер (список a) 

Посмотрите, что мы получили, когда ввели всего list . Вывод предполагает, что список — это функция, которая принимает декодер и возвращает другой декодер. Давайте посмотрим, что мы получим, когда введем строку .

 > строка
 : Строка декодера 

Примечание: Мы смогли ввести список и строку в repl без префикса имени модуля, потому что мы выставили все при импорте Json. Decode .

Декодер строк

string — это декодер, который умеет переводить строку JSON в строку Elm. Вот пример:

 > строка decodeString "\"Шапочка\""
Хорошо "Шапочка": Строка ошибки результата 

Мы использовали два набора двойных кавычек, чтобы указать, что "\"Шапочка\"" содержит строку JSON в необработанной строке. 9Строка 0018 сама по себе не декодирует JSON. Это как рецепт для расшифровки. Функция decodeString выполняет фактическое декодирование. Сначала он преобразует необработанную строку в JSON, а затем применяет декодер строки для преобразования этого JSON в строку Elm.

На следующей диаграмме подробно поясняется сигнатура типа decodeString .

Json.Decode.Error

При сбое декодирования decodeString возвращает значение типа Error . Вот пример:

 > строка decodeString "42"
Err (Отказ ("Ожидание STRING") <внутренние>)
    : Result Error String 

Примечание: Хотя мы заключили 42 в двойные кавычки, это не считается строкой JSON. Чтобы это была правильная строка JSON, нам нужно добавить еще один набор двойных кавычек, например: "\"42\"" .

Тип Ошибка определен в Модуль Json.Decode следующим образом:

 Тип Ошибка
    = Ошибка строки поля
    | Ошибка индекса
    | OneOf (ошибка списка)
    | Ошибка Строковое значение 

Это рекурсивный тип. Ранее в разделе «Система типов» мы создали собственный рекурсивный тип:

.

 введите MyList a
    = Пусто
    | Node a (MyList a) 

Вы заметили сходство? Оба типа предоставляют по крайней мере один конструктор данных, который не является рекурсивным. Без этих конструкторов данных мы получили бы бесконечное значение. Вот пример:

 Узел 16 (Узел 5 (Узел 31 (Узел 9) (Узел 18 (Узел 7 (Узел 26 (...))))))) 

Но почему тип Ошибка должен быть таким сложным? Почему это не может быть просто строкой? На самом деле до Elm 0. 19 это была просто строка. Создав более сложный тип, авторы пакета elm/json дали нам возможность создать сложную визуализацию проблемы, возникшей в процессе декодирования. Например, мы можем показать весь объект JSON и выделить часть, вызвавшую ошибку, красным цветом.

Мы не будем вдаваться в подробности того, как это сделать, но вы можете изучить это самостоятельно после прочтения разделов «Декодирование JSON — часть 1» и «Декодирование JSON — часть 2».

Другие примитивные декодеры

Elm предоставляет три других декодера для преобразования примитивных типов JSON в значения Elm: int , float и bool . Вот несколько примеров, показывающих их в действии:

 > decodeString целое число "9"
Ok 9: Ошибка результата Int
> decodeString int "2.5"
Err (Ошибка ("Ожидание INT") <внутренние>)
    : Результат Ошибка Цел.
> decodeString с плавающей запятой "2.5"
Хорошо 2.5: Ошибка результата с плавающей запятой
> decodeString bool "истина"
Ok True : Результат Ошибка Bool
> decodeString логическое значение "false"
OK False : Результат Ошибка Bool
> decodeString bool "87"
Err (Ошибка ("Ожидание BOOL") <внутренние>)
    : Результат Ошибка Bool 
Дешифраторы строительных комплексов

JSON поддерживает следующие типы данных:

  • string — Строка должна быть заключена в двойные кавычки и очень похожа на строку Elm.

  • число — Число должно быть целым числом или вещественным числом.

  • логическое значение — логическое значение должно быть либо true , либо false .

  • array — Массив может содержать любые другие значения JSON, включая сами массивы.

  • объект — Объект состоит из пар ключ-значение.

  • null null используется для обозначения отсутствия значения.

Мы уже знаем, как декодировать строки, числа и логические значения. Чтобы декодировать остальное, нам нужно создать более сложные декодеры, используя примитивные декодеры в качестве строительных блоков. Начнем с массива JSON.

Декодер списка

Ранее мы создали декодер для перевода массива строк JSON в список строк Elm.

 псевдонимовDecoder : Декодер (строка списка)
прозвищаДекодер =
    list string 

Мы можем декодировать массив псевдонимов, используя list string следующим образом:

 > псевдонимJson = "[\"Крестный отец\", \"Танк\", \"Шапочка\", \"Сыр\"]"
"[\"Крестный отец\", \"Танк\", \"Шапочка\", \"Сыр\"]" : String
> decodeString (строка списка) NickJson
Хорошо [«Крестный отец», «Танк», «Шапочка», «Сыр»]
    : Ошибка результата (строка списка) 

Точно так же мы можем декодировать массив целых чисел JSON (или чисел с плавающей запятой) следующим образом:

 > decodeString (список целых чисел) "[1, 2, 3]"
Ok [1,2,3]: ошибка результата (List Int)
> decodeString (список с плавающей запятой) "[1. 5, 2.5]"
Хорошо [1.5,2.5]: Ошибка результата (список с плавающей запятой) 

список сам по себе не является декодером. Это функция, которая берет декодер и создает более сложный декодер. Вот как выглядит его подпись типа:

 список : Декодер a -> Декодер (список a) 

Если мы хотим декодировать JSON, содержащий массив массивов, мы можем сделать это с помощью список декодеров несколько раз, например:

 > decodeString (список (список int)) "[[1, 2], [4, 5]]"
Хорошо [[1,2],[4,5]]
    : Result Error (List (List Int)) 

Глубина вложенности не ограничена. Важно помнить, что Elm требует, чтобы все элементы в списке List были одного типа. Поэтому мы не можем декодировать массив JSON с разными типами.

 > decodeString (список (список int)) "[[1, 2], [3.5, 4.5]]"
Err (Индекс 1 (Индекс 0 (Сбой ("Ожидание INT") <внутренние>)))
    : Ошибка результата (Список (Список целых)) 
Замена

String. split на ников Декодер

Теперь, когда мы поняли, как работают декодеры list и string , давайте вернемся к HttpExamples.elm и заменим String.split на псевдонимовDecoder в DataReceived ( Ок никнеймыStr) -> ветка внутри обновление .

Обновление

: Msg -> Model -> (Model, Cmd Msg)
обновить модель сообщения =
    дело сообщение из
        .
        .
        DataReceived (окей никнеймыJson) ->
            case decodeString псевдонимыДекодерные никнеймыJson of
                Ок никнеймы ->
                    ( { модель | прозвища = прозвища }, Cmd.none )
                Ошибка ошибки ->
                    ( {модель | errorMessage = ошибка handleJsonError }
                    , Cmd.none
                    )
        .
        . 

Мы переименовали полезную нагрузку с никнеймовStr на никнеймовJson и заменили выражение let на case . В отличие от String.split , decodeString возвращает результат . Вот почему мы использовали выражение case для извлечения никнеймов из Ok . Если декодирование не удается, для извлечения сообщения об ошибке используется функция handleJsonError . Давайте добавим эту функцию ниже update .

 handleJsonError : Json.Decode.Error -> Возможно, строка
ошибка handleJsonError =
    случайная ошибка
        Ошибка errorMessage _ ->
            Просто сообщение об ошибке
        _ ->
            Просто «Ошибка: неверный JSON» 

Нас интересует только конструктор данных Failure , поскольку именно в нем находится сообщение об ошибке. Второй параметр Failure — это значение JSON, вызвавшее сбой. Поскольку мы не используем этот параметр, мы заменили его на 9.0018 _ .

Запустите elm Reactor из каталога begin-elm в терминале, если он еще не запущен, и перейдите по этому URL-адресу в браузере: http://localhost:8000/src/HttpExamples. elm . Нажмите кнопку Получить данные с сервера , и вы должны увидеть тот же список псевдонимов, который мы видели в разделе Получение данных с помощью GET.

В отличие от http-server , json-server автоматически включает совместное использование ресурсов между источниками (CORS). Вот почему мы не получили В запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Ошибка при получении никнеймов.

Замена

expectString на expectJson

Давайте рассмотрим процесс, который мы прошли, чтобы получить и расшифровать псевдонимы JSON.

Шаг 1: Создайте команду, используя Http.get . Укажите, какой URL использовать, и сообщите среде выполнения Elm, что мы ожидаем, что ответ будет строкой.

 getNicknames : Cmd Msg
получитьникнеймы =
    http.получить
        { URL-адрес = URL-адрес
        , ожидать = Http. expectString DataReceived
        } 

Шаг 2: Среда выполнения запускает команду.

Шаг 3: Среда выполнения отправляет сообщение DataReceived функции update .

  • Шаг 3.1: Включите JSON в качестве полезной нагрузки, если запрос на получение псевдонимов выполнен успешно.
  • Шаг 3.2: Включить ошибку типа Http.Error в качестве полезной нагрузки, если запрос на получение псевдонимов не удается.

Шаг 4: Декодировать JSON внутри DataReceived (Ok NicksJson) -> ветвь обновить функцию .

  • Шаг 4.1: Если декодирование прошло успешно, обновите свойство псевдонимов в модели.
  • Шаг 4.2: При сбое декодирования обновите свойство errorMessage в модели.

Мы можем немного упростить этот процесс, используя функцию Http. expectJson вместо Http.expectString в getNicknames . Вот как выглядит упрощенный процесс:

Шаг 1: Создайте команду, используя Http.get . Укажите, какой URL использовать, и сообщите среде выполнения Elm, что мы ожидаем ответ в формате JSON.

 getNicknames : Cmd Msg
получитьникнеймы =
    http.получить
        { URL-адрес = URL-адрес
        , expect = Http.expectJson DataReceived никнеймовDecoder
        } 

Шаг 2: Среда выполнения запускает команду.

Шаг 3: Среда выполнения отправляет 9Сообщение 0018 DataReceived для функции обновления .

  • Шаг 3.1: Включить декодированные псевдонимы в качестве полезной нагрузки, если запрос на получение JSON и декодирование выполняются успешно.

  • Шаг 3.2: Включите ошибку типа Http.Error в качестве полезной нагрузки в случае сбоя запроса на получение JSON или декодирования.

Нам вообще не нужен шаг 4 если мы используем Http.expectJson . Извлечение и декодирование JSON происходит за один раз. На следующей диаграмме показано, чем отличаются Http.expectString и Http.expectJson .

Замените Http.expectString на Http.expectJson в getNicknames , как показано выше, если вы еще этого не сделали. Далее нам нужно изменить ветку DataReceived (Ok NicknamesJson) -> в update .

Обновление

: Msg -> Model -> (Model, Cmd Msg)
обновить модель сообщения =
    дело сообщение из
        .
        .
        DataReceived (окей ники) ->
            ( { модель | прозвища = прозвища }, Cmd.none )
        Получено данных (ошибка httpError) ->
            ... 

Http.expectJson действительно упростил эту ветку. Нам больше не нужно вручную декодировать JSON. Это происходит автоматически за кулисами. Если декодирование прошло успешно, полезной нагрузкой будет список Elm, который мы можем назначить непосредственно в поле псевдонимов в нашей модели. Это означает, что нам нужно изменить определение сообщения DataReceived , чтобы принять List String вместо просто String .

 тип Сообщение
    = ОтправитьHttpRequest
    | DataReceived (результат Http.Error (строка списка)) 

Нам вообще не нужно изменять ветку DataReceived (Err httpError) -> в update . В случае сбоя декодирования будет возвращена ошибка Http.BadBody , которую мы уже обрабатываем в buildErrorMessage . Наконец, удалите функцию handleJsonError . Нам это больше не нужно.

Обновите страницу по адресу http://localhost:8000/src/HttpExamples.elm и нажмите кнопку Получить данные с сервера . Вы должны еще раз увидеть список никнеймов.

Резюме

В этом разделе мы узнали, как создать локальный сервер, настроенный для обслуживания JSON. Мы получили некоторый JSON с этого сервера и преобразовали его в значения Elm с помощью декодера. Мы также узнали, как упростить общий процесс извлечения и декодирования JSON с помощью функции Http.expectJson вместо Http.expectString . На приведенной ниже диаграмме показано, что общее взаимодействие между средой выполнения Elm и нашим кодом не сильно изменилось по сравнению с разделом «Извлечение данных с помощью GET».

В следующем разделе мы узнаем, как декодировать более сложный JSON. Вот весь код из HttpExamples.elm на данный момент:

 модуль HttpExamples выставление (основной)
импортировать браузер
импортировать HTML-разоблачение (..)
импорт Html.Events (onClick)
импорт HTTP
импортировать Json.Decode, раскрывающий (декодер, ошибка (. .), decodeString, список, строка)
введите псевдоним Модель =
{ прозвища : строка списка
, errorMessage : Возможно Строка
}
представление: Модель -> Html Msg
модель просмотра =
раздел []
[кнопка [ onClick SendHttpRequest ]
[ текст "Получить данные с сервера" ]
, модель viewNicknamesOrError
]
viewNicknamesOrError: Модель -> Html Msg
модель viewNicknamesOrError =
case model.errorMessage of
Просто сообщение ->
сообщение об ошибке просмотра
Ничего ->
viewNicknames model.nicknames
viewError: строка -> Html-сообщение
viewError errorMessage =
позволять
ошибкаЗаголовок =
"В настоящее время не удалось получить псевдонимы."
в
раздел []
[ h4 [] [текстовая ошибкаЗаголовок ]
, текст ("Ошибка: " ++ errorMessage)
]
viewNicknames : Строка списка -> Html Msg
никнеймы viewNicknames =
раздел []
[ h4 [] [текст "Главные герои старой школы" ]
, ul [] (List. map viewNickname никнеймы)
]
viewNickname : String -> Html Msg
никнейм viewNickname =
li [] [текстовое имя]
введите сообщение
= ОтправитьHttpRequest
| DataReceived (результат Http.Error (строка списка))
URL-адрес: строка
URL =
"http://локальный:5019/прозвища"
getNicknames : Cmd Msg
получитьникнеймы =
http.получить
{ URL-адрес = URL-адрес
, expect = Http.expectJson DataReceived никнеймовDecoder
}
никнеймыДекодер : Декодер (строка списка)
прозвищаДекодер =
строка списка
обновление: Msg -> Model -> (Model, Cmd Msg)
обновить модель сообщения =
дело сообщение из
ОтправитьHttpRequest ->
(модель, getNicknames)
DataReceived (окей ники) ->
( { модель | прозвища = прозвища }, Cmd.none )
Получено данных (ошибка httpError) ->
( { модель
| errorMessage = Просто (buildErrorMessage httpError)
}
, Cmd.none
)
buildErrorMessage : Http.