I wanted to add a .toJson
method to an instantiated JavaScript object, which would allow me to get the stringified object instance without functions and prototype, to transmit during a request.
However, it seems like the actual name of the function 'toJSON' as a method name impacts the ability of JavaScript engine (at least in V8) to run the function - that is, if you rename the same exact function to "JSON" instead of "toJSON", it works, however, as "toJSON", it causes a Maximum Callstack error. See example:
function P1(name, age){
this.name = name;
this.age= age;
this.toJSON = function(){
return JSON.stringify(this);
}
}
function P2(name, age){
this.name = name;
this.age= age;
this.JSON = function(){
return JSON.stringify(this);
}
}
// This causes an error: Uncaught RangeError: Maximum call stack size exceeded(…)
var p1 = new P1('Memory Error', 10);
try {
p1.toJSON();
} catch(e){
console.log(e);
}
var p2 = new P2('No Error', 20);
p2.JSON();
Is this an expected behavior of JavaScript? Does it have something to do with "toJSON" being a native method (note: I have verified that on an instantiated object as above, there is no toJSON method on the prototype that would interfere with a redefinition on the instance)? I am trying to determine if I should report this as a bug to V8 team, or this is explainable by someone who knows more about the spec.
Thanks
I wanted to add a .toJson
method to an instantiated JavaScript object, which would allow me to get the stringified object instance without functions and prototype, to transmit during a request.
However, it seems like the actual name of the function 'toJSON' as a method name impacts the ability of JavaScript engine (at least in V8) to run the function - that is, if you rename the same exact function to "JSON" instead of "toJSON", it works, however, as "toJSON", it causes a Maximum Callstack error. See example:
function P1(name, age){
this.name = name;
this.age= age;
this.toJSON = function(){
return JSON.stringify(this);
}
}
function P2(name, age){
this.name = name;
this.age= age;
this.JSON = function(){
return JSON.stringify(this);
}
}
// This causes an error: Uncaught RangeError: Maximum call stack size exceeded(…)
var p1 = new P1('Memory Error', 10);
try {
p1.toJSON();
} catch(e){
console.log(e);
}
var p2 = new P2('No Error', 20);
p2.JSON();
Is this an expected behavior of JavaScript? Does it have something to do with "toJSON" being a native method (note: I have verified that on an instantiated object as above, there is no toJSON method on the prototype that would interfere with a redefinition on the instance)? I am trying to determine if I should report this as a bug to V8 team, or this is explainable by someone who knows more about the spec.
Thanks
Share Improve this question asked Sep 29, 2015 at 16:50 netpoeticanetpoetica 3,4254 gold badges29 silver badges37 bronze badges 2-
3
JSON.stringify
calls the object'stoJSON
method. This callsJSON.stringify
which callstoJSON
which callsJSON.stringify
... – gen_Eric Commented Sep 29, 2015 at 16:53 -
4
JSON.stringify()
will call thetoJSON()
function defined on your object. Hopefully you can see why you have the problem... – Jeff Mercado Commented Sep 29, 2015 at 16:53
1 Answer
Reset to default 15This is not what the .toJSON
method is used for. You use .toJSON
to override the default stringification behavior. The .toJSON
is called internally by JSON.stringify
, you don't need to call it on your own. .toJSON
can return a string, object, array, whatever you want to be stringified in the response from JSON.stringify
.
Your .toJSON
method needs to do something other than call JSON.stringify(this)
. Right now you are getting an infinite loop since JSON.stringify(this)
calls the object's .toJSON
, and so on.
Try something like this:
function P1(name, age){
this.name = name;
this.age= age;
this.toJSON = function(){
return {
name: this.name,
age: this.age
};
}
}
var p1 = new P1('Test', 10);
console.log(JSON.stringify(p1));