Какой минимальный допустимый JSON?


175

Я внимательно прочитал описание JSON http://json.org/, но не уверен, что знаю ответ на простой вопрос. Какие строки являются минимально возможным допустимым JSON?

  • "string" допустимая строка JSON?
  • 42 допустимо ли простое число JSON?
  • true логическое значение является допустимым JSON?
  • {} пустой объект является допустимым JSON?
  • [] пустой массив является допустимым JSON?

12
Тестирование на jsonlint.com , последние два действительны, остальные нет.
Ironcito

1
некоторые парсеры JSON ожидают массив или объект. Они жалуются только на число или строку.
Аконсу

3
На данный момент, они действительны
Брайан Колавито


краткий ответ - {}
Тукарам Бхосале

Ответы:


157

На момент написания статьи JSON был описан исключительно в RFC4627 . Он описывает (в начале «2») текст JSON как сериализованный объект или массив.

Это означает, что только {} и []являются действительными, полные строки JSON в синтаксических анализаторах и строковых преобразователях, которые соответствуют этому стандарту.

Однако , введение ECMA-404 меняет это, и обновленный совет можно прочитать здесь . Я также написал сообщение в блоге по проблеме.


Однако, чтобы еще больше запутать этот вопрос, JSONобъект (например, JSON.parse()и JSON.stringify()), доступный в веб-браузерах, ситуацию , стандартизирован в ES5 , и это четко определяет приемлемые тексты JSON, например, так:

Формат обмена JSON, используемый в этой спецификации, в точности соответствует RFC 4627 с двумя исключениями:

  • JSONText верхнего уровня для грамматики JSON ECMAScript может состоять из любого JSONValue, а не быть JSONObject или JSONArray, как указано в RFC 4627.

  • пропущено

Это будет означать, что все значения JSON (включая строки, нули и числа) принимаются объектом JSON, даже если объект JSON технически соответствует RFC 4627.

Обратите внимание, что вы могли бы поэтому преобразовать число в соответствующий браузер через JSON.stringify(5), который был бы отклонен другим синтаксическим анализатором, который соответствует RFC4627, но у которого нет определенного исключения, перечисленного выше. Например, может показаться , что Ruby является одним из таких примеров, который принимает в качестве корневого объекта только объекты и массивы . PHP, с другой стороны, специально добавляет исключение, что «он также будет кодировать и декодировать скалярные типы и NULL».


@amdorra: Можете ли вы быть более конкретным, где вы видите это?
Мэтт

5
JSON не является существительным, поэтому «JSON» не имеет смысла. Любое «значение JSON» является «значением JSON», но анализаторы часто ожидают «текст JSON», как определено в этом RFC.
IMSoP

2
мой плохой, я удалю свой ответ тогда
Амдорра

1
@jmoreno Не могли бы вы уточнить свой комментарий? Вы говорите true, falseили nullодин действительный текст JSON? Не могли бы вы привести источник, поскольку это противоречит большинству других ответов / комментариев здесь?
Лоуренс Джонстон

2
@jmoreno: Конечно, цитата из раздела 2 «Текст JSON - это сериализованный объект или массив». Противостоит этому? JSON Lint также не считает недействительным массив или объект. Споры о том, является ли строка допустимым литералом JSON, не обсуждаются; все кончено, допустима ли строка сама по себе.
Мэтт

42

В Интернете есть как минимум четыре документа, которые можно считать стандартами JSON. RFCs, на которые все ссылаются, описывают тип пантомимы application/json. Вот что каждый должен сказать о значениях верхнего уровня и о том, разрешено ли что-либо кроме объекта или массива наверху:

RFC-4627 : Нет.

Текст JSON - это последовательность токенов. Набор токенов включает шесть структурных символов, строки, числа и три литеральных имени.

Текст JSON - это сериализованный объект или массив.

JSON-текст = объект / массив

Обратите внимание, что RFC-4627 был помечен как «информационный», а не «предлагаемый стандарт», и что он устарел в RFC-7159 , который, в свою очередь, устарел в RFC-8259.

RFC-8259 : да.

Текст JSON - это последовательность токенов. Набор токенов включает шесть структурных символов, строки, числа и три литеральных имени.

