у JSON, чому кожне ім'я цитується?


91

Специфікація JSON говорить, що JSON - це об’єкт або масив. У випадку з об'єктом

Структура об’єкта представлена ​​у вигляді пари фігурних дужок, що оточують нуль або більше пар імен / значень (або членів). Ім'я - це рядок. ...

А пізніше, специфікація говорить, що рядок оточений лапками.

Чому?

Таким чином,

{"Property1":"Value1","Property2":18}

і ні

{Property1:"Value1",Property2:18}

Питання 1 : чому б не дозволити імені в парах ім’я / значення бути ідентифікаторами без котирувань?


Запитання 2 : Чи існує семантична різниця між двома поданими вище поданнями при оцінці в Javascript?


1
@Bruno: Ви могли б говорити про XML так само ... і, на жаль, деякі там, можливо, намагаються використовувати XML як мову програмування ...
Mike DeSimone

2
+1 ... це, здається, своєрідне протиріччя .... "з лапками" робить його стандартним JSON, але не буде працювати з ним eval()(тобто javascript).
skaffman

2
@bruno, ні. якщо його розширити, він стає "у нотації об'єктів Javascript", що нормально
Дейв Арчер

2
@skaffman - Він буде працювати, коли буде видалено в JavaScript.
Квентін

1
@Bruno - JSON - це формат даних. "У форматі JSON" означає - із даними, відформатованими відповідно до специфікації.
Cheeso

Відповіді:


57

Питання 1: чому б не дозволити імені в парах ім’я / значення бути ідентифікаторами без котирувань?

Філософія дизайну JSON - "Нехай це буде просто"

"Цитувати імена з "" набагато простіше, ніж "Ви можете цитувати імена з "або, 'але не обов’язково, якщо вони не містять певних символів (або комбінацій символів, які могли б зробити це ключовим словом) і, 'або, "можливо, доведеться цитувати на якому розділювачі ви вибрали " .

Запитання 2: Чи існує семантична різниця між двома поданими вище поданнями при оцінці в Javascript?

Ні. У JavaScript вони однакові.


3
Ні, це не правильно. CMS має правильну відповідь. Ця відповідь є лише приємним побічним ефектом справжньої причини. Окрім того, що це простіше пояснити, простіше написати парсер, оскільки ви можете повторно використовувати правила синтаксичного аналізу для рядків в ідентифікаторах.
Бретон,

і крім цього, є невелика семантична різниця в тому, що якщо ідентифікатор виявляється зарезервованим словом, він інтерпретується як це слово, а не як ідентифікатор.
Бретон,

2
+1 на відповідь CMS, це правильно. Подвійні лапки не є умовою коду, але ви хочете уникати зарезервованих слів як ключів в об'єкті. Наприклад: {property1: "abc", this: "def"} НЕПРАВИЛЬНИЙ (це зарезервоване ключове слово)
Sorin Mocanu

Питання 2 : Невелика різниця в JavaScript , при використанні JSON.parseфункції: JSON.parse('{"a":1}') добре працює , чому JSON.parse('{a:1}')буде викликати виключення .
nhnghia

@nhnghia - Питання 2 стосується оцінки вихідного коду як JavaScript , а не JSON. JSON.parseє синтаксичним аналізатором JSON, реалізованим в JavaScript, це не парсер JavaScript.
Квентін,

134

Я залишаю цитату з презентації, яку Дуглас Крокфорд (творець стандарту JSON) провів для Yahoo.

Він розповідає про те, як він виявив JSON, і серед іншого, чому він вирішив використовувати цитовані ключі :

.... Це було тоді, коли ми виявили проблему імен без котирувань. Виявляється, ECMA Script 3 має політику зарезервованих слів. Зарезервовані слова потрібно цитувати у ключовій позиції, що насправді є неприємністю. Коли я дійшов до того, щоб сформулювати це в стандарт, я не хотів вносити всі зарезервовані слова в стандарт, тому що це виглядало б по-справжньому дурним.

У той час я намагався переконати людей: так, ви можете писати програми на JavaScript, це насправді буде працювати і це гарна мова. Тоді я не хотів сказати одночасно: і подивіться на цю справді дурну річ, яку вони зробили! Тому я вирішив, натомість давайте просто цитувати ключі.
Таким чином, ми не повинні нікому говорити про те, наскільки це зловмисно.

Ось чому донині ключі цитуються в JSON.

Ви можете знайти повне відео та стенограму тут .


Мммм ... творець стандарту JSON ?! Я вважаю, що це завищення. JSON - це об’єктна нотація JavaScript і походить від специфікації Javascript (ECMA).
Sorin Mocanu

