2010-09-14 108 views
318

Algo así como:¿Cómo comprobar si una cadena es una cadena JSON válida en JavaScript sin necesidad de utilizar Try/Catch

var jsonString = '{ "Id": 1, "Name": "Coke" }'; 

//should be true 
IsJsonString(jsonString); 

//should be false 
IsJsonString("foo"); 
IsJsonString("<div>foo</div>") 

La solución no debe contener try/catch. Algunos de nosotros activamos "romper todos los errores" y no les gusta que el depurador rompa esas cadenas JSON no válidas.

+11

¿Hay una razón válida para no usar 'try'? –

+4

@NickT Porque si activa "interrumpir todos los errores" en el depurador, lo hará. Chrome ahora tiene la opción de romper los errores no detectados aunque. –

+1

Para los curiosos, así es como el motor V8 hace su análisis JSON: http://v8.googlecode.com/svn/trunk/src/json-parser.h –

Respuesta

107

Un comentario primero. La pregunta era sobre no usar try/catch.
Si no te importa usarlo, lee la respuesta a continuación. Aquí simplemente verificamos una cadena JSON usando una expresión regular, y funcionará en la mayoría de los casos, no en todos los casos.

echar un vistazo alrededor de la línea 450 en https://github.com/douglascrockford/JSON-js/blob/master/json2.js

Hay una expresión regular que comprobar si hay un JSON válida, algo así como:

if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@'). 
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). 
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { 

    //the json is ok 

}else{ 

    //the json is not ok 

} 

EDITAR: La nueva versión de json2.js hace un análisis más avanzado que el anterior, pero todavía se basa en sustituir una expresión regular (desde el comentario de @Mrchief)

+34

Esto solo está comprobando si el código es seguro para que eval lo use. Por ejemplo, la siguiente cadena '2011-6-27' pasaría esa prueba. – SystemicPlural

+3

@SystemicPlural, sí, pero la pregunta era sobre no usar try/catch – Mic

+0

http://stackoverflow.com/questions/546433/regular-expression-to-match-outer-brackets –

550

Utilizar un analizador JSON como JSON.parse:

function IsJsonString(str) { 
    try { 
     JSON.parse(str); 
    } catch (e) { 
     return false; 
    } 
    return true; 
} 
+3

Gracias, pero acabo de ejecutar esto con el equipo y quieren algo que no use try/catch. La pregunta se edita junto con un nuevo título. Lo siento por eso. –

+1

Hm ... Extraño ... Usé este ejemplo y me funciona bien (el objeto JSON de las pasadas 'json_encode' de PHP es válido), pero no funciona para el ejemplo en cuestión:' {"Id": 1, "Nombre": "Coque"} '. Devuelve 'falso' para mí. – trejder

+4

@trejder: lo hace porque 1 no es una cadena, inténtalo con "1" – Purefan

11

en js prototipo que tienen método isJSON. intentarlo de

http://api.prototypejs.org/language/string/prototype/isjson/

incluso http://www.prototypejs.org/learn/json

"something".isJSON(); 
// -> false 
"\"something\"".isJSON(); 
// -> true 
"{ foo: 42 }".isJSON(); 
// -> false 
"{ \"foo\": 42 }".isJSON(); 
+7

Gracias, pero creo que usar la biblioteca de prototipos para hacer esto es un poco sobrecargado. –

+4

Has dado CUATRO ejemplos pero solo TRES resultados. ¿Cuál es el resultado de '" {foo: 42} ". IsJSON()'? Si es 'falso ', como supongo (el resultado debe seguir a la función documento), entonces la buena pregunta es, ¿por qué es falso? '{foo: 42}' parece ser perfectamente válido JSON. – trejder

+3

@trejder Desafortunadamente, la especificación JSON requiere claves entrecomilladas. – mikermcneil

5

Usted puede utilizar la función de JavaScript eval() para verificar si es válido.

