en JSON, ¿por qué se cita cada nombre?

91

La especificación JSON dice que JSON es un objeto o una matriz. En el caso de un objeto,

Una estructura de objeto se representa como un par de llaves que rodean cero o más pares de nombre / valor (o miembros). Un nombre es una cadena. ...

Y luego, la especificación dice que una cadena está entre comillas.

¿Por qué?

Así,

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

y no

{Property1:"Value1",Property2:18}

Pregunta 1 : ¿por qué no permitir que el nombre en los pares de nombre / valor sean identificadores sin comillas?


Pregunta 2 : ¿Existe una diferencia semántica entre las dos representaciones anteriores, cuando se evalúan en Javascript?

Cheeso
fuente
1
@Bruno: Se podría hablar de XML de la misma manera ... y, lamentablemente, es posible que algunos estén intentando usar XML como lenguaje de programación ...
Mike DeSimone
2
+1 ... parece una contradicción peculiar ... "con comillas" lo convierte en JSON estándar, pero no funciona con eval()(es decir, javascript).
skaffman
2
@bruno, no. si lo expande, se convierte en "en notación de objetos de JavaScript", lo cual está bien
Dave Archer
2
@skaffman: funcionará cuando se evalúe en JavaScript.
Quentin
1
@Bruno: JSON es un formato de datos. "En JSON" significa - con datos formateados de acuerdo con la especificación.
Cheeso

Respuestas:

57

Pregunta 1: ¿por qué no permitir que el nombre en los pares de nombre / valor sean identificadores sin comillas?

La filosofía de diseño de JSON es "Keep it simple"

"Citar nombres con "" es mucho más simple que "Puede citar nombres con "o, 'pero no es necesario, a menos que contengan ciertos caracteres (o combinaciones de caracteres que lo convertirían en una palabra clave) 'o es "posible que deba citarse según en el delimitador que seleccionó " .

Pregunta 2: ¿Existe una diferencia semántica entre las dos representaciones anteriores, cuando se evalúan en Javascript?

No. En JavaScript son idénticos.

Quentin
fuente
3
No, no es correcto. CMS tiene la respuesta correcta. Esta respuesta es solo un buen efecto secundario de la verdadera razón. Además de ser más sencillo de explicar, también es más sencillo escribir un analizador, ya que puede reutilizar las reglas de análisis para cadenas en identificadores.
Bretón
y aparte de eso, hay una ligera diferencia semántica en que si un identificador resulta ser una palabra reservada, se interpreta como esa palabra en lugar de como un identificador.
Bretón
2
+1 en la respuesta de CMS, eso es correcto. Las comillas dobles no son una convención de código, pero desea evitar las palabras reservadas como claves en el objeto. Por ejemplo: {propiedad1: "abc", esto: "def"} es INCORRECTO (esta es una palabra clave reservada)
Sorin Mocanu
Pregunta 2 : Una pequeña diferencia en Javascript cuando se usa la JSON.parsefunción: JSON.parse('{"a":1}') funciona bien , ¿por qué JSON.parse('{a:1}')generará una excepción ?
nhnghia
@nhnghia: la pregunta 2 trata sobre la evaluación del código fuente como JavaScript , no como JSON. JSON.parsees un analizador JSON implementado en JavaScript, no es un analizador de JavaScript.
Quentin
134

Les dejo una cita de una presentación que Douglas Crockford (el creador del estándar JSON) le dio a Yahoo.

Habla sobre cómo descubrió JSON y, entre otras cosas, por qué decidió usar claves entre comillas :

.... Fue entonces cuando descubrimos el problema de los nombres sin comillas. Resulta que ECMA Script 3 tiene una política de palabras reservadas. Las palabras reservadas deben citarse en la posición clave, lo que realmente es una molestia. Cuando llegué a formular esto en un estándar, no quería tener que poner todas las palabras reservadas en el estándar, porque se vería realmente estúpido.

En ese momento, estaba tratando de convencer a la gente: sí, puedes escribir aplicaciones en JavaScript, realmente va a funcionar y es un buen lenguaje. No quería decir, entonces, al mismo tiempo: ¡y mire esta cosa realmente estúpida que hicieron! Así que decidí, en cambio, citar las claves.
De esa manera, no tenemos que decirle a nadie qué tan bueno es.

Es por eso que, hasta el día de hoy, las claves se cotizan en JSON.

Puede encontrar el video completo y la transcripción aquí .

