0

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!

0

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, I saw that page about toJSON. So that's the only way.
Well, I'm afraid that it won't work if I have a third inner object inside MyInnerClass that also implements a stringify method. But I think I can deal with it by making some adjusts to this function. Thanks anyway, Paul.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.