是否有已知的方法或库已经有一个帮助器来评估对象是否可以在JavaScript中序列化?
我尝试了以下内容,但它没有涵盖原型属性,因此它提供了误报:
_.isEqual(obj, JSON.parse(JSON.stringify(obj))
还有另一个lodash函数可能让我更接近真相,_.isPlainObject
。但是,当_.isPlainObject(new MyClass())
返回false
时,_.isPlainObject({x: new MyClass()})
会返回true
,因此需要递归应用。
在我自己冒昧之前,是否有人知道一种已经可靠的方法来检查JSON.parse(JSON.stringify(obj))
是否会实际产生与obj
相同的对象?
答案 0 :(得分:3)
function isSerializable(obj) {
var isNestedSerializable;
function isPlain(val) {
return (typeof val === 'undefined' || typeof val === 'string' || typeof val === 'boolean' || typeof val === 'number' || Array.isArray(val) || _.isPlainObject(val));
}
if (!isPlain(obj)) {
return false;
}
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (!isPlain(obj[property])) {
return false;
}
if (typeof obj[property] == "object") {
isNestedSerializable = isSerializable(obj[property]);
if (!isNestedSerializable) {
return false;
}
}
}
}
return true;
}
递归迭代所有给定的对象属性。它们可以是:
传递obj
内任何地方的任何其他值都会导致它被理解为"不可序列化"。
(老实说,我并不是绝对肯定的,我没有省略检查某些可序列化/不可序列化的数据类型,实际上我认为这取决于" serializable&#34的定义; - 欢迎任何意见和建议。)
答案 1 :(得分:2)
最后,我创建了自己的方法,利用了Underscore / Lodash的_.isPlainObject
。我的功能最终类似于@bardzusny提出的,但我也发布了我的功能,因为我更喜欢简单/清晰。随意概述利弊。
var _ = require('lodash');
exports.isSerializable = function(obj) {
if (_.isUndefined(obj) ||
_.isNull(obj) ||
_.isBoolean(obj) ||
_.isNumber(obj) ||
_.isString(obj)) {
return true;
}
if (!_.isPlainObject(obj) &&
!_.isArray(obj)) {
return false;
}
for (var key in obj) {
if (!exports.isSerializable(obj[key])) {
return false;
}
}
return true;
};
答案 2 :(得分:1)
这是@treznik解决方案的稍微更多的Lodashy ES6版本
export function isSerialisable(obj) {
const nestedSerialisable = ob => (_.isPlainObject(ob) || _.isArray(ob)) &&
_.every(ob, isSerialisable);
return _.overSome([
_.isUndefined,
_.isNull,
_.isBoolean,
_.isNumber,
_.isString,
nestedSerialisable
])(obj)
}
测试
describe.only('isSerialisable', () => {
it('string', () => {
chk(isSerialisable('HI'));
});
it('number', () => {
chk(isSerialisable(23454))
});
it('null', () => {
chk(isSerialisable(null))
});
it('undefined', () => {
chk(isSerialisable(undefined))
});
it('plain obj', () => {
chk(isSerialisable({p: 1, p2: 'hi'}))
});
it('plain obj with func', () => {
chkFalse(isSerialisable({p: 1, p2: () => {}}))
});
it('nested obj with func', () => {
chkFalse(isSerialisable({p: 1, p2: 'hi', n: { nn: { nnn: 1, nnm: () => {}}}}))
});
it('array', () => {
chk(isSerialisable([1, 2, 3, 5]))
});
it('array with func', () => {
chkFalse(isSerialisable([1, 2, 3, () => false]))
});
it('array with nested obj', () => {
chk(isSerialisable([1, 2, 3, { nn: { nnn: 1, nnm: 'Hi'}}]))
});
it('array with newsted obj with func', () => {
chkFalse(isSerialisable([1, 2, 3, { nn: { nnn: 1, nnm: () => {}}}]))
});
});
}