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


174

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

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

12
Тестуючи на jsonlint.com , останні два є дійсними, інші - ні.
ironcito

1
деякі JSON-аналізатори очікують масив або об'єкт. Вони скаржаться на просто число чи рядок.
akonsu

3
На сьогоднішній день вони дійсні
Брайан Колавіто


коротка відповідь - {}
Tukaram Bhosale

Відповіді:


156

На момент написання повідомлення 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. Всі посилання на RFC описують тип mime application/json. Ось що кожен повинен сказати про значення найвищого рівня та чи дозволено щось інше, ніж об’єкт чи масив у верхній частині:

RFC-4627 : Ні.

Текст JSON - це послідовність лексем. Набір лексем включає шість структурних символів, рядків, цифр та три буквальних імена.

Текст JSON - це серіалізований об'єкт або масив.

JSON-text = об'єкт / масив

Зауважимо, що RFC-4627 був позначений "інформаційним" на відміну від "запропонованого стандарту", і що він застарів RFC-7159 , який, в свою чергу, застарів RFC-8259.

RFC-8259 : Так.

Текст JSON - це послідовність лексем. Набір лексем включає шість структурних символів, рядків, цифр та три буквальних імена.

Текст JSON - це серіалізоване значення. Зауважте, що деякі попередні технічні характеристики JSON обмежували текст JSON об’єктом чи масивом. Реалізації, які генерують лише об'єкти або масиви, де викликається текст JSON, будуть сумісними в тому сенсі, що всі реалізації приймуть їх як відповідні тексти JSON.

JSON-text = 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 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
Гюнтер

@Gunther Ага, так, я забув, що це технічно необов'язково, хоча дуже рекомендується.
IMSoP

@Gunther: Nitpick: <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 реалізуються як рядки ECMAScript, Numbers, Booleans та null. JSON використовує більш обмежений набір символів пробілу, ніж WhiteSpace, і дозволяє кодові точки Unicode U + 2028 і U + 2029 безпосередньо з'являтися в літералах JSONString, не використовуючи послідовність відходу. Процес розбору аналогічний 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, і це невірно. Я оновлю свою відповідь.
Реакційний

2

Так, так, так, так і так. Усі вони є дійсними літералами значення JSON.

Однак офіційний документ RFC 4627 зазначає:

Текст JSON - це серіалізований об'єкт або масив.

Отже, цілий "файл" повинен складатися з об'єкта або масиву як самої зовнішньої структури, яка, звичайно, може бути порожньою. Однак багато JSON-аналізатори також приймають примітивні значення для введення.


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

Тож ваша відповідь така, "{}"що позначає порожній об’єкт.


FWIW, У Chrome це дає undefined, а не "{}" `
Метт

-2

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


3
Це не FSM, це граматика. І це, схоже, не вказує, яке виробництво є правилом початку. Якби правила старту були 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.