Текст JSON является сериализованным значением. Обратите внимание, что некоторые предыдущие спецификации JSON ограничивали текст JSON объектом или массивом. Реализации, которые генерируют только те объекты или массивы, для которых требуется текст JSON, будут совместимы в том смысле, что все реализации примут их как соответствующие тексты JSON.

JSON-текст = значение ws ws

RFC-8259 датирован декабрем 2017 года и имеет пометку «ИНТЕРНЕТ СТАНДАРТ».

ECMA-262 : да.

Синтаксическая грамматика JSON определяет допустимый текст JSON в терминах токенов, определенных лексической грамматикой JSON. Целью грамматики является JSONText.

Синтаксис JSONText:

JSONValue

JSONValue:

JSONNullLiteral

JSONBooleanLiteral

JSONObject

JSONArray

JSONString

JSONNumber

ECMA-404 : да.

Текст JSON - это последовательность токенов, сформированная из кодовых точек Unicode, которая соответствует грамматике значений JSON. Набор токенов включает в себя шесть структурных токенов, строки, числа и три токена буквальных имен.


10

Согласно старому определению в RFC 4627 (которое было отменено в марте 2014 года RFC 7159), все они были действительными «значениями JSON», но только последние два составляли полный «текст JSON»:

Текст JSON - это сериализованный объект или массив.

В зависимости от используемого парсера, одиночные «значения JSON» могут быть приняты в любом случае. Например (придерживаясь терминологии «значение JSON» и «текст JSON»):

  • JSON.parse()функция в настоящее время стандартизировано в современных браузерах принимает любое «JSON значение»
  • функция PHP json_decodeбыла введена в версии 5.2.0, принимающей только весь «текст JSON», но была исправлена, чтобы принимать любое «значение JSON» в версии 5.2.1
  • Python's json.loadsпринимает любое «значение JSON» в соответствии с примерами на этой странице руководства
  • валидатор на http://jsonlint.com ожидает полный «текст JSON»
  • модуль Ruby JSON будет принимать только полный текст JSON (по крайней мере, согласно комментариям на этой странице руководства )

Различие немного похоже на различие между «XML-документом» и «XML-фрагментом», хотя технически <foo />это правильно сформированный XML-документ (лучше было бы записать его <?xml version="1.0" ?><foo />, но, как указано в комментариях, <?xmlобъявление технически необязательно ).


Сравнение XML может быть неуместным, поскольку документ XML полностью допустим без необязательного объявления XML. См. Рекомендацию по XML на w3.org/TR/xml/#sec-well-formed
Гюнтер,

@ Гюнтер Ах, да, я забыл, что это технически необязательно, хотя очень рекомендуется.
IMSoP

@Gunther: придирка: <foo />это правильно сформированный XML-документ, но недействительный . (Но то же самое относится и к <?xml version="1.0" ?><foo />.)
ruakh

@ruakh Интересно, что определение здесь подразумевает, что XML может быть «действительным» только для DTD, что означает, что очень мало XML-документов, так как DTD очень редко пишутся и объявляются на практике (по сравнению с форматами определения схемы, такими как XSD или RelaxNG) , Я проверял, потому что, если вы могли бы быть действительным по отношению к внешней схеме, не ссылаясь на нее, то <foo /> может быть или не быть действительным по отношению к конкретной схеме , но это не то, что этот стандарт заявляет.
IMSoP

4

Спецификация ecma может быть полезна для справки:

http://www.ecma-international.org/ecma-262/5.1/

Функция анализа анализирует текст JSON (строка в формате JSON) и создает значение ECMAScript. Формат JSON является ограниченной формой литерала ECMAScript. Объекты JSON реализованы как объекты ECMAScript. Массивы JSON реализованы как массивы ECMAScript. Строки JSON, числа, логические значения и значения NULL реализуются как строки ECMAScript, числа, логические значения и значения NULL. JSON использует более ограниченный набор символов пробела, чем WhiteSpace, и позволяет кодовым точкам Unicode U + 2028 и U + 2029 напрямую появляться в литералах JSONString без использования escape-последовательности. Процесс синтаксического анализа аналогичен 11.1.4 и 11.1.5 и ограничен грамматикой JSON.

JSON.parse("string"); // SyntaxError: Unexpected token s
JSON.parse(43); // 43
JSON.parse("43"); // 43
JSON.parse(true); // true
JSON.parse("true"); // true
JSON.parse(false);
JSON.parse("false");
JSON.parse("trueee"); // SyntaxError: Unexpected token e
JSON.parse("{}"); // {}
JSON.parse("[]"); // []