p. Ej.

var jsonString = '{ "Id": 1, "Name": "Coke" }'; 
var json; 

try { 
    json = eval(jsonString); 
} catch (exception) { 
    //It's advisable to always catch an exception since eval() is a javascript executor... 
    json = null; 
} 

if (json) { 
    //this is json 
} 

Como alternativa, puede utilizar la función de JSON.parsejson.org:

try { 
    json = JSON.parse(jsonString); 
} catch (exception) { 
    json = null; 
} 

if (json) { 
    //this is json 
} 

Espero que esto ayude.

ADVERTENCIA: eval() es peligroso si alguien añade código JS malicioso, ya que lo ejecutará. Asegúrese de que la cadena JSON sea confiable, es decir, que la obtuvo de una fuente confiable.

Editar Para mi primera solución, se recomienda hacer esto.

try { 
     json = eval("{" + jsonString + "}"); 
    } catch (exception) { 
     //It's advisable to always catch an exception since eval() is a javascript executor... 
     json = null; 
    } 

Para garantía JSON-dad. Si el jsonString no es JSON puro, el eval emitirá una excepción.

+0

El primer ejemplo que usa eval dice que "

foo
" es JSON válido. Puede funcionar de manera diferente en diferentes navegadores, pero parece que en Firefox, eval() acepta XML. –

+0

Gracias, pero acabo de ejecutar esto con el equipo y quieren algo que no use try/catch. La pregunta se edita junto con un nuevo título. Lo siento por eso. –

+0

@Mark Lutton, el tipo de objeto no será de JSON sino de XML Dom Document (olvidé cuál es el tipo exacto en firefox). –

2

tal vez será útil:

function parseJson(code) 
{ 
    try { 
     return JSON.parse(code); 
    } catch (e) { 
     return code; 
    } 
} 
function parseJsonJQ(code) 
{ 
    try { 
     return $.parseJSON(code); 
    } catch (e) { 
     return code; 
    } 
} 

var str = "{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}"; 
alert(typeof parseJson(str)); 
alert(typeof parseJsonJQ(str)); 
var str_b = "c"; 
alert(typeof parseJson(str_b)); 
alert(typeof parseJsonJQ(str_b)); 

de salida:

IE7: cuerdas, objeto, secuencia, secuencia de

Chrome: objeto, objeto, cuerda, cadena

1
function get_json(txt) 
{ var data 

    try  { data = eval('('+txt+')'); } 
    catch(e){ data = false;    } 

    return data; 
} 

Si hay errores, devuelve falso.

Si no hay errores, devolver datos JSON

+3

En la pregunta: "La solución no debe contener try/catch". – ddmps

+1

¿Por qué? Esto es una manera garantizada ... ¡Sería una tontería desistir! Lo siento por no saber inglés. Utilicé Google Translate –

-9

I prefere esta manera:

if (!typeof arg == 'object') { 
    //Not JSon 
} else { 
    //Json 
} 
+0

La pregunta es preguntar cómo saber si una cadena es JSON válida (por lo que podría convertirse en un objeto). Su prueba requiere que ya tenga un objeto (y, aparte, es mucho más fácil para otros comprender su código si escribe enunciados negativos como, por ejemplo: 'typeof arg! == 'object'') –

+0

Hum .. No un objeto. Es la prueba ... No entiendo tu comentario. Uso este código y está funcionando muy bien. – Portekoi

+2

Por el momento, cualquier cosa que envíe a su función como el valor de arg dirá que es JSON porque es incorrecta. Entonces, si arg es '' foo bar'' o si arg es '{foo: 'bar'}' tu prueba dirá que es JSON. Si corrigió su código y tenía 'if (typeof arg! == 'object')', su prueba dirá que '{foo: bar}' es JSON, pero dirá que ''{foo: bar}' 'no es JSON (¡que no lo es!pero la pregunta original era preguntar cómo saber si una cadena era JSON válida) –