42
@Sorin: Не плутайте JSON з літералами об’єктів JavaScript. JSON - це мовно-агностичний формат обміну даними, запропонований Крокфордом 2006 р. ( Tools.ietf.org/html/rfc4627 ), його граматика відрізняється від літералів об’єктів JavaScript ( bclary.com/2004/11/07/#a-11.1 .5 ), в основному дозволяючи лише рядкові ключі, а значення ПОВИННІ бути об’єктом , масивом , числом , рядком або одним із наступних імен літералу: false , null true . Об’єктивні літерали в JavaScript можуть мати ключі як ідентифікатори , рядкові літерали абоЧисло літералів , а значенням може бути будь-який тип виразу ...
Крістіан Сальвадо,

@CMS І сьогоднішній JavaScript дозволяє скорочувальні ідентифікатори всередині виразів конструктора об'єктів, наприклад:, { a }де властивість 'a' копіює значення глобальної або локальної змінної 'a'.
Hydroper

@CMS А ще є обчислювані ключі:{[key]: value}
Hydroper

0

Як :і пробільні дозволені в ідентифікаторах. Без лапок це могло б викликати неоднозначність при спробі визначити, що саме являє собою ідентифікатор.


0

У javascript об'єкти можуть використовуватися як хеш / хеш-таблиця з парами ключів.

Однак якщо у вашому ключі є символи, які javascript не може позначити як ім'я, він не зможе отримати доступ, як властивість об'єкта, а не ключа.

var test  = {};
test["key"] = 1;
test["#my-div"] = "<div> stuff </div>";

// test = { "key": 1, "#my-div": "<div> stuff </div>" };

console.log(test.key);           // should be 1
console.log(test["key"]);        // should be 1
console.log(test["#my-div"]);    // should be "<div> stuff </div>";
console.log(test.#my-div);       // would not work.

Ідентифікатори іноді можуть мати символи, які неможливо оцінити як маркер / ідентифікатор у javascript, тому найкраще розміщувати всі ідентифікатори в рядках для узгодженості.


-2

Я думаю, що правильною відповіддю на питання Чезо є те, що реалізація перевершила документацію. Для цього більше не потрібен рядок як ключ, а щось інше, яке може бути або рядком (тобто в лапках), або (можливо) будь-яким, що може використовуватися як ім'я змінної, що, на мою думку, означає, що починати з літери, _ , або $, і включають лише літери, цифри, а також $ і _.

Я хотів спростити решту для наступної людини, яка відвідує це питання з тією ж ідеєю, що і я. Ось м’ясо:

Імена змінних не інтерполюються в JSON, коли вони використовуються як ключ об’єкта (Дякую, Фрідо!)

Бретонський, використовуючи "ідентифікатор" замість "ключ", писав, що "якщо ідентифікатор виявляється зарезервованим словом, він інтерпретується як це слово, а не як ідентифікатор". Це може бути правдою, але я спробував це без особливих проблем:

var a = {do:1,long:2,super:3,abstract:4,var:5,break:6,boolean:7};
a.break

=> 6

Про використання лапок Квентін пише: "... але вам не потрібно, якщо [ключ] не містить певних символів (або комбінацій символів, які роблять це ключовим словом)"

Я виявив, що колишня частина (певні символи) відповідає дійсності, використовуючи знак @ (насправді, я думаю, $ і _ - це єдині символи, які не спричиняють помилку):

var a = {a@b:1};

=> Синтаксична помилка

var a = {"a@b":1};
a['a@b']

=> 1

але дужка про ключові слова, як я показав вище, не відповідає дійсності.

Те, що я хотів, працює, тому що текст між початком {та двокрапкою, або між комою та двокрапкою для наступних властивостей використовується як рядок без котирувань для створення ключа об'єкта, або, як висловився Фрідо, ім'я змінної там немає ' t отримати інтерполяцію:

var uid = getUID();
var token = getToken();            // Returns ABC123
var data = {uid:uid,token:token};
data.token

=> ABC123


-3

Якщо json описує об'єкти, то на практиці ви отримуєте наступне

var foo = {};

var bar = 1;

foo["bar"] = "hello";
foo[bar] = "goodbye";

так то,

foo.bar == "hello";
foo[1] == "goodbye" // in setting it used the value of var bar

так що навіть якщо ваші приклади дають однаковий результат, їх еквіваленти в "необробленому коді" не дадуть. Може, тому ?? не знаю, просто ідея.


3
@David, імена змінних не інтерполюються в JS, коли використовуються як ключ об'єкта. { bar: 'goodbye' }не встановить для імені ключа значення bar, це просто буде bar. Інші мають рацію щодо причини, чому специфікація вимагає лапок: це уникнення конфліктів ключових слів та спеціальних символів.
friedo

-3

Це може зменшити обсяг даних, якщо лапки назви дозволяються лише за необхідності

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.