en JSON, pourquoi chaque nom est-il cité?

91

La spécification JSON indique que JSON est un objet ou un tableau. Dans le cas d'un objet,

Une structure d'objet est représentée par une paire d'accolades entourant zéro ou plusieurs paires nom / valeur (ou membres). Un nom est une chaîne. ...

Et plus tard, la spécification dit qu'une chaîne est entourée de guillemets.

Pourquoi?

Donc,

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

et pas

{Property1:"Value1",Property2:18}

Question 1 : pourquoi ne pas autoriser le nom dans les paires nom / valeur à être des identificateurs sans guillemets?


Question 2 : Y a-t-il une différence sémantique entre les deux représentations ci-dessus, lorsqu'elles sont évaluées en Javascript?

Cheeso
la source
1
@Bruno: Vous pourriez parler de XML de la même manière ... et malheureusement, certains pourraient bien essayer d'utiliser XML comme langage de programmation ...
Mike DeSimone
2
+1 ... cela semble être une contradiction particulière .... "avec des guillemets" le rend standard JSON, mais ne fonctionnera pas avec eval()(c'est-à-dire javascript).
skaffman
2
@bruno, non. si vous le développez, il devient "en notation d'objet Javascript" ce qui est bien
Dave Archer
2
@skaffman - Cela fonctionnera une fois évalué en JavaScript.
Quentin
1
@Bruno - JSON est un format de données. «En JSON» signifie - avec des données formatées selon les spécifications.
Cheeso

Réponses:

57

Question 1: pourquoi ne pas autoriser le nom dans les paires nom / valeur à être des identificateurs sans guillemets?

La philosophie de conception de JSON est "Keep it simple"

"Citer les noms avec "" est beaucoup plus simple que "Vous pouvez citer des noms avec "ou, 'mais vous n'êtes pas obligé de le faire, sauf s'ils contiennent certains caractères (ou des combinaisons de caractères qui en feraient un mot-clé) et / 'ou "pourraient devoir être cités selon sur quel délimiteur vous avez sélectionné " .

Question 2: Y a-t-il une différence sémantique entre les deux représentations ci-dessus, lorsqu'elles sont évaluées en Javascript?

Non. En JavaScript, ils sont identiques.

Quentin
la source
3
Non, ce n'est pas correct. CMS a la bonne réponse. Cette réponse n'est qu'un bel effet secondaire de la vraie raison. En plus d'être plus simple à expliquer, il est également plus simple d'écrire un analyseur, car vous pouvez réutiliser les règles d'analyse pour les chaînes sur les identificateurs.
Breton
et à part cela, il y a une légère différence sémantique en ce que si un identifiant se trouve être un mot réservé, il est interprété comme ce mot plutôt que comme un identifiant.
Breton
2
+1 sur la réponse du CMS, c'est exact. Les guillemets doubles ne sont pas une convention de code, mais vous voulez éviter les mots réservés comme clés dans l'objet. Par exemple: {property1: "abc", this: "def"} est FAUX (ceci est un mot clé réservé)
Sorin Mocanu
Question 2 : Une petite différence en Javascript lors de l' utilisation JSON.parsefonction: JSON.parse('{"a":1}') fonctionne bien , pourquoi JSON.parse('{a:1}')va soulever une exception .
nhnghia le
@nhnghia - La question 2 concerne l'évaluation du code source en JavaScript et non en JSON. JSON.parseest un analyseur JSON implémenté en JavaScript, ce n'est pas un analyseur JavaScript.
Quentin le
134

Je laisse une citation d'une présentation que Douglas Crockford (le créateur de la norme JSON) a donnée à Yahoo.

Il explique comment il a découvert JSON et, entre autres, pourquoi il a décidé d'utiliser les clés entre guillemets :

.... C'est à ce moment-là que nous avons découvert le problème des noms sans guillemets. Il s'avère que ECMA Script 3 a une politique de mots réservés whack. Les mots réservés doivent être cités dans la position clé, ce qui est vraiment une nuisance. Quand j'ai commencé à formuler cela dans une norme, je ne voulais pas avoir à mettre tous les mots réservés dans la norme, car cela aurait l'air vraiment stupide.

À l'époque, j'essayais de convaincre les gens: oui, vous pouvez écrire des applications en JavaScript, ça va marcher et c'est un bon langage. Je ne voulais pas dire, alors, en même temps: et regardez cette chose vraiment stupide qu'ils ont faite! J'ai donc décidé, à la place, de citer simplement les clés.
De cette façon, nous n'avons pas besoin de dire à qui que ce soit à quel point c'est mauvais.

C'est pourquoi, à ce jour, les clés sont citées en JSON.

Vous pouvez trouver la vidéo complète et la transcription ici .

Christian C. Salvadó
la source
Hum ... le créateur du standard JSON?! Je pense que c'est une exagération. JSON est la notation d'objet JavaScript et provient de la spécification Javascript (ECMA).
Sorin Mocanu
42
@Sorin: ne confondez pas JSON avec les littéraux d'objet JavaScript. JSON est un format d'échange de données indépendant du langage, proposé par Crockford en 2006 ( tools.ietf.org/html/rfc4627 ), sa grammaire diffère des littéraux d'objet JavaScript ( bclary.com/2004/11/07/#a-11.1 .5 ), essentiellement en n'autorisant que les clés de chaîne et les valeurs DOIVENT être un objet , un tableau , un nombre , une chaîne ou l'un des noms littéraux suivants: false , null true . Les littéraux d'objet en JavaScript peuvent avoir des clés en tant qu'identificateurs , littéraux de chaîne ouLes littéraux numériques , et la valeur peut être n'importe quel type d' expression ...
Christian C. Salvadó
@CMS Et le JavaScript d'aujourd'hui autorise les identificateurs abrégés à l'intérieur des expressions de constructeur d'objet, par exemple:, { a }où la propriété 'a' copie la valeur d'une variable globale ou locale 'a'.
Hydroper
@CMS Et il y a aussi des clés calculées:{[key]: value}
Hydroper
0

Les :espaces et les espaces sont autorisés dans les identificateurs. Sans les guillemets, cela provoquerait une ambiguïté lors de la tentative de déterminer ce qui constitue exactement l'identifiant.

Anon.
la source
0

En javascript, les objets peuvent être utilisés comme un hash / hashtable avec des paires de clés.

Cependant, si votre clé contient des caractères que javascript ne peut pas tokeniser en tant que nom, elle échouerait en essayant d'accéder comme une propriété sur un objet plutôt qu'une clé.

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.

les identificateurs peuvent parfois avoir des caractères qui ne peuvent pas être évalués en tant que jeton / identificateur en javascript, il est donc préférable de mettre tous les identificateurs dans des chaînes pour des raisons de cohérence.

Michael Herndon
la source
-2

Je pense que la bonne réponse à la question de Cheeso est que la mise en œuvre a dépassé la documentation. Il ne nécessite plus une chaîne comme clé, mais plutôt autre chose, qui peut être une chaîne (c'est-à-dire entre guillemets) ou (probablement) tout ce qui peut être utilisé comme nom de variable, ce qui, je suppose, signifie commencer par une lettre, _ , ou $, et n'incluent que les lettres, les chiffres et les $ et _.

Je voulais simplifier le reste pour la prochaine personne qui visite cette question avec la même idée que moi. Voici la viande:

Les noms de variables ne sont pas interpolés en JSON lorsqu'ils sont utilisés comme clé d'objet (Merci Friedo!)

Breton, utilisant "identifiant" au lieu de "clé", a écrit que "si un identifiant se trouve être un mot réservé, il est interprété comme ce mot plutôt que comme un identifiant". Cela peut être vrai, mais je l'ai essayé sans aucun problème:

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

=> 6

À propos des guillemets, Quentin a écrit "... mais ce n'est pas obligatoire, à moins que [la clé] contienne certains caractères (ou combinaisons de caractères qui en feraient un mot-clé)"

J'ai trouvé que la première partie (certains caractères) est vraie, en utilisant le signe @ (en fait, je pense que $ et _ sont les seuls caractères qui ne causent pas l'erreur):

var a = {a@b:1};

=> Erreur de syntaxe

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

=> 1

mais la parenthèse sur les mots clés, comme je l'ai montré ci-dessus, n'est pas vraie.

Ce que je voulais fonctionne parce que le texte entre l'ouverture {et les deux-points, ou entre la virgule et les deux-points pour les propriétés suivantes est utilisé comme une chaîne sans guillemets pour créer une clé d'objet, ou, comme Friedo l'a dit, un nom de variable là-bas ne le fait pas ' t être interpolé:

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

=> ABC123

Dave Scotese
la source
-3

Si json décrit des objets, vous obtenez en pratique ce qui suit

var foo = {};

var bar = 1;

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

Donc alors,

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

donc même si vos exemples produisent le même résultat, leurs équivalents en "code brut" ne le feraient pas. C'est peut-être pourquoi ?? Je sais pas, juste une idée.

Dave Archer
la source
3
@David, les noms de variables ne sont pas interpolés dans JS lorsqu'ils sont utilisés comme clé d'objet. { bar: 'goodbye' }ne définira pas le nom de la clé sur la valeur de bar, il le sera simplement bar. Les autres ont raison sur la raison pour laquelle la spécification nécessite des guillemets: c'est pour éviter les conflits de mots-clés et de caractères spéciaux.
friedo le
-3

Cela peut réduire la taille des données si les citations sur le nom ne sont autorisées que lorsque cela est nécessaire

shashank joshi
la source