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.)

Nick Heiner
la source
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.

Brettkelly
la source
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 
}
RayLoveless
la source
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 
}
Håvard S
la source
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>

Dujardin Emmanuel
la source
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'
}
Hesham Yassin
la source
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

ADMETTRE
la source
-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


Ramazan Polat
la source