检查对象在JavaScript中是否可序列化的可靠方法
是否有一种已知的方法或库已经有一个助手来评估对象在JavaScript中是否可序列化 我尝试了以下方法,但它不包括原型属性,因此它提供了误报:检查对象在JavaScript中是否可序列化的可靠方法,javascript,json,serialization,Javascript,Json,Serialization,是否有一种已知的方法或库已经有一个助手来评估对象在JavaScript中是否可序列化 我尝试了以下方法,但它不包括原型属性,因此它提供了误报: _.isEqual(obj, JSON.parse(JSON.stringify(obj)) 还有另一个lodash函数可以让我更接近事实,\uu.isPlainObject。但是,虽然.isPlainObject(new MyClass())返回false,.isPlainObject({x:new MyClass()})返回true,因此需要递归应
_.isEqual(obj, JSON.parse(JSON.stringify(obj))
还有另一个lodash函数可以让我更接近事实,\uu.isPlainObject
。但是,虽然.isPlainObject(new MyClass())
返回false
,.isPlainObject({x:new MyClass()})
返回true
,因此需要递归应用它
在我独自探讨这个问题之前,有人知道一种已经可靠的方法来检查JSON.parse(JSON.stringify(obj))
是否会产生与obj
相同的对象吗
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;
}
递归地迭代所有给定的对象属性。它们可以是:
- 普通对象(“由对象构造函数创建的对象或[[Prototype]]为null的对象。”-来自lodash文档)
- 阵列
- 字符串,数字,布尔值
- 未定义
obj
中的任何其他值都将使其被理解为“不可序列化”
(老实说,我不是绝对肯定我没有忽略检查某些可序列化/不可序列化的数据类型,事实上我认为这取决于“可序列化”的定义-欢迎任何评论和建议。)最后,我创建了我自己的方法,利用下划线/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;
};
这里是@treznik解决方案的ES6版本
export function isSerialisable(obj) {
const nestedSerialisable = ob => (_.isPlainObject(ob) || _.isArray(ob)) &&
_.every(ob, isSerialisable);
return _.overSome([
_.isUndefined,
_.isNull,
_.isBoolean,
_.isNumber,
_.isString,
nestedSerialisable
])(obj)
}
测验
这是一个奇怪的问题,原型属性不应该是stringized对象的一部分,而且任何其他属性都是可序列化的,所以通常不需要检查这个问题?我在这一点上支持@adeneo。stringify旨在将存储在JavaScript数据结构中的数据单独转换为字符串格式,以简化所述数据的传输。函数(如原型属性)不是有效的JSON;因此,它们不会被严格化。为什么需要检查它们是否可序列化?你不确定你是被传递了一个POJO还是一个实例?@treznik这里的可序列化是什么意思?Json解析将仅字符串化对象的属性。你在寻找一种序列化每件事的方法吗?我的用例有点复杂,请参阅。基本上我有一个JSON“fixtures”的在线编辑器。我想让用户编辑来自该fixture对象的可序列化键,但仍然扩展用户与来自初始fixture对象的不可序列化键的组合。希望它有意义。无论如何,看看我自己接受的答案,看看我想要什么,如果你有进一步的想法,请告诉我。谢谢,同时我也创造了类似的东西。因此,你的评论证实了这是一条道路(至少目前如此)。我还发布了我的解决方案,因为我发现它更简单。但是,如果您检测到任何输出差异,请告诉我。如果没有lodash--
typeof obj==='null'| |(obj.constructor=='Object&&obj.toString()==''[Object Object Object]')
,则对于null
(可JSON序列化)返回false
,对于未定义的
(不可序列化)返回true
。是的,我想说你的代码比我的代码更好、更一致(到处使用lodash方法)。我只想补充一点,除非您非常明确什么是“可序列化”(运行自定义检查),否则简单的JSON.parse(JSON.stringify(obj))
可能就足够了。之所以使用此选项,是因为我的linter抱怨中的for…in
if(u.find(obj,element=>!isSerializable(element))!=null){return false;
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: () => {}}}]))
});
});
}