в JSON, почему каждое имя цитируется?

91

В спецификации JSON говорится, что JSON - это объект или массив. В случае объекта

Структура объекта представлена ​​в виде пары фигурных скобок, окружающих ноль или более пар имя / значение (или членов). Имя - это строка. ...

А позже в спецификации сказано, что строка заключена в кавычки.

Зачем?

Таким образом,

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

и нет

{Property1:"Value1",Property2:18}

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


Вопрос 2 : есть ли семантическая разница между двумя приведенными выше представлениями при оценке в Javascript?

Чизо
источник
1
@Bruno: Вы могли бы говорить об XML таким же образом ... и, к сожалению, некоторые из них вполне могут пытаться использовать XML в качестве языка программирования ...
Майк Дезимоун,
2
+1 ... это похоже на своеобразное противоречие .... "с кавычками" делает его стандартным JSON, но не работает с eval()(т.е. javascript).
skaffman
2
@bruno, нет. если вы развернете его, он станет «в нотации объектов Javascript», и это нормально
Дэйв Арчер,
2
@skaffman - он будет работать, если будет реализован в JavaScript.
Quentin
1
@Bruno - JSON - это формат данных. «В JSON» означает - с данными, отформатированными согласно спецификации.
Cheeso

Ответы:

57

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

Философия дизайна JSON - «Будь проще».

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

Вопрос 2: есть ли семантическая разница между двумя приведенными выше представлениями при оценке в Javascript?

Нет. В JavaScript они идентичны.

Квентин
источник
3
Нет, это не так. CMS дает правильный ответ. Этот ответ - лишь приятный побочный эффект настоящей причины. Помимо простоты объяснения, еще проще написать синтаксический анализатор, поскольку вы можете повторно использовать правила синтаксического анализа для строк в идентификаторах.
Бретон,
кроме того, есть небольшая семантическая разница в том, что если идентификатор оказывается зарезервированным словом, он интерпретируется как это слово, а не как идентификатор.
Бретон,
2
+1 к ответу CMS, это правильно. Двойные кавычки не являются соглашением о коде, но вы хотите, чтобы зарезервированные слова не использовались в качестве ключей в объекте. Например: {property1: "abc", this: "def"} НЕПРАВИЛЬНО (это зарезервированное ключевое слово)
Сорин Мокану
Вопрос 2 : Небольшая разница в Javascript при использовании JSON.parseфункции: JSON.parse('{"a":1}') работает хорошо , почему JSON.parse('{a:1}')вызовет исключение .
nhnghia 04
@nhnghia - Вопрос 2 касается оценки исходного кода как JavaScript , а не JSON. JSON.parse- это парсер JSON, реализованный на JavaScript, это не парсер JavaScript.
Квентин
134

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

Он рассказывает о том, как он обнаружил JSON, и, среди прочего, почему решил использовать ключи в кавычках :

.... Именно тогда мы обнаружили проблему с именем без кавычек. Оказывается, в сценарии ECMA 3 используется политика зарезервированных слов для взлома. Зарезервированные слова необходимо цитировать в ключевой позиции, что действительно неприятно. Когда я добрался до формулировки этого стандарта, я не хотел помещать все зарезервированные слова в стандарт, потому что это выглядело бы действительно глупо.

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

Вот почему по сей день ключи цитируются в JSON.

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

Кристиан К. Сальвадо
источник
Эммм ... создатель стандарта JSON ?! Я считаю, что это преувеличение. JSON - это нотация объектов JavaScript, происходящая из спецификации Javascript (ECMA).
Сорин Мокану
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

Я думаю, что правильный ответ на вопрос Cheeso заключается в том, что реализация превзошла документацию. Ему больше не требуется строка в качестве ключа, а скорее что-то еще, которое может быть либо строкой (то есть заключенной в кавычки), либо (возможно) чем-либо, что можно использовать в качестве имени переменной, что, как я предполагаю, означает начало с буквы _ , или $, и включать только буквы, цифры, а также $ и _.

Я хотел упростить остальное для следующего человека, который задаст этот вопрос с той же идеей, что и я. Вот мясо:

Имена переменных не интерполируются в 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

Это может уменьшить размер данных, если кавычки в имени разрешены только при необходимости

шашанк джоши
источник