2010-01-14 29 views
78

The JSON spec dice que JSON es un objeto o una matriz. En el caso de un objeto,en JSON, ¿por qué se cita cada nombre?

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

Y más adelante, la especificación dice que una cadena está entre comillas.

¿Por qué?

Por lo tanto,

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

y no

{Property1:"Value1",Property2:18} 

Pregunta 1: ¿por qué no permite que el nombre en los pares de nombre/valor para ser identificadores cotizados?


Pregunta 2: ¿Hay una diferencia semántica entre las dos representaciones anteriores, cuando se evaluó en Javascript?

+0

¿Qué quiere decir por "en JSON"? Hace que "JSON" se vea como un lenguaje de programación. –

+1

@ Bruno: Se podría hablar de XML de la misma manera ... y, por desgracia, algunos pueden estar tratando de usar XML como lenguaje de programación ... –

+2

+1 ... parece una contradicción peculiar ... .. "con comillas" lo convierte en JSON estándar, pero no funcionará con 'eval()' (es decir, javascript). – skaffman

Respuesta

53

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

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

"nombres de cotización con "" es mucho más simple que "Usted puede citar nombres con " o ' pero que no tienen hasta, a menos que contengan ciertos caracteres (o combinaciones de caracteres que lo convertirían en una palabra clave) y ' o " pueden necesitar ser cotizados dependiendo de qué delimitador haya seleccionado ".

Pregunta 2: ¿Hay una diferencia semántica entre las dos representaciones de arriba, cuando se evalúa en Javascript?

No. En JavaScript son idénticos.

+2

No, no es correcto. CMS tiene la respuesta correcta. Esta respuesta es solo un buen efecto secundario de la razón real. Además de ser más fácil de explicar, también es más sencillo escribir un analizador, ya que puede reutilizar las reglas de análisis para cadenas de identificadores. – Breton

+0

y aparte de eso, hay una ligera diferencia semántica en que si un identificador pasa a ser una palabra reservada, se interpreta como esa palabra en lugar de como un identificador. – Breton

+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 erróneo (esto es una palabra clave reservada) –

0

Ambos : y espacios en blanco están permitidos en los identificadores. Sin las comillas, esto causaría ambigüedad al tratar de determinar qué constituye exactamente el identificador.

125

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

Él habla de cómo descubrió JSON, y entre otras cosas por lo que decidió utilizar claves citadas:

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

En ese momento, yo estaba tratando de convencer a la gente : sí, se puede escribir aplicaciones en JavaScript, es realidad va a trabajar y es una buena idioma. No quería decir, entonces, al mismo tiempo: ¡y mira esto realmente estúpido que hicieron! Entonces, yo decidí, en cambio, citemos las claves .
De esta manera, no tenemos que decirle a nadie acerca de cómo es.

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

Puede encontrar el video completo y la transcripción here.

+0

Ummm ... el creador * * de la norma JSON?! Creo que es una exageración. JSON es la notación de objetos JavaScript y proviene de la especificación Javascript (ECMA). –

+39

@Sorin: No confundas los literales de JSON con los objetos de JavaScript. JSON es un formato de intercambio de datos independiente del idioma, propuesto por Crockford en 2006 (http://tools.ietf.org/html/rfc4627), su gramática difiere de los literales de Object de JavaScript (http://bclary.com/2004/ 11/07/# a-11.1.5), básicamente al permitir solo las claves * string * y los valores * DEBEN * ser un * objeto *, * matriz *, * número *, * cadena *, o uno de los siguientes literales nombres: * falso *, * nulo * * verdadero *. Los literales de objeto en JavaScript pueden tener claves como * Identifiers *, * String literales * o * Number literals *, y el valor puede ser cualquier tipo de * expression * ... – CMS

+0

@CMS Y el JavaScript de hoy permite los identificadores abreviados dentro de las expresiones del constructor de objetos, por ejemplo: '{a}', donde la propiedad 'a' copia el valor de una variable global o local 'a'. – Hydro

-3

Si JSON describe los objetos, a continuación, en la práctica se obtiene el siguiente

var foo = {}; 

var bar = 1; 

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

por lo tanto,

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

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

+3

@David, los nombres de las variables no se interpolan en JS cuando se usan como una clave de objeto. '{bar: 'adiós'}' no establecerá el nombre de la clave en el valor de 'bar', simplemente será' bar'. Los otros tienen razón sobre por qué la especificación requiere citas: es para evitar conflictos de palabras clave y de caracteres especiales. – friedo

0

En javascript, los objetos se pueden utilizar como hash/hashtable con pares de claves.

Sin embargo, si su clave tiene caracteres que javascript no podría tokenizar como 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. 

identificadores a veces pueden tener caracteres que no pueden ser evaluados como muestra/identificador en Javascript, por lo tanto todo lo posible para poner todos los identificadores de cadenas para la consistencia.

-1

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 otra cosa, que puede ser una cadena (es decir, citada) o (probablemente) cualquier cosa que se pueda usar como nombre de variable, lo que supongo significa comenzar con una letra, _ , o $, e incluyen solo letras, números y $ y _.

Quería simplificar el resto para la siguiente persona que visita esta pregunta con la misma idea que yo. Aquí está la carne:

nombres de las variables no son interpolados en JSON cuando se utiliza como un objeto clave (! Gracias Friedo)

Bretón, el uso de "identificador" en lugar de "clave", escribió que "si un identificador pasa a ser 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 citas, Quentin escribió" ... pero no tiene que, a menos que [la tecla ] contiene ciertos caracteres (o combinaciones de caracteres que harían una palabra clave)"

me encontré con la parte anterior (ciertos caracteres) es verdadera, utilizando el signo @ (de hecho, creo que $ y _ son la solo caracteres que no causan el error):

var a = {[email protected]:1}; 

=> Error de sintaxis

var a = {"[email protected]":1}; 
a['[email protected]'] 

=> 1

pero el paréntesis sobre las palabras clave, como he mostrado 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 siguientes se usa como una cadena sin comillas para crear una clave de objeto o, como Friedo lo expresó, una variable nombre que no se pone interpoladas:

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

=> ABC123

-2

se puede reducir el tamaño de los datos si cotizaciones en nombre solamente se permite cuando sea necesario

Cuestiones relacionadas