Transformando com segurança uma sequência JSON em um objeto

1336

Dada uma sequência de dados JSON, como posso transformar essa sequência com segurança em um objeto JavaScript?

Obviamente, eu posso fazer isso de maneira insegura com algo como:

var obj = eval("(" + json + ')');

mas isso me deixa vulnerável à string JSON que contém outro código, que parece muito perigoso simplesmente avaliar.

Matt Sheppard
fonte
77
Na maioria dos idiomas, o eval acarreta um risco adicional. Eval deixa uma porta aberta para ser explorada por hackers. No entanto, lembre-se de que todo o javascript é executado no cliente. ESPERAR que isso será alterado por hackers. Eles podem avaliar o que quiserem, apenas usando o console. Você deve criar sua proteção no lado do servidor.
Beachhouse
19
Ok, agora é 2014 e você nunca deve usar evalpara analisar uma string JSON, porque você estaria expondo seu código a "injeção de código". Use em JSON.parse(yourString)vez disso.
Daniel
Os dados JSON são literais?
Shanechiu
@ Shanechiu: se você quer dizer um tipo de dados escalar, sim é. É apenas uma string com uma sintaxe de valor-chave.
00Dezembro

Respostas:

1963

JSON.parse(jsonString) é uma abordagem JavaScript pura, desde que você possa garantir um navegador razoavelmente moderno.

Jonathan.
fonte
74
Eu tenho certeza que é seguro para o Node.js
Stephen
76
@vsync você percebe que esta é a ÚNICA Resposta Javascript Pura ... se você ler a descrição da tag javascript, verá isso ... " A menos que uma tag para uma estrutura / biblioteca também esteja incluída, uma resposta JavaScript pura é esperado. ".. Eu dou um +1 por ser a única resposta javascript ...
iConnor
4
Muito seguro de usar .
Redsandro
12
Se você estiver executando o NodeJS, não há como carregar o jQuery apenas para analisar um jsonString em um objeto JSON. Portanto, a resposta de Jonathan foi positiva
Antony
6
De acordo com este link for suportada pelo IE8 +, embora ele diz:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid
878

O método jQuery agora está obsoleto. Use este método:

let jsonObject = JSON.parse(jsonString);

Resposta original usando a funcionalidade jQuery obsoleta :

Se você estiver usando jQuery, basta usar:

jQuery.parseJSON( jsonString );

É exatamente o que você está procurando (consulte a documentação do jQuery ).

Alex V
fonte
7
Existe um motivo para usar isso em JSON.parse ()?
19416 Jon
8
jQuery.parseJSONo padrão é usar JSON.parsese ele existir, portanto, o único motivo para usá-lo sobre o real é se você precisar de um fallback para <IE7. Foi mudado caminho de volta em jQuery 1.6: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren
9
Atualização de 2016: a partir do jQuery 3.0, $ .parseJSON está obsoleto e você deve usar o método JSON.parse nativo.
Jkdev 28/06/16
159

Esta resposta é para o IE <7; para navegadores modernos, verifique a resposta de Jonathan acima.

Esta resposta está desatualizada e a resposta de Jonathan acima ( JSON.parse(jsonString)) agora é a melhor resposta .

O JSON.org possui analisadores JSON para vários idiomas, incluindo quatro diferentes para JavaScript. Acredito que a maioria das pessoas consideraria o json2.js sua implementação goto.

John
fonte
24
Eu gostaria que as pessoas parassem de votar esta resposta. Era preciso quando foi publicado em 2008. Apenas com um voto positivo.
João
22
Se a resposta agora estiver desatualizada, considere atualizá-la.
Sotirios Delimanolis
2
para o IE <8, você precisa usar isso.
Mahmoodvcs
74

Use o exemplo de código simples em " JSON.parse () ":

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

e revertendo:

var str = JSON.stringify(arr);
Ronald
fonte
23

Não tenho certeza sobre outras maneiras de fazer isso, mas veja como você faz isso no Prototype (tutorial JSON) .

new Ajax.Request('/some_url', {
  method:'get',
  requestHeaders: {Accept: 'application/json'},
  onSuccess: function(transport){
    var json = transport.responseText.evalJSON(true);
  }
});