331

Sé que soy 3 años de retraso a esta pregunta, pero me sentí como campanadas en.

Mientras que la solución de Gumbo funciona muy bien, no maneja unos pocos casos en los que se planteó ninguna excepción para JSON.parse({something that isn't JSON})

También prefiero devolver el JSON analizado al mismo tiempo, por lo que el código de llamada no tiene que llamar al JSON.parse(jsonString) por segunda vez.

Esto parece funcionar bien para mis necesidades:

function tryParseJSON (jsonString){ 
    try { 
     var o = JSON.parse(jsonString); 

     // Handle non-exception-throwing cases: 
     // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking, 
     // but... JSON.parse(null) returns null, and typeof null === "object", 
     // so we must check for that, too. Thankfully, null is falsey, so this suffices: 
     if (o && typeof o === "object") { 
      return o; 
     } 
    } 
    catch (e) { } 

    return false; 
}; 
+18

+1 para algo que maneja nulos y números – Yarin

+4

De las respuestas en la página, esta es la más robusta y confiable. – Jonline

+17

'o && o! == null' es superfluo. – mudasobwa

3

esta pregunta para reducir el costo de TryCatch comunicado.

que utiliza jQuery para analizar cadenas JSON y yo solía TryCatch declaración de manejar excepciones, pero lanzar excepciones para las cadenas no-parsable ralentizado mi código, por lo que utiliza expresiones regulares sencilla de comprobar la cadena si se trata de un posible JSON cuerdas o no sin ir comprobando que la pluma de la sintaxis, a continuación, utilicé la forma habitual mediante el análisis de la cadena usando jQuery:

if (typeof jsonData == 'string') { 
    if (! /^[\[|\{](\s|.*|\w)*[\]|\}]$/.test(jsonData)) { 
     return jsonData; 
    } 
} 

try { 
    jsonData = $.parseJSON(jsonData); 
} catch (e) { 

} 

que envuelve el código anterior en una función recursiva para analizar las respuestas JSON anidados.

6

Utilicé un método realmente simple para comprobar una cadena de cómo es o no un JSON válido.

function testJSON(text){ 
    try{ 
     JSON.parse(text); 
     return true; 
    } 
    catch (error){ 
     return false; 
    } 
} 

resultado con una cadena JSON válida:

var input='["foo","bar",{"foo":"bar"}]'; 
testJSON(input); // returns true; 

resultado con una cadena simple;

var input='This is not a JSON string.'; 
testJSON(input); // returns false; 

Esto funciona cada vez.:)

+0

Parece que solo funciona el 60% del tiempo. –

+0

¿Puede explicar algunos casos cuando no está funcionando? – kukko

35
// vanillaJS 
function isJSON(str) { 
    try { 
     return (JSON.parse(str) && !!str); 
    } catch (e) { 
     return false; 
    } 
} 

Uso:isJSON({}) habrá false, isJSON('{}') habrá true.

Para comprobar si algo es un Array o Object (Analizada JSON):

// vanillaJS 
function isAO(val) { 
    return val instanceof Array || val instanceof Object ? true : false; 
} 

// ES2015 
var isAO = (val) => val instanceof Array || val instanceof Object ? true : false; 

Uso:isAO({}) habrá true, isAO('{}') habrá false.

+2

Tenga cuidado ya que 'null' pasa esta validación. –

+2

'return !! (JSON.parse (str) & & str);' debe bloquear valores nulos. Actualizaré la respuesta con este código. – Machado

+1

Esta es la mejor respuesta, ya que también le permite verificar si el JSON ha sido * objetivado *, y por lo tanto no pasando la prueba 'parse()', causando WTF's. – not2qubit

4

De marco Prototipo String.isJSON definición here

/** 
    * String#isJSON() -> Boolean 
    * 
    * Check if the string is valid JSON by the use of regular expressions. 
    * This security method is called internally. 
    * 
    * ##### Examples 
    * 
    *  "something".isJSON(); 
    *  // -> false 
    *  "\"something\"".isJSON(); 
    *  // -> true 
    *  "{ foo: 42 }".isJSON(); 
    *  // -> false 
    *  "{ \"foo\": 42 }".isJSON(); 
    *  // -> true 
    **/ 
    function isJSON() { 
    var str = this; 
    if (str.blank()) return false; 
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); 
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); 
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); 
    return (/^[\],:{}\s]*$/).test(str); 
    } 

