Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/430.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查对象在JavaScript中是否可序列化的可靠方法_Javascript_Json_Serialization - Fatal编程技术网

检查对象在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,因此需要递归应

是否有一种已知的方法或库已经有一个助手来评估对象在JavaScript中是否可序列化

我尝试了以下方法,但它不包括原型属性,因此它提供了误报:

_.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: () => {}}}]))
        });

    });

}