Christian C. Salvadó
fuente
Ummm ... ¿el creador del estándar JSON? Creo que es una exageración. JSON es la notación de objetos de JavaScript y proviene de la especificación de Javascript (ECMA).
Sorin Mocanu
42
@Sorin: No confunda JSON con literales de objetos JavaScript. JSON es un formato de intercambio de datos independiente del lenguaje, propuesto por Crockford en 2006 ( tools.ietf.org/html/rfc4627 ), su gramática difiere de los literales de objetos JavaScript ( bclary.com/2004/11/07/#a-11.1 .5 ), básicamente al permitir solo claves de cadena y los valores DEBEN ser un objeto , matriz , número , cadena o uno de los siguientes nombres literales: falso , nulo verdadero . Los literales de objeto en JavaScript pueden tener claves como identificadores , literales de cadena oLiterales numéricos , y el valor puede ser cualquier tipo de expresión ...
Christian C. Salvadó
@CMS Y el JavaScript de hoy permite identificadores abreviados dentro de expresiones de constructor de objetos, por ejemplo:, { a }donde la propiedad 'a' copia el valor de una variable global o local 'a'.
Hydroper
@CMS Y también hay claves calculadas:{[key]: value}
Hydroper
0

:Se permiten tanto los espacios en blanco como los identificadores. Sin las comillas, esto causaría ambigüedad al intentar determinar qué constituye exactamente el identificador.

Luego.
fuente
0

En javascript, los objetos se pueden usar como una tabla hash / hash con pares de claves.

Sin embargo, si su clave tiene caracteres que javascript no podría convertir en un nombre, fallaría al intentar acceder como una propiedad en un objeto en lugar de una clave.

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.

Los identificadores a veces pueden tener caracteres que no se pueden evaluar como token / identificador en javascript, por lo tanto, es mejor poner todos los identificadores en cadenas para mantener la coherencia.

Michael Herndon
fuente
-2

Creo que la respuesta correcta a la pregunta de Cheeso es que la implementación superó la documentación. Ya no requiere una cadena como clave, sino algo más, que puede ser una cadena (es decir, entre comillas) o (probablemente) cualquier cosa que se pueda usar como nombre de variable, lo que supongo que significa comenzar con una letra, _ , o $, e incluya solo letras, números y $ y _.

Quería simplificar el resto para la próxima persona que visite esta pregunta con la misma idea que yo. Aquí está la carne:

Los nombres de las variables no se interpolan en JSON cuando se usan como clave de objeto (¡Gracias Friedo!)

Breton, utilizando "identificador" en lugar de "clave", escribió que "si un identificador es una palabra reservada, se interpreta como esa palabra en lugar de como un identificador". Esto puede ser cierto, pero lo intenté sin ningún problema:

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

=> 6

Sobre el uso de comillas, Quentin escribió "... pero no es necesario, a menos que [la clave] contenga ciertos caracteres (o combinaciones de caracteres que la convertirían en una palabra clave)".

Encontré que la parte anterior (ciertos caracteres) es verdadera, usando el signo @ (de hecho, creo que $ y _ son los únicos caracteres que no causan el error):

var a = {a@b:1};

=> Error de sintaxis

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

=> 1

pero el paréntesis sobre las palabras clave, como mostré anteriormente, no es cierto.

Lo que quería funciona porque el texto entre la apertura {y los dos puntos, o entre la coma y los dos puntos para las propiedades posteriores se usa como una cadena sin comillas para hacer una clave de objeto, o, como dijo Friedo, un nombre de variable no lo hace ' t se interpola:

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

=> ABC123

Dave Scotese
fuente
-3

Si json describe objetos, en la práctica obtienes lo siguiente

var foo = {};

var bar = 1;

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

por lo que entonces,

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

por lo que incluso si sus ejemplos producen el mismo resultado, sus equivalentes en "código sin formato" no lo harían. ¿¿Tal vez por eso?? no sé, sólo una idea.

Dave Archer
fuente
3
@David, los nombres de las variables no se interpolan en JS cuando se utilizan como clave de objeto. { bar: 'goodbye' }no establecerá el nombre de la clave en el valor de bar, simplemente lo será bar. Los demás tienen razón sobre la razón por la que la especificación requiere comillas: es para evitar conflictos de palabras clave y caracteres especiales.
friedo
-3

Puede reducir el tamaño de los datos si las comillas en el nombre solo se permiten cuando sea necesario

Shashank Joshi
fuente