Why doesn't JSON.stringify serialize non-enumerable properties?

I am serializing objects for JSON strings with JavaScript,

I noticed that only the enumerated properties of the object get serialized:

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 ]

I wonder why this is? I looked at the json2 documentation page. I could not find this behavior to be documented anywhere.

I suspect this is the result of using for... in loops that only execute the [[enumerated]] properties (at least in the case of json2 ). This can probably be done using Object.getOwnPropertyNames , which returns both enumerated and non-enumerated properties. This can be problematic for serialization (due to deserialization).

TL; DR

  • Why JSON.stringify only serialize enumerated properties?
  • Is this behavior documented anywhere?
  • How can I serialize non-enumerable properties on my own?
+7
source share
2 answers

It is specified in the ES5 specification .

If Type (value) is Object and IsCallable is 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. 

So let's take a look at JO . Here is the relevant section:

Let K be an internal list of strings consisting of the names of all its own property values, the [[Enumerable]] attribute is true . The order of the lines should be the same as in the standard built-in function Object.keys.

+9
source

As @ThiefMaster answered above, this is stated in the spec

however, if you know the names of non-enumerable properties that you would like to serialize in advance, you can achieve this by passing the replace function as the second parameter to JSON.stringify () ( MDN documentation ), like so:

 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); 
0
source

All Articles