Как я могу проверить, является ли значение объектом json?

102

Мой серверный код возвращает значение, которое является объектом json в случае успеха и строкой false в случае ошибки. Как теперь проверить, является ли возвращаемое значение объектом json?

Барт
источник
2
Если это на самом деле «ваш» код на стороне сервера, почему бы не иметь поле статуса в результате JSON, а не создавать эту ситуацию «иногда-это-JSON-а-иногда-это-нет» ...?
HostileFork говорит, что не доверяйте SE
@Hostile Для отладки. Вы никогда не сможете понять, какой сбой выдаст сервер, и в этот момент json не используется.
Барт
1
Я до сих пор не понимаю, как наличие кода ошибки (в виде именованного поля) в ответе сервера может подорвать это. Для Freebase этого достаточно! wiki.freebase.com/wiki/MQL_errors
HostileFork говорит, что не доверяйте SE
Пожалуйста, измените принятый ответ на ответ Сергея Федорова, если можете, принятый в настоящее время ответ неверен.
Серж Саган
Что такое «объект json»? Есть строки JSON и объекты JS, но нет такой вещи, как «объект нотации объектов JavaScript».
mpen

Ответы:

107

jQuery.parseJSON () должен возвращать объект типа «объект», если строка была JSON, поэтому вам нужно только проверить тип с помощью 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
  }
}
Доктор Молле
источник
29
Возможно, также потребуется использовать try / catch для исключений, если возможно, что parseJSON будет иметь дело с чем-то другим, кроме значений JSON (например, HTML)
acorncom
2
До jQuery 1.9 $ .parseJSON возвращал null вместо того, чтобы выдавать ошибку, если ему была передана пустая строка, null или undefined, даже если они не являются допустимым JSON. Ссылка на сайт jquery
gloomy.penguin
7
Это решение не самое лучшее, т.к. возвращает "SyntaxError: JSON.parse: unexpected character"ошибку! , Я думаю, что лучшим решением является использование метода try / catch, о котором говорится Serguei Fedorovздесь: stackoverflow.com/questions/4295386/…
Nabi KAZ
2
Если вы не хотите использовать jquery, вы можете использовать vanilla JS, проверив тип конструктора, как описано здесь: stackoverflow.com/questions/11182924/…
Mat
2
Этот ответ неверен, ответ Сергея Федорова должен быть принятым ответом.
Серж Саган
148

Выбранное решение мне не подходит, потому что я получаю

     "Unexpected Token <" 

ошибка в Chrome. Это потому, что ошибка выдается, как только при синтаксическом анализе встречается неизвестный символ. Однако есть способ обойти это, если вы возвращаете только строковые значения через ajax (что может быть довольно полезно, если вы используете PHP или ASPX для обработки запросов ajax и можете или не можете возвращать JSON в зависимости от условий)

Решение довольно простое, вы можете сделать следующее, чтобы проверить, был ли это действительный возврат JSON.

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

Как я уже сказал, это решение, если вы либо возвращаете материал строкового типа из вашего запроса AJAX, либо если вы возвращаете смешанный тип.

Сергей Федоров
источник
Речь идет не о строках, отличных от JSON. Сервер всегда возвращает действительный JSON (строка falseтакже является допустимым JSON). Вопрос только в одном: как false
различить,
2
Оценка производительности: заключая это в функцию, убедитесь, что не анализируете json дважды (один раз внутри try catch и один раз в коде, вызывающем функцию.)
Michiel Cornille
Это помощники действуют isJSON () , которые вы можете использовать: isJSON(someValue).
Chofoteddy
19

Решение 3 (самый быстрый способ)

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

Вы можете использовать это:

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

Лучший способ подтвердить, что объект относится к типу JSON или массиву, выглядит следующим образом:

var a = [],
    o = {};

Решение 1

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

Решение 2

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

Но, строго говоря, массив - это часть синтаксиса JSON. Таким образом, следующие два примера являются частью ответа JSON:

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

И:

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

AJAX / JQuery (рекомендуется)

Если вы используете JQuery для передачи информации через AJAX. Я рекомендую вам указать в атрибуте «dataType» значение «json», таким образом, если вы получите JSON или нет, JQuery проверит его за вас и сделает это известным через свои функции «успех» и «ошибка». Пример:

$.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) {}
});
Чофотедди
источник
13

Если у вас есть jQuery, используйте isPlainObject .

if ($.isPlainObject(my_var)) {}
thnee
источник
5
Если вы используете isPlainObject в строке, он вернет false, например jQuery.isPlainObject ('{}')
Рой Шоа,
Что еще более важно, если оно содержит в качестве свойства значение, отличное от JSON, согласно документации, эта функция все равно будет возвращать true.
samvv 05
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
Луижп
источник
4

Поскольку это просто false и объект json, почему бы вам не проверить, ложно ли оно, иначе это должен быть json.

if(ret == false || ret == "false") {
    // json
}
Андреас Вонг
источник
2

Я знаю, что на эту ветку уже ответили, но приход сюда на самом деле не решил мои проблемы, я нашел эту функцию где-то еще. может быть, кто-то, придя сюда, найдет в нем какую-то пользу;

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
источник
1
var data = 'json string ?';
var jdata = null;
try
{
    jdata = $.parseJSON(data);  
}catch(e)
{}

if(jdata)
{
//use jdata
}else
{
//use data
}
Фирас Абд Альрахман
источник
0

Если вы хотите явно протестировать действительный JSON (в отличие от отсутствия возвращаемого значения false), вы можете использовать подход синтаксического анализа, как описано здесь .

Кен Редлер
источник
0

Мне не очень нравится принятый ответ. В первую очередь для этого требуется jQuery, который не всегда доступен или необходим. Во-вторых, он выполняет полную структуризацию объекта, что для меня является излишним. Вот простая функция, которая тщательно определяет, является ли значение JSON-подобным, используя не что иное, как несколько частей библиотеки lodash для универсальности.

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
}

Я даже нашел время, чтобы поместить его в npm как пакет: https://npmjs.com/package/is-json-object . Используйте его вместе с чем-то вроде Webpack чтобы получить его в браузере.

Надеюсь, это кому-то поможет!

самвв
источник
0

Я использую это для проверки объекта JSON

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

Я использую это для проверки строки JSON

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}
Абхишек Гоэль
источник
0

Я попробовал все предложенные ответы, у меня ничего не получилось, поэтому мне пришлось использовать

jQuery.isEmptyObject()

мотыга, которая помогает кому-то еще с этой проблемой

Джей Рицци
источник
-1

Вы должны всегда возвращать json , но изменять его статус или, в следующем примере, свойство ResponseCode :

if(callbackResults.ResponseCode!="200"){
    /* Some error, you can add a message too */
} else {
    /* All fine, proceed with code */
};
Кобе
источник
@bart, вы можете просто указать объект в условии if, который выполнит проверку.
kobe