4
Хотя это полезная ссылка, это спецификация конкретного синтаксического анализатора JSON (который определен в стандарте ECMAScript), но не для самого формата. json.org прямо заявляет, что JSON «полностью независим от языка», поэтому нет единственного правильного парсера.
IMSoP

1
JavaScript / ECMAScipt является источником вдохновения для JSON и его пользователя, но не является его «домом». JSON был получен из литеральной нотации объекта в (всех более ранних версиях) ECMAScript, но не идентичен ей. Затем эта JSON.parseфункция была добавлена ​​в более поздние версии стандарта ECMAScript, основанного на грамматике Крокфорда и RFC.
IMSoP

4
Вы должны сделатьJSON.parse("\"string\"");
ericbn

4

JSON означает JavaScript Object Notation. Только {}и []определите объект Javascript. Другие примеры являются литералами значений. В Javascript есть типы объектов для работы с этими значениями, но выражение "string"представляет собой представление исходного кода буквального значения, а не объекта.

Имейте в виду, что JSON не является Javascript. Это нотация, которая представляет данные. Он имеет очень простую и ограниченную структуру. Данные JSON структурированы с использованием {},:[]символов. Вы можете использовать только литеральные значения внутри этой структуры.

Для сервера вполне допустимо отвечать либо описанием объекта, либо литеральным значением. Все парсеры JSON должны обрабатываться только для обработки буквального значения, но только для одного значения. JSON может представлять только один объект одновременно. Таким образом, чтобы сервер возвращал более одного значения, он должен был бы структурировать его как объект или массив.


1
Я думаю, что подход к ответу с этой стороны более запутывает, чем поясняет: происхождение имени не имеет отношения к деталям стандарта, а типы, доступные в JavaScript, могут быть источником вдохновения для типов в JSON, но нет никаких требований что они совпадают. Введение в json.org проясняет это: «JSON - это текстовый формат, полностью независимый от языка»
IMSoP

@IMSoP Я полностью согласен. Я смешал типы Javascript с JSON, и это не правильно. Я обновлю свой ответ.
Reactgular

2

Да, да, да, да и да. Все они являются допустимыми литералами значения JSON.

Однако официальный RFC 4627 гласит:

Текст JSON - это сериализованный объект или массив.

Таким образом, весь «файл» должен состоять из объекта или массива в качестве внешней структуры, которая, конечно, может быть пустой. Тем не менее, многие анализаторы JSON также принимают примитивные значения для ввода.


-1
var x;
JSON.stringify(x); // will output "{}"

Таким образом, ваш ответ, "{}"который обозначает пустой объект.


FWIW, в Chrome это дает undefined, а не "{}" `
Мэтт

-2

Просто следуйте железнодорожным схемам, приведенным на странице json.org . [] и {} - минимально возможные допустимые объекты JSON. Таким образом, ответ [] и {}.


3
Это не ФШМ, это грамматика. И это, кажется, не указывает, какое производство является правилом запуска. Если бы стартовые правила были arrayи objectвы были бы правы, но разумно ожидать, valueчто будет старт.

Выглядит довольно просто для меня, хотя. Дуглас Крокфорд называет их так, и мы всегда начинаем слева и следуем по следам направо. Самый маленький трек дает минимальный допустимый JSON.
Хриши

2
Я не возражаю против вашей интерпретации какого-либо конкретного правила грамматики, а потому, что вы выбрали два правила и предполагаете, что одно можно начать только с этих, а не с других. Если вы посмотрите на valuesправила , вместо (или в дополнение к нему ) arrayи objectправила, то автономные номера и строки действительный JSON документ.

-1. Во-первых, как указывает @delnan, ничто в диаграммах на json.org не предполагает, что полный текст JSON должен быть объектом или массивом; вы выбрали эти два произвольно, не основываясь ни на чем на json.org. Во-вторых, придирчивость к терминологии: []хотя действительный текст JSON для каждой спецификации, который когда-либо имел мнение по этому вопросу, не является «действительным объектом JSON», поскольку это не объект JSON. «Объект» в JSON конкретно относится к {}нотации; Массивы JSON не являются объектами JSON.
Марк Амери
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.