AJAX: Sprawdź, czy ciąg to JSON?

83

Mój JavaScript czasami ulega awarii w tej linii:

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

Awarie występują, gdy argumentem eval()nie jest JSON. Czy istnieje sposób, aby sprawdzić, czy ciąg jest w formacie JSON przed wykonaniem tego wywołania?

Nie chcę używać frameworka - czy jest jakiś sposób, aby ten działał, używając tylko eval()? (Obiecuję, że jest dobry powód).

Nick Heiner
źródło
Możesz spróbować JSON.parse () w try / catch ... jeśli uda ci się złapać, nie jest to poprawny znacznik JSON. Oczywiście to trochę nieefektywne, heh ... Czy możesz podać przykład nieprawidłowego znacznika JSON, który otrzymujesz?
Warty

Odpowiedzi:

158

Jeśli dołączysz parser JSON z json.org, możesz użyć jego funkcji parse () i po prostu zawinąć go w try / catch, na przykład:

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

Coś takiego prawdopodobnie zrobiłoby to, co chcesz.

brettkelly
źródło
9
używając jQuery.parseJSON (..) nie trzeba uwzględniać json.org
RayLoveless,
1
@Raymo OP nie wspomniał o używaniu jQuery i json2.js mniej niż połowę rozmiaru jQuery (pod względem rozmiaru pliku).
brettkelly
Przetwarzanie całego ciągu jest złą praktyką, a rzucenie wyjątku może spowodować opóźnienie
nieprzyjemny
nie zgłosi wyjątku, jeśli wyślesz ciąg liczb
Hesham Yassin
21

To alternatywa dla jQuery ...

try
{
  var jsonObject = jQuery.parseJSON(yourJsonString);
}
catch(e)
{
  // handle error 
}
RayLoveless
źródło
16

Gorąco polecam korzystanie z biblioteki JavaScript JSON do serializacji do iz formatu JSON. eval()jest zagrożeniem bezpieczeństwa, którego nigdy nie należy używać, chyba że masz absolutną pewność, że wprowadzone dane są oczyszczone i bezpieczne.

Mając bibliotekę JSON na miejscu, po prostu zawiń wywołanie do jej parse()odpowiednika w bloku try / catch, aby obsłużyć dane wejściowe inne niż JSON:

try
{
  var jsonObject = JSON.parse(yourJsonString);
}
catch(e)
{
  // handle error 
}
Håvard S
źródło
2

Może to pomoże: za pomocą tego kodu możesz bezpośrednio uzyskać dane…

<!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
źródło
Istnieje wiele alternatywnych sposobów osiągnięcia tego samego wyniku, przy czym użycie eval () jest prawdopodobnie najmniej odpowiednie.
David
1

Problem z zależnością od try-catchpodejścia polega na tym, JSON.parse('123') = 123że nie zgłosi wyjątku. Dlatego oprócz tego try-catchmusimy sprawdzić typ w następujący sposób:

function isJsonStr(str) {
    var parsedStr = str;
    try {
        parsedStr = JSON.parse(str);
    } catch (e) {
        return false;
    }
    return typeof parsedStr == 'object'
}
Hesham Yassin
źródło
0

Dlaczego nie możesz po prostu sprawdzić, jaka jest odpowiedź? Jest bardziej wydajna.

var result;

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

screen1

PRZYZNAĆ
źródło
-1

Istnieje niewielka biblioteka, która sprawdza typy 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

W rzeczywistości is.js jest czymś więcej niż to, kilka wyróżnień:

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
źródło