Chamar evalJSON()com true como o argumento limpa a string de entrada.

Mark Biek
fonte
22

Este parece ser o problema:

Uma entrada que é recebida via Ajax websocket etc, e ela estará no formato String, mas você precisa saber se é JSON.parsable. O problema é que, se você sempre executá-lo JSON.parse, o programa PODE continuar "com êxito", mas você ainda verá um erro no console com o temido "Error: unexpected token 'x'".

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});
Cody
fonte
NÃO. O problema é que você está esperando um objeto JSON e pode acabar com (function(){ postCookiesToHostileServer(); }());coisas ainda mais desagradáveis ​​no contexto do Node.
Yaur
Bem, o JSON.parse limpa a entrada de funções (que neste caso não ajudaria como um objeto IIF ->). Parece que a melhor maneira de abordar esse assunto é tentar / capturar. (Ver edição)
Cody
18

Se você estiver usando jQuery , também poderá usar:

$.getJSON(url, function(data) { });

Então você pode fazer coisas como

data.key1.something
data.key1.something_else

etc.

Leanan
fonte
você está usando jQuery, não é?
Alexandre C.
15
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

O retorno de chamada recebe os dados retornados, que serão um objeto ou matriz JavaScript conforme definido pela estrutura JSON e analisados ​​usando o $.parseJSON()método

Prahlad
fonte
12

Apenas por diversão, aqui está uma maneira de usar uma função:

 jsonObject = (new Function('return ' + jsonFormatData))()
lessisawesome
fonte
1
Abordagem interessante, não tenho certeza se usaria isso com JSON.Parse disponível, mas é bom ver alguém pensando fora da caixa.
5
Isso é muito semelhante ao uso apenas evalpara fazer isso e não é seguro. : P
Florrie
7
Isso tem todas as desvantagens de usar, evalmas é mais complicado e mais difícil para os mantenedores entenderem.
Quentin
9

Usar JSON.parseé provavelmente o melhor caminho.

Aqui está um exemplo de demonstração ao vivo .

var jsonRes = '{ "students" : [' +
          '{ "firstName":"Michel" , "lastName":"John" ,"age":18},' +
          '{ "firstName":"Richard" , "lastName":"Joe","age":20 },' +
          '{ "firstName":"James" , "lastName":"Henry","age":15 } ]}';
var studentObject = JSON.parse(jsonRes);
Bharath Kumaar
fonte
9

A maneira mais fácil de usar o parse()método:

var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);

Então você pode obter os valores dos elementos JSON, por exemplo:

var myResponseResult = JsonObject.result;
var myResponseCount = JsonObject.count;

Usando o jQuery, conforme descrito na jQuery.parseJSON()documentação:

JSON.parse(jsonString);
Jorgesys
fonte
9

Tente usar o método com este objeto Data. ex: Data='{result:true,count:1}'

try {
  eval('var obj=' + Data);
  console.log(obj.count);
}
catch(e) {
  console.log(e.message);
}

Esse método realmente ajuda no Nodejs quando você está trabalhando com programação de porta serial

GPrathap
fonte
É muito engraçado como as pessoas são fixados com "eval é mau" e eles vão fazer de tudo para evitá-lo, mesmo re-escrever o todo eval-funcionalidade ..
diynevala
O consenso de que esse truque é um método seguro para transformar string em objeto JSON? Eu poderia usar isso porque nenhuma importação js adicional é necessária.
Quem é
1
QUALQUER abordagem usando evalou Functioné igualmente vulneráveis
Slai
undefined; function bye() {...} bye();
Salvioner 22/01/19
5

Eu encontrei uma maneira "melhor":

No CoffeeScript:

try data = JSON.parse(jqxhr.responseText)
data ||= { message: 'Server error, please retry' }

Em Javascript:

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});
Dorian
fonte
4

A análise JSON é sempre uma dor. Se a entrada não for como o esperado, gera um erro e trava o que você está fazendo.

Você pode usar a pequena função a seguir para analisar com segurança sua entrada. Ele sempre transforma um objeto, mesmo que a entrada não seja válida ou já seja um objeto melhor na maioria dos casos:

JSON.safeParse = function (input, def) {
  // Convert null to empty object
  if (!input) {
    return def || {};
  } else if (Object.prototype.toString.call(input) === '[object Object]') {
    return input;
  }
  try {
    return JSON.parse(input);
  } catch (e) {
    return def || {};
  }
};
Tahsin Turkoz
fonte
Object.prototype.toString.call(input) === '[object Object]'deve ser typeof input === 'object'IMO
Serge K.
typeof input retorna o objeto para null e matrizes também. Portanto, não é a maneira segura de fazer isso.
Tahsin Turkoz
Você já cobriu o nullcaso antes e uma matriz é um Objeto. Se você quiser testá-lo, você pode usar instanceof. Além disso, se você atribuir a essa função um Array, ele será capturado e return defquando poderia ter retornado a matriz perfeitamente fina.
Serge K.
Meu comentário foi sobre o bom senso ao pegar objetos. Minha função pode ter várias prevenções, mas o uso da entrada typeof não é a maneira preferida de detectar objetos em geral.
Tahsin Turkoz
Na IMO, o senso comum não usa o toString()método para verificar se uma variável é um objeto ou não. Veja AngularJS , jQuery , sublinhados , ou mesmo devs
Serge K.
3
JSON.parse(jsonString);

json.parse mudará para objeto.

Shekhar Tyagi
fonte
3

Se tivermos uma string como esta:

"{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"

então podemos simplesmente usar JSON.parseduas vezes para converter essa string em um objeto JSON:

var sampleString = "{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"
var jsonString= JSON.parse(sampleString)
var jsonObject= JSON.parse(jsonString)

E podemos extrair valores do objeto JSON usando:

// instead of last JSON.parse:
var { status, token } = JSON.parse(jsonString);

O resultado será:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059
Hamid Araghi
fonte
3

JSON.parse() converte qualquer string JSON passada na função em um objeto JSON.

Para entender melhor, pressione F12para abrir "Inspect Element" no seu navegador e vá para o console para escrever os seguintes comandos:

var response = '{"result":true,"count":1}'; //sample json object(string form)
JSON.parse(response); //converts passed string to JSON Object.

Agora execute o comando:

console.log(JSON.parse(response));

Você obterá a saída como um objeto {result: true, count: 1} .

Para usar esse objeto, você pode atribuí-lo à variável, talvez obj:

var obj = JSON.parse(response);

Usando obje o ponto (. operador ), você pode acessar as propriedades do objeto JSON.

Tente executar o comando:

console.log(obj.result);
Pushkar Kathuria
fonte
3

Documentação oficial :

O JSON.parse()método analisa uma sequência JSON, construindo o valor ou o objeto JavaScript descrito pela sequência. Um opcionalreviver função pode ser fornecida para executar uma transformação no objeto resultante antes que ele seja retornado.

Sintaxe:

JSON.parse(text[, reviver])

Parâmetros:

text : A sequência a ser analisada como JSON. Consulte o objeto JSON para obter uma descrição da sintaxe JSON.

reviver (optional) : Se uma função, isso prescreve como o valor produzido originalmente pela análise é transformado, antes de ser retornado.

Valor de retorno

O objeto correspondente ao texto JSON fornecido.

Exceções

Lança uma exceção SyntaxError se a sequência a ser analisada não for JSON válida.

Salomon Zhang
fonte
2

Converter o objeto em JSON e, em seguida, analisá-lo, funciona para mim, como:

JSON.parse(JSON.stringify(object))
Liuver Reynier Durán Pérez
fonte
1
Você perdeu um colchete de fechamento.
Salomon Zhang
2

Analise a cadeia JSON JSON.parse()e os dados se tornarão um objeto JavaScript:

JSON.parse(jsonString)

Aqui, o JSON representa para processar o conjunto de dados JSON.

Imagine que recebemos este texto de um servidor web:

'{ "name":"John", "age":30, "city":"New York"}'

Para analisar em um objeto JSON:

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}'); 

Aqui objestá o respectivo objeto JSON que se parece com:

{ "name":"John", "age":30, "city":"New York"}

Para buscar um valor, use o .operador:

obj.name // John
obj.age //30

