Con seguridad convirtiendo una cadena JSON en un objeto


1336

Dada una cadena de datos JSON, ¿cómo puedo convertir esa cadena de manera segura en un objeto JavaScript?

Obviamente puedo hacer esto de forma insegura con algo como:

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

pero eso me deja vulnerable a la cadena JSON que contiene otro código, que parece muy peligroso simplemente evaluar.


77
En la mayoría de los idiomas eval conlleva un riesgo adicional. Eval deja una puerta abierta para ser explotada por los hackers. SIN EMBARGO, recuerde que todo javascript se ejecuta en el cliente. ESPERE que los hackers lo cambien. Pueden EVALAR todo lo que quieran, simplemente usando la consola. Debe construir su protección en el lado del servidor.
Beachhouse

19
Ok, ahora es 2014 y nunca debe usarlo evalpara analizar una cadena JSON porque estaría exponiendo su código a "inyección de código". Usar en su JSON.parse(yourString)lugar.
Daniel

¿Los datos JSON son literales?
shanechiu

@shanechiu: si te refieres a un tipo de datos escalar, sí lo es. Es solo una cadena con una sintaxis de clave-valor.
0zkr PM

Respuestas:


1963

JSON.parse(jsonString) es un enfoque de JavaScript puro siempre que pueda garantizar un navegador razonablemente moderno.


74
Estoy bastante seguro de que es seguro para Node.js
Stephen

76
@vsync te das cuenta de que esta es la ÚNICA respuesta de JavaScript puro ... si lees la descripción de la etiqueta de JavaScript, verás esto ... " A menos que también se incluya una etiqueta para un marco / biblioteca, se incluye una respuesta de JavaScript pura esperado ". Le doy a +1 por ser la única respuesta de JavaScript ...
iConnor


12
Si está haciendo NodeJS, no hay forma de que cargue jQuery solo para analizar un jsonString en un objeto JSON. Vota la respuesta de Jonathan
Antony

66
De acuerdo con este enlace , es compatible con IE8 +, aunque dice:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid

878

El método jQuery ahora está en desuso. Use este método en su lugar:

let jsonObject = JSON.parse(jsonString);

Respuesta original usando la funcionalidad de jQuery en desuso :

Si estás usando jQuery solo usa:

jQuery.parseJSON( jsonString );

Es exactamente lo que está buscando (consulte la documentación de jQuery ).


77
¿Hay alguna razón para usar esto sobre JSON.parse ()?
Jon

8
jQuery.parseJSONel uso predeterminado es JSON.parsesi existe, por lo que la única razón para usar esto sobre el real es si necesita un respaldo para <IE7. Se cambió en jQuery 1.6: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren

99
Actualización de 2016: a partir de jQuery 3.0, $ .parseJSON está en desuso y, en su lugar, debe usar el método JSON.parse nativo.
jkdev

159

Esta respuesta es para IE <7, para navegadores modernos verifique la respuesta de Jonathan arriba.

Esta respuesta está desactualizada y la respuesta de Jonathan anterior ( JSON.parse(jsonString)) ahora es la mejor respuesta .

JSON.org tiene analizadores JSON para muchos idiomas, incluidos cuatro diferentes para JavaScript. Creo que la mayoría de la gente consideraría json2.js su implementación de goto.


24
Desearía que la gente dejara de votar esta respuesta. Fue exacto cuando se publicó en 2008. Simplemente vota el nuevo.
John

22
Si la respuesta está desactualizada, considere actualizarla.
Sotirios Delimanolis

2
para IE <8 necesitas usar esto.
Mahmoodvcs

74

Use el ejemplo de código simple en " JSON.parse () ":

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

y revertirlo:

var str = JSON.stringify(arr);

23

No estoy seguro de otras formas de hacerlo, pero así es como lo haces en Prototype (tutorial de JSON) .

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

Llamar evalJSON()con verdadero como argumento desinfecta la cadena entrante.


22

Este parece ser el problema:

Una entrada que se recibe a través de Ajax websocket, etc., y estará en formato de cadena, pero debe saber si es así JSON.parsable. El problema es que, si siempre lo ejecuta JSON.parse, el programa PUEDE continuar "con éxito", pero aún verá un error en la consola con el temido "Error: unexpected token 'x'".

