Jak mogę sprawdzić, czy wartość jest obiektem JSON?

102

Mój kod po stronie serwera zwraca wartość, która jest obiektem json w przypadku sukcesu i ciągiem znaków „false” w przypadku niepowodzenia. Jak mogę teraz sprawdzić, czy zwrócona wartość jest obiektem json?

Bart
źródło
2
Jeśli jest to faktycznie „Twój” kod po stronie serwera, dlaczego nie mieć pola statusu w wyniku JSON, zamiast tworzyć sytuację „czasami-to-JSON-a-czasami-nie-jest-nie” ...?
HostileFork mówi, że nie ufaj SE
@Hostile Ze względu na debugowanie. Nigdy teraz nie wiesz, jakiego rodzaju awarię zgłosi serwer iw tym momencie json nie jest używany.
bart
1
Nadal nie widzę, w jaki sposób posiadanie kodu błędu (jako nazwanego pola) w odpowiedzi serwera mogłoby to podważyć. To wystarczy dla Freebase! wiki.freebase.com/wiki/MQL_errors
HostileFork mówi, że nie ufaj SE
Zmień zaakceptowaną odpowiedź na Serguei Federov, jeśli możesz, obecnie zaakceptowana odpowiedź jest nieprawidłowa.
Serj Sagan
Co to jest „obiekt JSON”? Istnieją ciągi JSON i obiekty JS, ale nie ma czegoś takiego jak „obiekt JavaScript Object Notation”.
mpen

Odpowiedzi:

107

jQuery.parseJSON () powinna zwrócić obiekt typu "object", jeśli ciąg znaków był JSON, więc musisz tylko sprawdzić typ za pomocą 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
źródło
29
Może być również konieczne użycie try / catch dla wyjątków, jeśli jest możliwe, że parseJSON będzie miał do czynienia z czymś innym niż wartości JSON (tj. HTML)
acorncom
2
Przed jQuery 1.9 $ .parseJSON zwracał wartość null zamiast zgłaszać błąd, jeśli przekazano pusty ciąg, wartość null lub undefined, nawet jeśli nie są to prawidłowe dane JSON. jQuery link do strony
gloomy.penguin
7
To rozwiązanie nie jest najlepsze, bo zwraca "SyntaxError: JSON.parse: unexpected character"błąd! , Myślę, że najlepszym rozwiązaniem jest użycie try / catch, które zostało powiedziane Serguei Fedorovtutaj: stackoverflow.com/questions/4295386/ ...
Nabi KAZ
2
Jeśli nie chcesz używać jquery, możesz użyć vanilla JS, sprawdzając typ konstruktora, jak opisano tutaj: stackoverflow.com/questions/11182924/ ...
Mat.
2
Ta odpowiedź jest nieprawidłowa, odpowiedź Siergieja Federowa powinna być odpowiedzią zaakceptowaną.
Serj Sagan
148

Wybrane rozwiązanie tak naprawdę nie działa dla mnie, ponieważ otrzymuję plik

     "Unexpected Token <" 

błąd w przeglądarce Chrome. Dzieje się tak, ponieważ błąd jest generowany, gdy tylko pojawi się parsowanie i nieznany znak. Istnieje jednak sposób na obejście tego problemu, jeśli zwracasz tylko wartości ciągów przez ajax (co może być dość przydatne, jeśli używasz PHP lub ASPX do przetwarzania żądań Ajax i może zwracać JSON lub nie w zależności od warunków)

Rozwiązanie jest dość proste, możesz wykonać następujące czynności, aby sprawdzić, czy był to prawidłowy zwrot JSON

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

Jak powiedziałem wcześniej, jest to rozwiązanie, jeśli zwracasz tekst typu string z żądania AJAX lub zwracasz typ mieszany.

