9

我正在使用 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"}

[]

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

我怀疑这是使用仅通过 [[enumerable]]for... in属性的循环的结果(至少在 的情况下)。这可能可以通过返回可枚举和不可枚举属性的类似方法来完成。但是,序列化可能会有问题(由于反序列化)。json2Object.getOwnPropertyNames

tl;博士

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

2 回答 2

13

它在ES5 规范中指定。

如果 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]] 属性为 true 的 value 的所有自身属性的名称组成。字符串的顺序应与 Object.keys 标准内置函数使用的顺序相同。

于 2013-03-31T20:06:36.450 回答
0

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

但是,如果您知道要提前序列化的不可枚举属性的名称,则可以通过将替换函数作为第二个参数传递给 JSON.stringify() 来实现它(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);

于 2019-07-07T19:49:54.333 回答