Ответ 1
На основе ваших комментариев кажется, что вы не хотите знать, является ли строка допустимой JSON, а скорее, может ли объект быть успешно закодирован как JSON (например, не содержит никаких объектов Date, определенные классы и т.д.).
Здесь есть два подхода: попытайтесь проанализировать объект и его "детей" (следить за рекурсивными объектами) или сосать-и-видеть. Если у вас есть JSON-кодер под рукой (JSON.stringify
в последних браузерах или плагин, например jquery-json), последний, вероятно, является более простым и более надежный подход:
function canJSON(value) {
try {
JSON.stringify(value);
return true;
} catch (ex) {
return false;
}
}
Анализ объекта напрямую требует, чтобы вы могли определить, является ли он "простым" объектом (т.е. создается с использованием объектного литерала или new Object()
), что, в свою очередь, требует, чтобы вы могли получить его прототип, всегда легко. Я нашел следующий код для работы в IE7, FF3, Opera 10, Safari 4 и Chrome (и, скорее всего, другие версии этих браузеров, которые я просто не тестировал).
var getPrototypeOf;
if (Object.getPrototypeOf) {
getPrototypeOf = Object.getPrototypeOf;
} else if (typeof ({}).__proto__ === "object") {
getPrototypeOf = function(object) {
return object.__proto__;
}
} else {
getPrototypeOf = function(object) {
var constructor = object.constructor;
if (Object.prototype.hasOwnProperty.call(object, "constructor")) {
var oldConstructor = constructor; // save modified value
if (!(delete object.constructor)) { // attempt to "unmask" real constructor
return null; // no mask
}
constructor = object.constructor; // obtain reference to real constructor
object.constructor = oldConstructor; // restore modified value
}
return constructor ? constructor.prototype : null;
}
}
// jQuery.isPlainObject() returns false in IE for (new Object())
function isPlainObject(value) {
if (typeof value !== "object" || value === null) {
return false;
}
var proto = getPrototypeOf(value);
// the prototype of simple objects is an object whose prototype is null
return proto !== null && getPrototypeOf(proto) === null;
}
var serializablePrimitives = { "boolean" : true, "number" : true, "string" : true }
function isSerializable(value) {
if (serializablePrimitives[typeof value] || value === null) {
return true;
}
if (value instanceof Array) {
var length = value.length;
for (var i = 0; i < length; i++) {
if (!isSerializable(value[i])) {
return false;
}
}
return true;
}
if (isPlainObject(value)) {
for (var key in value) {
if (!isSerializable(value[key])) {
return false;
}
}
return true;
}
return false;
}
Так что да... Я бы рекомендовал подход try/catch.; -)