javascript - Como testar se uma string é JSON ou não?
Eu tenho uma chamada AJAX simples, e o servidor retornará ou uma string JSON com dados úteis ou uma string de mensagem de erro produzida pela função PHP mysql_error(). Como posso testar se esses dados são uma string JSON ou a mensagem de erro.
Seria bom usar uma função chamada isJSON, assim como você pode usar a função instanceof para testar se algo é um Array.
Isto é o que eu quero:
if (isJSON(data)){
//do some data stuff
}else{
//report the error
alert(data);
}
Resposta #1
Use JSON.parse
function isJson(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
Resposta #2
Usar JSON.parse() possui algumas desvantagens:
JSON.parse(1234)ouJSON.parse(0)ouJSON.parse(false)ouJSON.parse(null)
todos retornarão verdadeiro.
function isJson(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
function testIsJson(value, expected) {
console.log(`Expected: ${expected}, Actual: ${isJson(value)}`);
}
// All of the following codes are expected to return false.
// But actually returns true.
testIsJson(1234, false);
testIsJson(0, false);
testIsJson(false, false);
testIsJson(null, false);Código que lida com falsos positivos
Então eu reescrevi o código desta forma:
function isJson(item) {
let value = typeof item !== "string" ? JSON.stringify(item) : item;
try {
value = JSON.parse(value);
} catch (e) {
return false;
}
return typeof value === "object" && value !== null;
}
Resultado do teste:
function isJson(item) {
let value = typeof item !== "string" ? JSON.stringify(item) : item;
try {
value = JSON.parse(value);
} catch (e) {
return false;
}
return typeof value === "object" && value !== null;
}
function testIsJson(value, expected) {
console.log(`Expected: ${expected}, Actual: ${isJson(value)}`);
}
const validJson = { "foo": "bar" };
const notValidJson = '{ "foo": "bar" } invalid';
// expected: true
testIsJson(validJson, true);
// expected: false
testIsJson(1234, false);
testIsJson(0, false);
testIsJson(notValidJson, false);
testIsJson(false, false);
testIsJson(null, false);Resposta #3
Vamos recapitular isso (para 2019+).
Argumento: Valores como
true,false,nullsão JSON válidos (?)
FATO: Esses valores primitivos são analisáveis por JSON, mas não são estruturas JSON bem formadas. A especificação do JSON indica que o JSON é construído sobre duas estruturas: uma coleção de pares nome/valor (objeto) ou uma lista ordenada de valores (array).
Argumento: O tratamento de exceções não deve ser usado para fazer algo esperado.
(Este é um comentário que tem mais de 25 votos positivos!)
FATO: Não! É definitivamente legal usar try/catch, especialmente em um caso como este. Caso contrário, você precisaria fazer muitas análises de strings, como tokenização/operções com regex; o que teria um desempenho terrível.
hasJsonStructure()
Isso é útil se o seu objetivo é verificar se alguns dados/texto estão no formato de intercâmbio JSON adequado.
function hasJsonStructure(str) {
if (typeof str !== 'string') return false;
try {
const result = JSON.parse(str);
const type = Object.prototype.toString.call(result);
return type === '[object Object]'
|| type === '[object Array]';
} catch (err) {
return false;
}
}
Uso :
hasJsonStructure('true') // —» false
hasJsonStructure('{"x":true}') // —» true
hasJsonStructure('[1, false, null]') // —» true
safeJsonParse()
E isso é útil se você quiser ter cuidado ao analisar alguns dados para um valor JavaScript.
function safeJsonParse(str) {
try {
return [null, JSON.parse(str)];
} catch (err) {
return [err];
}
}
Uso :
const [err, result] = safeJsonParse('[Invalid JSON}');
if (err) {
console.log('Failed to parse JSON: ' + err.message);
} else {
console.log(result);
}
Resposta #4
Se o servidor estiver respondendo com JSON, então ele terá um application/json como tipo de conteúdo; se estiver respondendo com uma mensagem de texto simples, então deve ter um text/plain como tipo de conteúdo. Certifique-se de que o servidor está respondendo com o tipo de conteúdo correto e teste isso.
Resposta #5
Ao usar jQuery $.ajax(), a resposta terá a propriedade responseJSON se a resposta for JSON, isso pode ser testado assim:
if (xhr.hasOwnProperty('responseJSON')) {}
