Basically I have something like this:
MyClass
var MyClass = function() {
this.num = 123;
this.obj = new MyInnerClass();
};
MyClass.prototype.stringify = function() {
return JSON.stringify(this);
};
MyInnerClass
var MyInnerClass = function() {
this.foo = 456;
this.bar = 'bonjour!';
};
MyInnerClass.prototype.stringify = function() {
return JSON.stringify(this, function(k, v) {
// ignores 'foo' attribute
return k !== 'foo' ? v : undefined;
});
};
Each class has its own stringify
implementation, so when I do:
var mc = new MyClass();
mc.stringify();
I would like something like calling MyClass.stringify
should stringify my mc
object, but respecting inner objects stringify
implementations. Once we don't have control over the JSON.stringify
method logic, is there a good way to do that?
Thank you!
If you look on MDN at JSON.stringify, you'll see a section that talks about a toJSON property
If an object being stringified has a property named toJSON whose value is a function, then the toJSON() method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON() method when called will be serialized.
Basically, define a toJSON method for your Object which creates another Object, but one that can be serialised as you desire. Then JSON.stringify
will serialise the return of your toJSON
function instead, i.e.
var MyClass = function() {
this.num = 123;
this.obj = new MyInnerClass();
};
var MyInnerClass = function() {
this.foo = 456;
this.bar = 'bonjour!';
};
MyInnerClass.prototype.toJSON = function () {
// shallow clone `this`, except .foo
var o = Object.create(null), k, blacklist = ['foo'];
for (k in this) // loop over enumerable properties
if (Object.prototype.hasOwnProperty.call(this, k)) // ignore inherited properties
if (blacklist.indexOf(k) === -1) // ignore blacklisted properties
o[k] = this[k]; // add to our clone
return o;
};
JSON.stringify(new MyClass()); // '{"num":123,"obj":{"bar":"bonjour!"}}'
This will also replace your need for the current stringify method.
Sadly you can't call JSON.stringify(this)
inside .toJSON
because it becomes circular and you get RangeError: Maximum call stack size exceeded
, but you'd not get the desired result this way anyway as it would be serialised a second time, giving you a String in your JSON.