var data;

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

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

NO. El problema es que está esperando un objeto JSON y podría terminar con (function(){ postCookiesToHostileServer(); }());cosas aún más desagradables en el contexto de Node.
Yaur

Bueno, JSON.parse elimina la entrada de funciones (que en este caso no ayudaría, ya que es un objeto IIF ->). Parece que la mejor manera de abordar este tema es intentar / atrapar. (Ver edición)
Cody

18

Si está usando jQuery , también puede usar:

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

Entonces puedes hacer cosas como

data.key1.something
data.key1.something_else

etc.


Estás usando jQuery, ¿no?
Alexandre C.

15
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

A la devolución de llamada se le pasan los datos devueltos, que serán un objeto o matriz de JavaScript según lo definido por la estructura JSON y analizado utilizando el $.parseJSON()método.


12

Solo por diversión, aquí hay una manera de usar una función:

 jsonObject = (new Function('return ' + jsonFormatData))()

1
Enfoque interesante, no estoy seguro de si usaría esto con JSON. Disponible a primera vista, pero es agradable ver a alguien pensando fuera de la caja.

55
Esto es muy similar a usarlo evalpara hacerlo y no es seguro. : P
Florrie

77
Esto tiene todos los inconvenientes de usar, evalpero es más complicado y más difícil de entender para los encargados del mantenimiento.
Quentin

9

Usar JSON.parsees probablemente la mejor manera.

Aquí hay un ejemplo de demostración en 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);

9

La forma más fácil de usar el parse()método:

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

Luego puede obtener los valores de los elementos JSON, por ejemplo:

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

Usando jQuery como se describe en la jQuery.parseJSON()documentación:

JSON.parse(jsonString);

9

Intente usar el método con este objeto de datos. ex: Data='{result:true,count:1}'

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

Este método realmente ayuda en Nodejs cuando trabajas con programación de puerto serie


Es realmente divertido cómo la gente está obsesionada con "evaluar es malo" y harán todo lo posible para evitarlo, incluso reescribiendo toda la funcionalidad de evaluación ..
diynevala

¿Existe consenso de que este truco es un método seguro para convertir cadenas en objetos JSON? Podría usar esto ya que no se necesitan importaciones js adicionales.
Quién

1
CUALQUIER enfoque que use evalo Functionsea ​​igualmente vulnerable
Slai

undefined; function bye() {...} bye();
Salvioner

5

Encontré una forma "mejor":

En CoffeeScript:

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

En Javascript:

var data;

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

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

4

El análisis JSON siempre es un dolor. Si la entrada no es la esperada, arroja un error y bloquea lo que está haciendo.

Puede usar la siguiente pequeña función para analizar de forma segura su entrada. Siempre convierte un objeto incluso si la entrada no es válida o si ya es un objeto, lo cual es mejor para la mayoría de los 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 || {};
  }
};

Object.prototype.toString.call(input) === '[object Object]'debería ser typeof input === 'object'IMO
Serge K.

typeof input devuelve objetos para nulos y matrices también. Por lo tanto, no es la forma segura de hacerlo.
Tahsin Turkoz

Ya cubriste el nullcaso antes, y una matriz es un Objeto. Si quieres probarlo, puedes usarlo instanceof. Además, si le da a esta función un Array, se capturará y return defcuándo podría haber devuelto la matriz perfectamente fina.
Serge K.

Mi comentario fue sobre un sentido común al atrapar objetos. Mi función puede tener varias precauciones, pero el uso de typeof input no es la forma preferida de detectar objetos en general.
Tahsin Turkoz

En mi opinión, el sentido común no utiliza un toString()método para verificar si una variable es un objeto o no. Vea AngularJS , jQuery , Underscore o incluso desarrolladores
Serge K.


3

Si tenemos una cadena como esta:

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

entonces podemos simplemente usar JSON.parsedos veces para convertir esta cadena en un objeto JSON:

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

Y podemos extraer valores del objeto JSON usando:

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

El resultado será:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059

3

JSON.parse() convierte cualquier cadena JSON pasada a la función en un objeto JSON.