por lo que esta es la versión que se puede utilizar de pasar un objeto de cadena

function isJSON(str) { 
    if (/^\s*$/.test(str)) return false; 
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); 
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); 
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); 
    return (/^[\],:{}\s]*$/).test(str); 
    } 

function isJSON(str) { 
 
    if (/^\s*$/.test(str)) return false; 
 
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); 
 
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); 
 
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); 
 
    return (/^[\],:{}\s]*$/).test(str); 
 
    } 
 

 
console.log ("this is a json", isJSON("{ \"key\" : 1, \"[email protected]\" : \"val\"}")) 
 

 
console.log("this is not a json", isJSON("{ \"key\" : 1, \"[email protected]\" : pippo }"))

2

creo que conoci w por qué quieres evitar eso. Pero tal vez intente & catch! == intente & catch. ; O) Este vino a la mente:

var json_verify = function(s){ try { JSON.parse(s); return true; } catch (e) { return false; }}; 

Así que es posible que también pinza sucia al objeto JSON, como:

JSON.verify = function(s){ try { JSON.parse(s); return true; } catch (e) { return false; }}; 

Como esto como encapsuled como sea posible, no se puede romper en caso de error.

1

var jsonstring='[{"ConnectionString":"aaaaaa","Server":"ssssss"}]'; 
 

 
if(((x)=>{try{JSON.parse(x);return true;}catch(e){return false}})(jsonstring)){ 
 

 
document.write("valide json") 
 

 
}else{ 
 
document.write("invalide json") 
 
}

1

deduzco del comentario de apertura que el caso de uso está delineando si una respuesta es HTML o JSON. En cuyo caso, cuando haga recibir JSON, probablemente deba analizarlo y manejar JSON no válido en algún punto de su código de todos modos. Aparte de todo, imagino que le gustaría que su navegador le informe si se espera JSON pero se recibe JSON no válido (¡como lo harán los usuarios por poder de algún mensaje de error significativo)!

No es necesario hacer una expresión regular completa para JSON (como sería, en mi experiencia, para la mayoría de los casos de uso). Probablemente sería mejor usar algo como el siguiente:

function (someString) { 
    // test string is opened with curly brace or machine bracket 
    if (someString.trim().search(/^(\[|\{){1}/) > -1) { 
    try { // it is, so now let's see if its valid JSON 
     var myJson = JSON.parse(someString); 
     // yep, we're working with valid JSON 
    } catch (e) { 
     // nope, we got what we thought was JSON, it isn't; let's handle it. 
    } 
    } else { 
    // nope, we're working with non-json, no need to parse it fully 
    } 
} 

que debe salvar a tener que manejar excepción código no válido JSON y cuidar de Duff JSON al mismo tiempo.

0

Aquí está la versión mecanografiada también:

JSONTryParse(input) { 
    try { 
     //check if the string exists 
     if (input) { 
      var o = JSON.parse(input); 

      //validate the result too 
      if (o && o.constructor === Object) { 
       return o; 
      } 
     } 
    } 
    catch (e) { 
    } 

    return false; 
}; 
0
if(resp) { 
    try { 
     resp = $.parseJSON(resp); 
     console.log(resp); 
    } catch(e) { 
     alert(e); 
    } 
} 

esperanza que esto funciona para usted también

Cuestiones relacionadas