Custom JSON.stringify to Classes with the toJSON method

The toJSON method allows you to tell JSON.stringify how to print out your Class. This can be pretty useful…

Why Stringify Objects?

The answer for that is as usual – there are many reasons. The most obvious one is to send the object to a remote service as payload to a request. Other reasons can be:

  • Create a hash from a JSON (I learned this trick from Cesium back in the days),
  • deep clone an object (const dupe = JSON.parse(JSON.stringify(duped));) – not really recommended in production, but possible…
  • Logging

There are probably more reasons, but that’s not the point. The thing is – there are times when you’d like to stringify your objects.

Your Class as a JSON

Let’s create a simple class and stringify its instance:

class MyClass {
#somethingCool = 5;
get somethingCool() {
return this.#somethingCool;
}
set somethingCool(value) {
this.#somethingCool = value;
}
}
const x = new MyClass();
JSON.stringify(x); // '{}'
x.somethingCool = 10;
JSON.stringify(x); // '{}'
view raw toJSON.js hosted with ❤ by GitHub

MyClass will have a private property #somethingCool which is not accessible outside the class itself. It has a setter and a getter to interact with it. Trying to stringify our class’s instance results in an empty object:

Stringifying my class gives me an empty object…

Is this how we’d expect our JSON to look like? I think that in most cases we would not… Imagine your logs missing a crucial property that’s built from a getter. Bummer…

Defining how to your class is stringified using toJSON

By adding a toJSON method to your class, JSON.stringify will know how to print your class instance:

class MyClass {
#somethingCool = 5;
get somethingCool() {
return this.#somethingCool;
}
set somethingCool(value) {
this.#somethingCool = value;
}
toJSON() {
return {
somethingCool: this.somethingCool,
}
}
}
const x = new MyClass();
JSON.stringify(x); // '{"somethingCool": 5}'
x.somethingCool = 10;
JSON.stringify(x); // '{"somethingCool": 10}'
view raw toJSON.js hosted with ❤ by GitHub

The difference between the last class above and the class in the former part of the article is the toJSON method. In this case, it returns an object with a somethingCool property with the value of somethingCool as returned from our getter.

Using JSON.stringify results in what we’d expect:

The class with a custom toJSON stringified.

Summary

JSON.stringify is a very useful tool. When using complex classes/objects with setters, getters and possible decorators the outcome of the stringification might lack some properties we’d expect to be there.

Using toJSON enables us to define what properties to output as part of the JSON output of the class instances.

Note we could achieve the same effect with the JSON.stringify replacer function (JSON.stringify(object, toJSONFunction).

Thanks a lot for Yuval Bar Levi and Piotr from xFAANG for the kind and thorough review!

Featured Photo by Ferenc Almasi on Unsplash

Sign up to my newsletter to enjoy more content:

0 0 votes
Article Rating
Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Piotr Zientara
2 years ago

I find this insightful, and I never thought of this `toJSON` getter. Looks like an intro to an interesting pattern that can help the code to remain clean. Thank you Yonatan for sharing this!