Les techniques "eval ()" et "JSON.parse ()" utilisent des formats mutuellement exclusifs.
- Avec "eval ()" les parenthèses sont obligatoires .
- Avec "JSON.parse ()" les parenthèses sont interdites .
Attention, il existe des fonctions "stringify ()" qui produisent le format "eval". Pour ajax, vous ne devez utiliser que le format JSON.
Alors que «eval» incorpore le langage JavaScript entier, JSON n'utilise qu'un petit sous-ensemble du langage. Parmi les constructions du langage JavaScript que «eval» doit reconnaître, il y a la «déclaration de bloc» (alias «instruction composée») ; qui est une paire ou des accolades "{}" avec quelques déclarations à l'intérieur. Mais les accolades sont également utilisées dans la syntaxe des littéraux d'objet. L'interprétation est différenciée par le contexte dans lequel le code apparaît. Quelque chose peut ressembler à un objet littéral pour vous, mais "eval" le verra comme une instruction composée.
Dans le langage JavaScript, les littéraux d'objet apparaissent à droite d'une affectation.
var myObj = { ...some..code..here... };
Les littéraux d'objet ne se produisent pas d'eux-mêmes.
{ ...some..code..here... } // this looks like a compound statement
Revenant à la question initiale du PO, posée en 2008, il a demandé pourquoi ce qui suit échoue dans "eval ()":
{ title: "One", key: "1" }
La réponse est que cela ressemble à une instruction composée. Pour le convertir en objet, vous devez le placer dans un contexte où une instruction composée est impossible. Cela se fait en mettant des parenthèses autour
( { title: "One", key: "1" } ) // not a compound statment, so must be object literal
Le PO a également demandé pourquoi une déclaration similaire avait réussi à évaluer:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
La même réponse s'applique - les accolades sont dans un contexte où une instruction composée est impossible. Il s'agit d'un contexte de tableau, " [...]
", et les tableaux peuvent contenir des objets, mais ils ne peuvent pas contenir d'instructions.
Contrairement à "eval ()", JSON est très limité dans ses capacités. La limitation est intentionnelle. Le concepteur de JSON a conçu un sous-ensemble minimaliste de JavaScript, utilisant uniquement la syntaxe qui pourrait apparaître sur le côté droit d'une affectation. Donc, si vous avez du code qui analyse correctement en JSON ...
var myVar = JSON.parse("...some...code...here...");
... cela implique qu'il analysera également légalement le côté droit d'une affectation, comme ceci.
var myVar = ...some..code..here... ;
Mais ce n'est pas la seule restriction sur JSON. La spécification du langage BNF pour JSON est très simple. Par exemple, il ne permet pas l'utilisation de guillemets simples pour indiquer des chaînes (comme le font JavaScript et Perl) et il n'a pas de moyen d'exprimer un seul caractère sous forme d'octet (comme le fait «C»). Malheureusement, il n'autorise pas non plus les commentaires (ce qui serait vraiment bien lors de la création de fichiers de configuration). L'avantage de toutes ces limitations est que l'analyse JSON est rapide et n'offre aucune possibilité d'injection de code (une menace pour la sécurité).
En raison de ces limitations, JSON n'a aucune utilité pour les parenthèses. Par conséquent, une parenthèse dans une chaîne JSON est un caractère non autorisé.
Utilisez toujours le format JSON avec ajax, pour les raisons suivantes:
- Un pipeline ajax typique sera configuré pour JSON.
- L'utilisation de "eval ()" sera critiquée comme un risque de sécurité.
Comme exemple de pipeline ajax, considérons un programme qui implique un serveur Node et un client jQuery. Le programme client utilise un appel jQuery ayant la forme $.ajax({dataType:'json',...etc.});
. JQuery crée un objet jqXHR pour une utilisation ultérieure, puis regroupe et envoie la requête associée. Le serveur accepte la demande, la traite, puis est prêt à répondre. Le programme serveur appellera la méthode res.json(data)
à empaqueter et enverra la réponse. De retour côté client, jQuery accepte la réponse, consulte l'objet jqXHR associé et traite les données au format JSON. Tout cela fonctionne sans aucune conversion manuelle des données. La réponse n'implique aucun appel explicite à JSON.stringify () sur le serveur Node, et aucun appel explicite à JSON.parse () sur le client; tout est géré pour vous.
L'utilisation de «eval» est associée à des risques de sécurité d'injection de code. Vous pensez peut-être que cela ne peut pas arriver, mais les pirates peuvent être assez créatifs. De plus, "eval" est problématique pour l'optimisation Javascript.
Si vous utilisez une fonction "stringify ()", sachez que certaines fonctions portant ce nom créeront des chaînes compatibles avec "eval" et non avec JSON. Par exemple, dans Node, ce qui suit vous donne une fonction qui crée des chaînes au format compatible «eval»:
var stringify = require('node-stringify'); // generates eval() format
Cela peut être utile, mais sauf si vous avez un besoin spécifique, ce n'est probablement pas ce que vous voulez.