¿Cómo puedo verificar si un valor es un objeto json?

101

El código del lado del servidor devuelve un valor que es un objeto json en caso de éxito y una cadena 'falso' en caso de error. Ahora, ¿cómo puedo verificar si el valor devuelto es un objeto json?

bart
fuente
2
Si en realidad es "su" código del lado del servidor, ¿por qué no tener un campo de estado en el resultado JSON en lugar de crear esta situación de "a veces-es-JSON-y-a veces-no-lo-es" ...?
HostileFork dice que no confíes en SE
@Hostile Por motivos de depuración. Nunca se sabe qué tipo de falla arrojará el servidor y en ese momento no se está utilizando json.
bart
1
Todavía no veo cómo tener un código de error (como un campo con nombre) en la respuesta del servidor socavaría eso. ¡Es lo suficientemente bueno para Freebase! wiki.freebase.com/wiki/MQL_errors
HostileFork dice que no confíes en SE
Cambie la respuesta aceptada por la de Serguei Federov, si puede, la respuesta aceptada actualmente es incorrecta.
Serj Sagan
¿Qué es un "objeto json"? Hay cadenas JSON y objetos JS, pero no existe un "objeto de notación de objetos JavaScript".
mpen

Respuestas:

105

jQuery.parseJSON () debería devolver un objeto de tipo "objeto", si la cadena era JSON, por lo que solo tienes que comprobar el tipo con 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
fuente
29
También es posible que deba usar un try / catch para las excepciones si es posible que parseJSON esté tratando con algo diferente a los valores JSON (es decir, HTML)
acorncom
2
Antes de jQuery 1.9, $ .parseJSON devolvía nulo en lugar de arrojar un error si se pasaba una cadena vacía, nula o indefinida, aunque esos no son JSON válidos. Enlace del sitio jquery
gloomy.penguin
7
Esta solución no es la mejor, ¡porque devuelve "SyntaxError: JSON.parse: unexpected character"error! , Creo que la mejor solución es usar try / catch que dice Serguei Fedorovaquí: stackoverflow.com/questions/4295386/…
Nabi KAZ
2
Si no desea usar jquery, puede usar Vanilla JS verificando el tipo de constructor como se describe aquí: stackoverflow.com/questions/11182924/…
Mat
2
Esta respuesta es incorrecta, la respuesta de Serguei Federov debería ser la respuesta aceptada.
Serj Sagan
148

La solución elegida no me funciona realmente porque obtengo una

     "Unexpected Token <" 

error en Chrome. Esto se debe a que el error se produce tan pronto como el análisis se encuentra con un carácter desconocido. Sin embargo, hay una forma de evitar esto si solo devuelve valores de cadena a través de ajax (que puede ser bastante útil si está utilizando PHP o ASPX para procesar solicitudes de ajax y podría o no devolver JSON según las condiciones)

La solución es bastante simple, puede hacer lo siguiente para verificar si fue una devolución JSON válida

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

Como he dicho antes, esta es la solución si está devolviendo material de tipo cadena de su solicitud AJAX o si está devolviendo un tipo mixto.

Serguei Fedorov
fuente
La pregunta no se trata de cadenas que no sean JSON en ningún momento. El servidor siempre devuelve un JSON válido (una cadena falsetambién es JSON válido). La pregunta trata solo sobre un punto: cómo diferenciar si la cadena JSON analizada es un booleano falseo un objeto
Dr. Molle
2
Consideración de rendimiento: al envolver esto en una función, asegúrese de no analizar el json dos veces (una vez dentro de la captura de prueba y otra en el código que llama a la función).
Michiel Cornille
Es un ayudantes funcionan isJSON () que puede utilizar: isJSON(someValue).
Chofoteddy
19

Solución 3 (forma más rápida)

/**
 * @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;
    }
}

Puedes usarlo:

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

La mejor forma de validar que un objeto es de tipo JSON o matriz es la siguiente:

var a = [],
    o = {};

Solución 1

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

Solucion 2

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

Pero, estrictamente hablando, una matriz es parte de una sintaxis JSON. Por lo tanto, los dos ejemplos siguientes son parte de una respuesta JSON:

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

Y:

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

AJAX / JQuery (recomendado)

Si usa JQuery para traer información a través de AJAX. Te recomiendo que pongas en el atributo "dataType" el valor "json", de esa forma si obtienes un JSON o no, JQuery lo valida por ti y lo da a conocer a través de sus funciones "éxito" y "error". Ejemplo:

$.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
fuente
13

Si tiene jQuery, use isPlainObject .

if ($.isPlainObject(my_var)) {}
thnee
fuente
5
Si usa isPlainObject en una cadena, devuelve falso, por ejemplo, jQuery.isPlainObject ('{}')
Roy Shoa
Más importante aún, si contiene un valor no similar a JSON como propiedad, de acuerdo con los documentos, esta función seguirá regresando 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
fuente
4

Dado que es solo un objeto falso y json, ¿por qué no verifica si es falso? De lo contrario, debe ser json.

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

Sé que este hilo ya ha sido respondido, pero venir aquí realmente no resolvió mis problemas, encontré esta función en otro lugar. tal vez alguien que venga aquí lo encontrará de alguna utilidad;

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
fuente
1
var data = 'json string ?';
var jdata = null;
try
{
    jdata = $.parseJSON(data);  
}catch(e)
{}

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

Si desea probar explícitamente JSON válido (a diferencia de la ausencia del valor devuelto false), puede usar un enfoque de análisis como se describe aquí .

Ken Redler
fuente
0

Realmente no me gusta la respuesta aceptada. En primer lugar, requiere jQuery, que no siempre está disponible o es obligatorio. En segundo lugar, hace una cadena completa del objeto que para mí es excesivo. Aquí hay una función simple que detecta a fondo si un valor es similar a JSON, usando nada más que algunas partes de la biblioteca lodash para genérico.

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
}

Incluso me he tomado el tiempo de ponerlo en npm como paquete: https://npmjs.com/package/is-json-object . Úselo junto con algo como Webpack para obtenerlo en el navegador.

¡Espero que esto ayude a alguien!

samvv
fuente
0

Estoy usando esto para validar el objeto JSON

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

Estoy usando esto para validar JSON String

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

Probé todas las respuestas sugeridas, nada funcionó para mí, así que tuve que usar

jQuery.isEmptyObject()

azada que ayuda a alguien más con este problema

Jay Rizzi
fuente
-1

Debe devolver json siempre , pero cambie su estado , o en el siguiente ejemplo, la propiedad ResponseCode :

if(callbackResults.ResponseCode!="200"){
    /* Some error, you can add a message too */
} else {
    /* All fine, proceed with code */
};
Kobe
fuente
@bart, puede proporcionar el objeto en la condición if, que hará la verificación.
kobe