Para entenderlo mejor, presione F12para abrir "Inspeccionar elemento" en su navegador y vaya a la consola para escribir los siguientes comandos:

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

Ahora ejecuta el comando:

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

Obtendrá salida como un objeto {result: true, count: 1} .

Para usar ese objeto, puede asignarlo a la variable, tal vez obj:

var obj = JSON.parse(response);

Mediante el uso objy el punto (. operador ) puede acceder a las propiedades del objeto JSON.

Intenta ejecutar el comando:

console.log(obj.result);

3

Documentación oficial :

El JSON.parse()método analiza una cadena JSON, construyendo el valor de JavaScript u objeto descrito por la cadena. Un opcionalreviver puede proporcionar una función para realizar una transformación en el objeto resultante antes de que se devuelva.

Sintaxis:

JSON.parse(text[, reviver])

Parámetros:

text : La cadena para analizar como JSON. Consulte el objeto JSON para obtener una descripción de la sintaxis JSON.

reviver (optional) : Si es una función, esto prescribe cómo se transforma el valor producido originalmente por el análisis antes de ser devuelto.

Valor de retorno

El objeto correspondiente al texto JSON dado.

Excepciones

Lanza una excepción SyntaxError si la cadena a analizar no es JSON válida.



2

Analice la cadena JSON con JSON.parse(), y los datos se convierten en un objeto JavaScript:

JSON.parse(jsonString)

Aquí, JSON representa procesar el conjunto de datos JSON.

Imagine que recibimos este texto de un servidor web:

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

Para analizar en un objeto JSON:

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

Aquí objestá el objeto JSON respectivo que se parece a:

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

Para obtener un valor, use el .operador:

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

Convierta un objeto JavaScript en una cadena con JSON.stringify().


1

Solo para analizar la cubierta para diferentes tipos de entrada

Analice los datos con JSON.parse (), y los datos se convierten en un objeto JavaScript.

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

Cuando se utiliza JSON.parse () en un JSON derivado de una matriz, el método devolverá una matriz de JavaScript, en lugar de un objeto de JavaScript.

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

Los objetos de fecha no están permitidos en JSON. Para las fechas hacer algo como esto

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

Las funciones no están permitidas en JSON. Si necesita incluir una función, escríbala como una cadena.

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

0

Pregunta anterior, lo sé, sin embargo, nadie se da cuenta de esta solución mediante el uso de new Function()una función anónima que devuelve los datos.


Solo un ejemplo:

 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 );
      }

Esto es un poco más seguro porque se ejecuta dentro de una función y no se compila en su código directamente. Entonces, si hay una declaración de función dentro de ella, no estará vinculada al objeto de ventana predeterminado.

Lo uso para 'compilar' la configuración de los elementos DOM (por ejemplo, el atributo de datos) simple y rápido.


0

Resumen:

Javascript (tanto el navegador como NodeJS) tienen un JSONobjeto incorporado . En este objeto hay 2 métodos convenientes para tratar JSON. Son los siguientes:

  1. JSON.parse() Toma JSONcomo argumento, devuelve el objeto JS
  2. JSON.stringify() Toma el objeto JS como argumento devuelve el JSONobjeto

Otras aplicaciones:

Además, para tratarlos de manera muy conveniente JSON, pueden utilizarse para otros medios. La combinación de ambos JSONmétodos nos permite hacer clones profundos de matrices u objetos muy fácilmente. Por ejemplo:

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


0

También puede usar la reviverfunción para filtrar.

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

Para más información lea JSON.parse.


0

JSON.parse es la forma correcta de convertir una cadena en un objeto, pero si la cadena que se analiza no es un objeto o si la cadena no es correcta, arrojará un error que hará que el resto del código se rompa. ideal para envolver la función JSON.parse dentro de try-catch like

try{
   let obj = JSON.parse(string);
}catch(err){
   console.log(err);
}

-1

Prueba esto. Este está escrito en mecanografiado.

         export function safeJsonParse(str: string) {
               try {
                 return JSON.parse(str);
                   } catch (e) {
                 return str;
                 }
           }

Soy nuevo en Typecript. ¿A qué beneficio se suma esto JSON.parse()?
Marc L.

Si ocurriera alguna excepción, esto devolverá la cadena de entrada en sí
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;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.