为什么JSON.stringify没有序列化不可枚举的属性?

时间:2013-03-31 20:01:15

标签: javascript json serialization

我正在使用JavaScript将对象序列化为JSON字符串,

我注意到只有可枚举的对象属性被序列化了:

var a = Object.create(null,{
  x: { writable:true, configurable:true, value: "hello",enumerable:false },
  y: { writable:true, configurable:true, value: "hello",enumerable:true }
});
document.write(JSON.stringify(a)); //result is {"y":"hello"}

[pen]

我想知道为什么会这样?我搜索了MDN pagejson2解析器文档。 我无法在任何地方找到这种行为。

我怀疑这是使用for... inonly go through [[enumerable]]属性循环的结果(至少在json2的情况下)。这可以通过Object.getOwnPropertyNames之类的东西来完成,它返回可枚举和不可枚举的属性。 但序列化可能会有问题(由于反序列化)。

TL;博士

  • 为什么JSON.stringify仅序列化可枚举属性?
  • 这种行为是否记录在任何地方?
  • 如何自行实现序列化非可枚举属性?

2 个答案:

答案 0 :(得分:9)

它在ES5 spec中指定。

  

如果Type(value)是Object,并且IsCallable(value)是false

If the [[Class]] internal property of value is "Array" then

    Return the result of calling the abstract operation JA with argument value.

Else, return the result of calling the abstract operation JO with argument value.

那么,让我们看一下JO。以下是相关部分:

  

设K是一个内部字符串列表,由 [[Enumerable]]属性为真的所有属性值组成。字符串的顺序应与Object.keys标准内置函数使用的顺序相同。

答案 1 :(得分:0)

正如@ThiefMaster回答的那样,它是在规范中指定的

但是,如果您知道要提前序列化的不可枚举属性的名称,则可以通过将替换函数作为第二个参数传递给JSON.stringify()(documentation on MDN ),就像这样

var o = {
  prop: 'propval',
}

Object.defineProperty(o, 'propHidden', {
  value: 'propHiddenVal',
  enumerable: false,
  writable: true,
  configurable: true
});

var s = JSON.stringify(o, (key, val) => {
  if (!key) {
    // Initially, the replacer function is called with an empty string as key representing the object being stringified. It is then called for each property on the object or array being stringified.
    if (typeof val === 'object' && val.hasOwnProperty('propHidden')) {
      Object.defineProperty(val, 'propHidden', {
        value: val.propHidden,
        enumerable: true,
        writable: true,
        configurable: true
      });

    }
  }
  return val;
});

console.log(s);