AJAX: vérifier si une chaîne est JSON?


83

Mon JavaScript plante parfois sur cette ligne:

var json = eval('(' + this.responseText + ')');

Des plantages surviennent lorsque l'argument de eval()n'est pas JSON. Existe-t-il un moyen de vérifier si la chaîne est JSON avant de faire cet appel?

Je ne veux pas utiliser de framework - y a-t-il un moyen de faire fonctionner cela en utilisant juste eval()? (Il y a une bonne raison, je le promets.)


Vous pouvez essayer JSON.parse () dans un try / catch ... si vous arrivez à catch, ce n'est pas un balisage JSON valide. Bien sûr, c'est un peu inefficace, hein ... Pouvez-vous me donner un exemple du balisage JSON invalide que vous obtenez?
— Warty

Réponses:


157

Si vous incluez l' analyseur JSON de json.org, vous pouvez utiliser sa fonction parse () et simplement l'envelopper dans un try / catch, comme ceci:

try
{
   var json = JSON.parse(this.responseText);
}
catch(e)
{
   alert('invalid json');
}

Quelque chose comme ça ferait probablement ce que vous voulez.


9
en utilisant jQuery.parseJSON (..) vous n'auriez pas besoin d'inclure json.org
— RayLoveless

1
@Raymo OP n'a pas mentionné l'utilisation de jQuery et json2.js moins de la moitié de la taille de jQuery (en termes de taille de fichier).
— brettkelly

L'analyse d'une chaîne entière est une mauvaise pratique, et lancer une exception peut provoquer un décalage
— évocateur

il ne lèvera pas d'exception si vous envoyez une chaîne de chiffres
— Hesham Yassin

21

C'est l'alternative jQuery ...

try
{
  var jsonObject = jQuery.parseJSON(yourJsonString);
}
catch(e)
{
  // handle error 
}

15

Je vous recommande vivement d'utiliser une bibliothèque javascript JSON pour la sérialisation vers et depuis JSON. eval()est un risque de sécurité qui ne doit jamais être utilisé à moins d'être absolument certain que son entrée est nettoyée et sûre.

Avec une bibliothèque JSON en place, enveloppez simplement l'appel à son parse()équivalent dans un bloc try / catch pour gérer une entrée non JSON:

try
{
  var jsonObject = JSON.parse(yourJsonString);
}
catch(e)
{
  // handle error 
}

2

Peut-être que cela aide: avec ce code, vous pouvez obtenir directement vos données…

<!DOCTYPE html>
<html>
<body>

<h3>Open console, please, to view result!</h3>
<p id="demo"></p>

<script>
var tryJSON = function (test) {
	try {
	    JSON.parse(test);
	}
	catch(err) {
    	// maybe you need to escape this… (or not)
	    test = '"'+test.replace(/\\?"/g,'\\"')+'"';
	}
	eval('test = '+test);
	console.debug('Try json:', test);
};

// test with string…
var test = 'bonjour "mister"';
tryJSON(test);
// test with JSON…
var test = '{"fr-FR": "<p>Ceci est un texte en français !</p>","en-GB": "<p>And here, a text in english!</p>","nl-NL": "","es-ES": ""}';
tryJSON(test);
</script>

</body>
</html>


Il existe de nombreuses autres façons d'obtenir le même résultat, utiliser eval () est probablement la moins appropriée.
— David

0

Le problème avec dépendre de l' try-catchapproche est que JSON.parse('123') = 123et cela ne lèvera pas d'exception. Par conséquent, en plus du try-catch, nous devons vérifier le type comme suit:

function isJsonStr(str) {
    var parsedStr = str;
    try {
        parsedStr = JSON.parse(str);
    } catch (e) {
        return false;
    }
    return typeof parsedStr == 'object'
}

0

Pourquoi vous ne pouvez pas simplement vérifier quelle est la réponse? C'est plus efficace.

var result;

if (response.headers['Content-Type'] === 'application/json')
    result = JSON.parse(this.responseText);
else
    result = this.responseText;

écran1


-1

Il existe une petite bibliothèque qui vérifie les types JavaScript: is.js

is.json({foo: 'bar'});
=> true

// functions are returning as false
is.json(toString);
=> false

is.not.json([]);
=> true

is.all.json({}, 1);
=> false

is.any.json({}, 2);
=> true

// 'all' and 'any' interfaces can also take array parameter
is.all.json([{}, {foo: 'bar'}]);
=> true

En fait, is.js est bien plus que cela, quelques mentions honorables:

var obj = document.createElement('div');
is.domNode(obj);
=> true

is.error(new Error());
=> true

is.function(toString);
=> true

is.chrome();
=> true if current browser is chrome


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.