Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
354 views
in Technique[技术] by (71.8m points)

javascript - Why is JSON.stringify not serializing prototype values?

I have been working with a fair bit of JSON parsing and passing in Javascript within Node.js and browsers recently and bumped into this conundrum.

Any objects I created using a constructor, cannot be fully serialized fully via JSON.stringify, UNLESS I initialised all values within the constructor individually! This means my prototype becomes essentially useless in designing these classes.

Can someone shed some light on why the following doesn't serialize as I expect?

var ClassA = function () { this.initialisedValue = "You can see me!" };
ClassA.prototype = { initialisedValue : "You can't see me!", uninitialisedValue : "You can't see me!" };
var a = new ClassA();
var a_string = JSON.stringify(a);

What happens:

a_string == { "initialisedValue" : "You can see me!" }

I would expect:

a_string == { "initialisedValue" : "You can see me!", "uninitialisedValue" : "You can't see me!" }


Update (01-10-2019):

Finally noticed @ncardeli 's Answer, which does allow us to do something like the following to achieve my above requirement (in 2019!):

Replace var a_string = JSON.stringify(a);

with var a_string = JSON.stringify(a, Object.keys(ClassA.prototype));

Full code:

var ClassA = function () { this.initialisedValue = "You can see me!" };
ClassA.prototype = { initialisedValue : "You can't see me!", uninitialisedValue : "You can't see me!" };
var a = new ClassA();
var a_string = JSON.stringify(a, Object.keys(ClassA.prototype));

console.log(a_string)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Simply because this is the way JSON works. From the ES5 spec:

Let K be an internal List of Strings consisting of the names of all the own properties of value whose [[Enumerable]] attribute is true.

This makes sense, because there is no mechanism in the JSON specification for preserving information that would be required to parse a JSON string back into a JavaScript object if inherited properties were included. In your example, how would this parsed:

{ "initialisedValue" : "You can see me!", "uninitialisedValue" : "You can't see me!" }

There is no information to parse it into anything other than a flat object with 2 key-value pairs.

And if you think about it, JSON is not intended to map directly to JavaScript objects. Other languages must be able to parse JSON strings into simple structures of name-value pairs. If JSON strings contained all the information necessary to serialize complete JavaScript scope chains, other languages may be less capable of parsing that into something useful. In the words of Douglas Crockford on json.org:

These [hash tables and arrays] are universal data structures. Virtually all modern programming languages support them in one form or another. It makes sense that a data format that is interchangeable with programming languages also be based on these structures.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...