Converta um objeto JavaScript em uma string com JSON.stringify().

Amitesh
fonte
1

Apenas para a análise da capa para diferentes tipos de entrada

Analise os dados com JSON.parse () e os dados se tornam um objeto JavaScript.

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');

Ao usar o JSON.parse () em um JSON derivado de uma matriz, o método retornará uma matriz JavaScript, em vez de um objeto JavaScript.

var myArr = JSON.parse(this.responseText);
console.log(myArr[0]);

Objetos de data não são permitidos no JSON. Para datas, faça algo assim

var text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}';
var obj = JSON.parse(text);
obj.birth = new Date(obj.birth);

Funções não são permitidas no JSON. Se você precisar incluir uma função, escreva-a como uma string.

var text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}';
var obj = JSON.parse(text);
obj.age = eval("(" + obj.age + ")");
Macaco
fonte
0

Eu sei que pergunta anterior, porém ninguém percebe essa solução usando new Function()uma função anônima que retorna os dados.


Apenas um exemplo:

 var oData = 'test1:"This is my object",test2:"This is my object"';

 if( typeof oData !== 'object' )
  try {
   oData = (new Function('return {'+oData+'};'))();
  }
  catch(e) { oData=false; }

 if( typeof oData !== 'object' )
  { alert( 'Error in code' ); }
 else {
        alert( oData.test1 );
        alert( oData.test2 );
      }

Isso é um pouco mais seguro porque é executado dentro de uma função e não é compilado diretamente no seu código. Portanto, se houver uma declaração de função dentro dela, ela não será vinculada ao objeto de janela padrão.

Eu uso isso para 'compilar' as definições de configuração dos elementos DOM (por exemplo, o atributo de dados) simples e rápido.

Codebeat
fonte
0

Resumo:

Javascript (navegador e NodeJS) tem um JSONobjeto interno . Sobre este objeto existem 2 métodos convenientes para lidar com eles JSON. Eles são os seguintes:

  1. JSON.parse() Recebe JSONcomo argumento, retorna o objeto JS
  2. JSON.stringify() Leva o objeto JS como argumento retorna o JSONobjeto

Outras aplicações:

Além disso, por serem muito convenientes, JSONeles podem ser usados ​​para outros meios. A combinação de ambos os JSONmétodos nos permite facilitar a criação de clones profundos de matrizes ou objetos. Por exemplo:

let arr1 = [1, 2, [3 ,4]];
let newArr = arr1.slice();

arr1[2][0] = 'changed'; 
console.log(newArr); // not a deep clone

let arr2 = [1, 2, [3 ,4]];
let newArrDeepclone = JSON.parse(JSON.stringify(arr2));

arr2[2][0] = 'changed'; 
console.log(newArrDeepclone); // A deep clone, values unchanged

Willem van der Veen
fonte
0

Você também pode usar a reviverfunção para filtrar.

var data = JSON.parse(jsonString, function reviver(key, value) {
   //your code here to filter
});

Para mais informações, leia JSON.parse.

Durgpal Singh
fonte
0

JSON.parse é a maneira correta de converter uma string em um objeto, mas se a string analisada não for objeto ou se a string não estiver correta, ocorrerá um erro que fará com que o restante do código quebre. ideal para agrupar a função JSON.parse dentro de try-catch como

try{
   let obj = JSON.parse(string);
}catch(err){
   console.log(err);
}
deepak thomas
fonte
-1

Tente isso. Este documento está escrito à máquina.

         export function safeJsonParse(str: string) {
               try {
                 return JSON.parse(str);
                   } catch (e) {
                 return str;
                 }
           }
Supun Dharmarathne
fonte
Eu sou novo no texto datilografado. Que benefício isso acrescenta JSON.parse()?
Marc L.
Se qualquer exceção ocorreu, este retornará a cadeia de entrada em si
Supun Dharmarathne
-1
/**
 * Safely turning a JSON string into an object
 *
 * @param {String} str - JSON String
 * @returns deserialized object, false if error
 */
export function jsonParse(str) {
  let data = null;
  try {
    data = JSON.parse(str);
  } catch (err) {
    return false;
  }
  return data;
}
山 茶树 和 葡萄
fonte