31
Simple way to serialize objects to JSON in TypeScript
When we’re building an application we often need to serialize objects to JSON for storing them in a key value store (e.g. Redis) or publishing them on a queue.
While there are libraries available like class-transformer or io-ts, there's an easier way to serialize/unserialize objects to JSON.
In both cases we also need to depend on an extra package.
What none of these packages offer is a way to deal with backwards compatibility (e.g. when you've added or renamed a property of an object).
I also want something simple.
Let's say we want to serialize a user with an email value object to JSON:
class Email {
constructor(private readonly email: string) {
if (!this.email.includes("@")) {
throw new Error(`Not an email address: ${this.email}`);
}
}
asString() {
return this.email;
}
}
class User {
constructor(
private readonly id: string,
private readonly email: Email
) {
if (!this.id) {
throw new Error("User ID cannot be empty!");
}
}
private toObject() {
return {
id: this.id,
email: this.email.asString(),
}
}
serialize() {
return JSON.stringify(this.toObject());
}
static fromSerialized(serialized: string) {
const user: ReturnType<User["toObject"]> = JSON.parse(serialized);
return new User(
user.id,
new Email(user.email)
);
}
}
const user = new User("id", new Email("[email protected]"));
const json = user.serialize();
const json = await redis.get(key);
const user = User.fromSerialized(json);
- We add a
private toObject()
method that returns a plain object for theUser
(since JSON is not aware of classes). - We add a
serialize()
method that returns the plain object as a JSON string. - We add a
static unserialize(serialized: string)
method to recreate theUser
instance.JSON.parse
hasany
as return type, which results in no type checking or autocompletion. We can grab the return type of thetoObject()
method withReturnType<User["toObject"]>
to regain type checking/autocompletion. - Always guard against invalid state in your entities. This makes sure that a
User
always has an ID and a valid email address. - Look ma, no packages needed!
Let me know if this blogpost was useful! 😊
31