Como posso verificar se um valor é um objeto json?

101

Meu código do lado do servidor retorna um valor que é um objeto json em caso de sucesso e uma string 'false' em caso de falha. Agora, como posso verificar se o valor retornado é um objeto json?

bart
fonte
2
Se for realmente "seu" código do lado do servidor, por que não ter um campo de status no resultado JSON em vez de criar esta situação "às vezes é JSON e às vezes não é" ...?
HostileFork diz não confie em SE
@Hostile Por motivos de depuração. Você nunca sabe que tipo de falha o servidor irá lançar e nesse ponto o json não está sendo usado.
Bart
1
Ainda não vejo como ter um código de erro (como um campo nomeado) na resposta do servidor pode prejudicar isso. É bom o suficiente para o Freebase! wiki.freebase.com/wiki/MQL_errors
HostileFork diz Não confie SE
Por favor, altere a resposta aceita para Serguei Federov, se você puder, a resposta aceita atualmente está incorreta.
Serj Sagan
O que é um "objeto json"? Existem strings JSON e objetos JS, mas não existe um "objeto JavaScript Object Notation".
MPEN

Respostas:

105

jQuery.parseJSON () deve retornar um objeto do tipo "objeto", se a string for JSON, então você só precisa verificar o tipo com typeof

var response=jQuery.parseJSON('response from server');
if(typeof response =='object')
{
  // It is JSON
}
else
{
  if(response ===false)
  {
     // the response was a string "false", parseJSON will convert it to boolean false
  }
  else
  {
    // the response was something else
  }
}
Dr.Molle
fonte
29
Também pode ser necessário usar um try / catch para exceções se for possível que parseJSON esteja lidando com algo diferente de valores JSON (ou seja, HTML)
acorncom
2
Antes do jQuery 1.9, $ .parseJSON retornava nulo em vez de gerar um erro se fosse transmitida uma string vazia, nula ou indefinida, mesmo que esses não sejam JSON válidos. link do site jquery
gloomy.penguin
7
Essa solução não é das melhores, pois retorna "SyntaxError: JSON.parse: unexpected character"erro! , Eu acho que a melhor solução é usar try / catch que disse Serguei Fedorovaqui: stackoverflow.com/questions/4295386/…
Nabi KAZ
2
Se você não quiser usar jquery, você pode usar vanilla JS verificando o tipo de construtor conforme descrito aqui: stackoverflow.com/questions/11182924/…
Mat
2
Essa resposta está incorreta, a resposta de Serguei Federov deve ser a resposta aceita.
Serj Sagan
148

A solução escolhida realmente não funciona para mim porque recebo um

     "Unexpected Token <" 

erro no Chrome. Isso ocorre porque o erro é lançado assim que a análise encontra um caractere desconhecido. No entanto, há uma maneira de contornar isso se você estiver retornando apenas valores de string por meio de ajax (o que pode ser bastante útil se você estiver usando PHP ou ASPX para processar solicitações de ajax e pode ou não retornar JSON dependendo das condições)

A solução é bastante simples, você pode fazer o seguinte para verificar se era um retorno JSON válido

       var IS_JSON = true;
       try
       {
               var json = $.parseJSON(msg);
       }
       catch(err)
       {
               IS_JSON = false;
       }                

Como eu disse antes, esta é a solução para se você estiver retornando coisas do tipo string de sua solicitação AJAX ou se estiver retornando tipo misto.

Serguei Fedorov
fonte
A questão não é sobre strings não JSON em nenhum ponto. O servidor retorna sempre um JSON válido (uma string falsetambém é um JSON válido). A questão é apenas sobre um único ponto: como diferenciar se a string JSON analisada é um booleano falseou um objeto
Dr.Molle
2
Consideração de desempenho: envolvendo isso em uma função, certifique-se de não analisar o json duas vezes (uma vez dentro do try catch e uma vez no código que chama a função.)
Michiel Cornille
É uma ajudantes funcionar isJSON () que você pode usar: isJSON(someValue).
Chofoteddy
19

Solução 3 (caminho mais rápido)

/**
 * @param Object
 * @returns boolean
 */
function isJSON (something) {
    if (typeof something != 'string')
        something = JSON.stringify(something);

    try {
        JSON.parse(something);
        return true;
    } catch (e) {
        return false;
    }
}

Você pode usar isso:

var myJson = [{"user":"chofoteddy"}, {"user":"bart"}];
isJSON(myJson); // true

A melhor maneira de validar se um objeto é do tipo JSON ou array é a seguinte:

var a = [],
    o = {};

Solução 1

toString.call(o) === '[object Object]'; // true
toString.call(a) === '[object Array]'; // true

Solução 2

a.constructor.name === 'Array'; // true
o.constructor.name === 'Object'; // true

Mas, estritamente falando, um array faz parte de uma sintaxe JSON. Portanto, os dois exemplos a seguir fazem parte de uma resposta JSON:

console.log(response); // {"message": "success"}
console.log(response); // {"user": "bart", "id":3}

E:

console.log(response); // [{"user":"chofoteddy"}, {"user":"bart"}]
console.log(response); // ["chofoteddy", "bart"]

AJAX / JQuery (recomendado)

Se você usa JQuery para trazer informações via AJAX. Recomendo que você coloque no atributo "dataType" o valor "json", dessa forma se você pegar um JSON ou não, o JQuery valide para você e divulgue através de suas funções "sucesso" e "erro". Exemplo:

$.ajax({
    url: 'http://www.something.com',
    data: $('#formId').serialize(),
    method: 'POST',
    dataType: 'json',
    // "sucess" will be executed only if the response status is 200 and get a JSON
    success: function (json) {},
    // "error" will run but receive state 200, but if you miss the JSON syntax
    error: function (xhr) {}
});
Chofoteddy
fonte
13

Se você tiver jQuery, use isPlainObject .

if ($.isPlainObject(my_var)) {}
thnee
fonte
5
Se você usar isPlainObject em uma string, ele retornará falso, por exemplo, jQuery.isPlainObject ('{}')
Roy Shoa
Mais importante, se ele contiver um valor diferente de JSON como uma propriedade, de acordo com os documentos, essa função ainda retornará true.
samvv
6
var checkJSON = function(m) {

   if (typeof m == 'object') { 
      try{ m = JSON.stringify(m); }
      catch(err) { return false; } }

   if (typeof m == 'string') {
      try{ m = JSON.parse(m); }
      catch (err) { return false; } }

   if (typeof m != 'object') { return false; }
   return true;

};


checkJSON(JSON.parse('{}'));      //true
checkJSON(JSON.parse('{"a":0}')); //true
checkJSON('{}');                  //true
checkJSON('{"a":0}');             //true
checkJSON('x');                   //false
checkJSON('');                    //false
checkJSON();                      //false
luizhp
fonte
4

Já que é apenas um objeto falso e json, por que você não verifica se é falso, caso contrário, deve ser json.

if(ret == false || ret == "false") {
    // json
}
Andreas Wong
fonte
2

Eu sei que este tópico já foi respondido, mas vir aqui não resolveu realmente meus problemas, eu encontrei esta função em outro lugar. talvez alguém que venha aqui descubra que é de alguma utilidade para eles;

function getClass(obj) {
  if (typeof obj === "undefined")
    return "undefined";
  if (obj === null)
    return "null";
  return Object.prototype.toString.call(obj)
    .match(/^\[object\s(.*)\]$/)[1];
}
pythonian29033
fonte
1
var data = 'json string ?';
var jdata = null;
try
{
    jdata = $.parseJSON(data);  
}catch(e)
{}

if(jdata)
{
//use jdata
}else
{
//use data
}
Firas Abd Alrahman
fonte
0

Se quiser testar explicitamente o JSON válido (em oposição à ausência do valor retornado false), você pode usar uma abordagem de análise conforme descrito aqui .

Ken Redler
fonte
0

Eu realmente não gosto da resposta aceita. Em primeiro lugar, requer jQuery, que nem sempre está disponível ou é obrigatório. Em segundo lugar, faz uma estringificação completa do objeto que para mim é um exagero. Aqui está uma função simples que detecta completamente se um valor é semelhante a JSON, usando nada mais do que algumas partes da biblioteca lodash para genericidade.

import * as isNull from 'lodash/isNull'
import * as isPlainObject from 'lodash/isPlainObject'
import * as isNumber from 'lodash/isNumber'
import * as isBoolean from 'lodash/isBoolean'
import * as isString from 'lodash/isString'
import * as isArray from 'lodash/isArray'

function isJSON(val) {
  if (isNull(val)
   || isBoolean(val)
   || isString(val))
    return true;
  if (isNumber(val)) 
     return !isNaN(val) && isFinite(val)
  if (isArray(val))
    return Array.prototype.every.call(val, isJSON)
  if (isPlainObject(val)) {
    for (const key of Object.keys(val)) {
      if (!isJSON(val[key]))
        return false
    }
    return true
  }
  return false
}

Até reservei um tempo para colocá-lo no npm como um pacote: https://npmjs.com/package/is-json-object . Use-o junto com algo como Webpack para colocá-lo no navegador.

Espero que isso ajude alguém!

samvv
fonte
0

Estou usando isso para validar objeto JSON

function isJsonObject(obj) {
    try {
        JSON.parse(JSON.stringify(obj));
    } catch (e) {
        return false;
    }
    return true;
}

Estou usando isso para validar a string JSON

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}
Abhishek Goel
fonte
0

tentei todas as respostas sugeridas, nada funcionou para mim, então tive que usar

jQuery.isEmptyObject()

enxada que ajuda outra pessoa com este problema

Jay Rizzi
fonte
-1

Você deve retornar json sempre , mas alterar seu status ou, no exemplo a seguir, a propriedade ResponseCode :

if(callbackResults.ResponseCode!="200"){
    /* Some error, you can add a message too */
} else {
    /* All fine, proceed with code */
};
Kobe
fonte
@bart, você pode apenas fornecer o objeto na condição if, que fará a verificação.
kobe