Serguei Fedorov
źródło
W żadnym wypadku nie chodzi o ciągi inne niż JSON. Serwer zwraca zawsze prawidłowy kod JSON (ciąg znaków falsejest również prawidłowym plikiem JSON). Pytanie dotyczy tylko jednego punktu: jak rozróżnić, czy przeanalizowany ciąg JSON jest wartością logiczną, falseczy obiektem
Dr.Molle,
2
Zagadnienia dotyczące wydajności: opakowując to w funkcję, upewnij się, że nie analizujesz json dwa razy (raz wewnątrz try catch i raz w kodzie, który wywołuje funkcję).
Michiel Cornille
Jest to pomocnicy funkcjonować isJSON () , które można użyć: isJSON(someValue).
Chofoteddy
19

Rozwiązanie 3 (najszybszy sposób)

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

Możesz tego użyć:

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

Najlepszym sposobem sprawdzenia, czy obiekt jest typu JSON lub tablicy, jest następujący:

var a = [],
    o = {};

Rozwiązanie 1

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

Rozwiązanie 2

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

Ale, ściśle mówiąc, tablica jest częścią składni JSON. Dlatego poniższe dwa przykłady są częścią odpowiedzi JSON:

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

I:

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

AJAX / JQuery (zalecane)

Jeśli używasz JQuery do dostarczania informacji za pośrednictwem AJAX. Zalecam umieszczenie w atrybucie „dataType” wartości „json”, w ten sposób, jeśli otrzymasz kod JSON lub nie, JQuery zweryfikuje go za Ciebie i powiadomi o tym za pomocą funkcji „sukces” i „błąd”. Przykład:

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

Jeśli masz jQuery, użyj isPlainObject .

if ($.isPlainObject(my_var)) {}
kolano
źródło
5
Jeśli użyjesz isPlainObject na łańcuchu, zwróci ono false, np. JQuery.isPlainObject ('{}')
Roy Shoa
Co ważniejsze, jeśli jako właściwość zawiera wartość inną niż JSON, zgodnie z dokumentacją ta funkcja nadal zwróci 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
źródło
4

Ponieważ jest to tylko obiekt false i json, dlaczego nie sprawdzisz, czy jest to fałsz, w przeciwnym razie musi to być json.

if(ret == false || ret == "false") {
    // json
}
Andreas Wong
źródło
2

Wiem, że na ten wątek już odpowiedziano, ale przybycie tutaj nie rozwiązało tak naprawdę moich problemów, znalazłem tę funkcję gdzie indziej. może ktoś, kto tu przyjdzie, uzna to za pożyteczne;

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

if(jdata)
{
//use jdata
}else
{
//use data
}
Firas Abd Alrahman
źródło
0

Jeśli chcesz jawnie przetestować prawidłowy kod JSON (w przeciwieństwie do braku zwracanej wartości false), możesz użyć metody analizowania opisanej tutaj .

Ken Redler
źródło
0

Nie podoba mi się zaakceptowana odpowiedź. Przede wszystkim wymaga jQuery, które nie zawsze jest dostępne lub wymagane. Po drugie, dokonuje pełnej stringifikacji obiektu, który jest dla mnie przesadą. Oto prosta funkcja, która dokładnie wykrywa, czy wartość jest podobna do formatu JSON, używając tylko kilku części biblioteki lodash do generowania .

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
}

Poświęciłem nawet trochę czasu, aby umieścić go w npm jako pakiet: https://npmjs.com/package/is-json-object . Użyj go razem z czymś takim jak Webpack, aby pobrać go w przeglądarce.

Mam nadzieję, że to komuś pomoże!

samvv
źródło
0

Używam tego do walidacji obiektu JSON

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

Używam tego do sprawdzania poprawności ciągu JSON

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}
Abhishek Goel
źródło
0

Wypróbowałem wszystkie sugerowane odpowiedzi, nic nie działało, więc musiałem użyć

jQuery.isEmptyObject()

motyka, która pomaga komuś innemu rozwiązać ten problem

Jay Rizzi
źródło
-1

Należy zwrócić json zawsze , ale zmienić jego stan , czy w poniższym przykładzie Kod odpowiedzi nieruchomości:

if(callbackResults.ResponseCode!="200"){
    /* Some error, you can add a message too */
} else {
    /* All fine, proceed with code */
};
kobe
źródło
@bart, możesz po prostu dostarczyć obiekt w warunku if, który dokona sprawdzenia.
kobe