As técnicas "eval ()" e "JSON.parse ()" usam formatos mutuamente exclusivos.
- Com "eval ()", os parênteses são obrigatórios .
- Com "JSON.parse ()" parênteses são proibidos .
Cuidado, existem funções "stringify ()" que produzem o formato "eval". Para ajax, você deve usar apenas o formato JSON.
Enquanto "eval" incorpora toda a linguagem JavaScript, JSON usa apenas um pequeno subconjunto da linguagem. Entre as construções na linguagem JavaScript que "eval" deve reconhecer está a "instrução Block" (também conhecida como "instrução composta") ; que é um par ou chaves "{}" com algumas declarações dentro. Mas as chaves também são usadas na sintaxe de literais de objeto. A interpretação é diferenciada pelo contexto em que o código aparece. Algo pode parecer um objeto literal para você, mas "eval" o verá como uma instrução composta.
Na linguagem JavaScript, os literais de objeto ocorrem à direita de uma atribuição.
var myObj = { ...some..code..here... };
Literais de objeto não ocorrem por conta própria.
{ ...some..code..here... } // this looks like a compound statement
Voltando à pergunta original do OP, feita em 2008, ele perguntou por que o seguinte falha em "eval ()":
{ title: "One", key: "1" }
A resposta é que se parece com uma declaração composta. Para convertê-lo em um objeto, você deve colocá-lo em um contexto em que uma instrução composta seja impossível. Isso é feito colocando-se entre parênteses
( { title: "One", key: "1" } ) // not a compound statment, so must be object literal
O OP também perguntou por que uma declaração semelhante foi avaliada com sucesso:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
A mesma resposta se aplica - as chaves estão em um contexto em que uma declaração composta é impossível. Este é um contexto de array, " [...]
", e os arrays podem conter objetos, mas não podem conter instruções.
Ao contrário de "eval ()", JSON é muito limitado em seus recursos. A limitação é intencional. O designer de JSON pretendia um subconjunto minimalista de JavaScript, usando apenas sintaxe que poderia aparecer no lado direito de uma atribuição. Então, se você tiver algum código que analisa corretamente em JSON ...
var myVar = JSON.parse("...some...code...here...");
... isso implica que também será analisado legalmente no lado direito de uma atribuição, como este ..
var myVar = ...some..code..here... ;
Mas essa não é a única restrição do JSON. A especificação da linguagem BNF para JSON é muito simples. Por exemplo, não permite o uso de aspas simples para indicar strings (como JavaScript e Perl fazem) e não tem uma maneira de expressar um único caractere como um byte (como 'C' faz). Infelizmente, também não permite comentários (o que seria muito bom ao criar arquivos de configuração). A vantagem de todas essas limitações é que a análise de JSON é rápida e não oferece oportunidade para injeção de código (uma ameaça à segurança).
Devido a essas limitações, JSON não usa parênteses. Consequentemente, um parêntese em uma string JSON é um caractere ilegal.
Sempre use o formato JSON com ajax, pelos seguintes motivos:
- Um pipeline de ajax típico será configurado para JSON.
- O uso de "eval ()" será criticado como um risco de segurança.
Como um exemplo de pipeline de ajax, considere um programa que envolve um servidor Node e um cliente jQuery. O programa cliente usa uma chamada jQuery com o formulário $.ajax({dataType:'json',...etc.});
. O JQuery cria um objeto jqXHR para uso posterior, em seguida, empacota e envia a solicitação associada. O servidor aceita a solicitação, processa-a e está pronto para responder. O programa do servidor chamará o método res.json(data)
para empacotar e enviar a resposta. De volta ao lado do cliente, o jQuery aceita a resposta, consulta o objeto jqXHR associado e processa os dados formatados em JSON. Tudo isso funciona sem a necessidade de conversão manual de dados. A resposta não envolve nenhuma chamada explícita para JSON.stringify () no servidor Node e nenhuma chamada explícita para JSON.parse () no cliente; está tudo resolvido para você.
O uso de "eval" está associado a riscos de segurança de injeção de código. Você pode pensar que não há como isso acontecer, mas os hackers podem ser bem criativos. Além disso, "eval" é problemático para a otimização Javascript.
Se você estiver usando uma função "stringify ()", saiba que algumas funções com esse nome criarão cadeias de caracteres compatíveis com "eval" e não com JSON. Por exemplo, no Node, o seguinte fornece a função que cria strings em formato compatível com "eval":
var stringify = require('node-stringify'); // generates eval() format
Isso pode ser útil, mas a menos que você tenha uma necessidade específica, provavelmente não é o que você deseja.