🚀 Jsonthis!

Jsonthis is a versatile TypeScript library designed to effortlessly convert your models into JSON objects.
It offers extensive support for custom property serializers, conditional property visibility, and more.
Jsonthis seamlessly integrates with the Sequelize ORM library, making it an ideal companion
for your data management needs. Explore the Sequelize support section for detailed instructions.
Table of Contents
Getting Started
Getting started with Jsonthis is quick and straightforward. Here's a simple example to get you going:
import {JsonField, Jsonthis} from "jsonthis";
class User {
id: number;
email: string;
@JsonField(false)
password: string;
registeredAt: Date = new Date();
constructor(id: number, email: string, password: string) {
this.id = id;
this.email = email;
this.password = password;
}
}
const user = new User(1, "john.doe@gmail.com", "s3cret");
const jsonthis = new Jsonthis();
console.log(jsonthis.toJson(user));
Additionally, the @JsonField decorator empowers you to fine-tune the serialization process of your properties
with Jsonthis. You can define custom serializers, change property visibility, and more.
Change Property Visibility
You can hide a property from the JSON output by setting the visible option to false.
You can achieve this by passing false to the @JsonField decorator directly
or by using the JsonFieldOptions object:
class User {
@JsonField({visible: false})
password: string;
}
Conditional Visibility
Jsonthis supports conditional property visibility based on a user-defined context.
This allows you to dynamically show or hide properties as needed.
In the following example, the email property is only visible if the email owner is requesting it:
function showEmailOnlyToOwner(_: string, state: JsonTraversalState, opts?: ToJsonOptions): boolean {
return opts?.context?.callerId === (state.parent as User)?.id;
}
class User {
id: number;
@JsonField({visible: showEmailOnlyToOwner})
email: string;
friend?: User;
constructor(id: number, email: string) {
this.id = id;
this.email = email;
}
}
const user = new User(1, "john.doe@gmail.com");
const jsonthis = new Jsonthis();
console.log(jsonthis.toJson(user, {context: {callerId: 1}}));
console.log(jsonthis.toJson(user, {context: {callerId: 2}}));
This also works with nested objects:
const user = new User(1, "john.doe@gmail.com");
user.friend = new User(2, "jane.doe@gmail.com");
const jsonthis = new Jsonthis();
console.log(jsonthis.toJson(user, {context: {callerId: 1}}));
console.log(jsonthis.toJson(user, {context: {callerId: 2}}));
Customizing Serialization
Change Property Name Casing
Jsonthis allows you to enforce specific casing for property names in the JSON output.
By default, Jsonthis uses whatever casing you use in your TypeScript code,
but you can change it to camelCase, snake_case, or PascalCase:
class User {
id: number = 123;
user_name: string = "john-doe";
registeredAt: Date = new Date();
}
const user = new User();
console.log(new Jsonthis().toJson(user));
console.log(new Jsonthis({case: "camel"}).toJson(user));
console.log(new Jsonthis({case: "snake"}).toJson(user));
console.log(new Jsonthis({case: "pascal"}).toJson(user));
Custom serializers
Jsonthis allows you to define custom serializers to transform property values during serialization.
These can be either global or field-specific.
Global Serializer
Register a global serializer for a specific type using Jsonthis.registerGlobalSerializer():
function dateSerializer(value: Date): string {
return value.toUTCString();
}
class User {
id: number = 1;
registeredAt: Date = new Date();
}
const jsonthis = new Jsonthis();
jsonthis.registerGlobalSerializer(Date, dateSerializer);
const user = new User();
console.log(jsonthis.toJson(user));
Field-Specific Serializer
Utilize the @JsonField decorator to specify a custom serializer for a specific property:
function maskEmail(value: string): string {
return value.replace(/(?<=.).(?=[^@]*?.@)/g, "*");
}
class User {
id: number = 1;
@JsonField({serializer: maskEmail})
email: string = "john.doe@gmail.com";
}
const jsonthis = new Jsonthis();
const user = new User();
console.log(jsonthis.toJson(user));
Contextual Field-Specific Serializer
Jsonthis serialization supports a user-defined context object that can be used to further influence the serialization
process:
function maskEmail(value: string, state: JsonTraversalState, opts?: ToJsonOptions): string {
return value.replace(/(?<=.).(?=[^@]*?.@)/g, opts?.context?.maskChar || "*");
}
class User {
id: number = 1;
@JsonField({serializer: maskEmail})
email: string = "john.doe@gmail.com";
}
const jsonthis = new Jsonthis();
const user = new User();
console.log(jsonthis.toJson(user, {context: {maskChar: "-"}}));
Circular References
Jsonthis can detect circular references out of the box. When serializing an object with circular references, the default
behavior is to throw a CircularReferenceError. However, you can customize this behavior by providing a custom handler:
function serializeCircularReference(value: any): any {
return { $ref: `$${value.constructor.name}(${value.id})` };
}
class User {
id: number;
name: string;
friend?: User;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
const user = new User(1, "John");
user.friend = new User(2, "Jane");
user.friend.friend = user;
const jsonthis = new Jsonthis({circularReferenceSerializer: serializeCircularReference});
console.log(jsonthis.toJson(user));
Sequelize support
Jsonthis seamlessly integrates with the Sequelize ORM library.
To utilize Jsonthis with Sequelize, simply specify it in the library constructor:
const sequelize = new Sequelize({ ... });
const jsonthis = new Jsonthis({
sequelize: sequelize
});
Now, Jsonthis will seamlessly intercept the serialization process when using the toJSON() method
with Sequelize models:
function maskEmail(value: string): string {
return value.replace(/(?<=.).(?=[^@]*?.@)/g, "*");
}
export class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
@Attribute(DataTypes.INTEGER)
@PrimaryKey
declare id: number;
@Attribute(DataTypes.STRING)
@NotNull
@JsonField({serializer: maskEmail})
declare email: string;
@Attribute(DataTypes.STRING)
@NotNull
@JsonField(false)
declare password: string;
}
const jsonthis = new Jsonthis({case: "snake", sequelize});
const user = await User.create({
id: 1,
email: "john.doe@gmail.com",
password: "s3cret"
});
console.log(user.toJSON());
Let's Contribute Together!
I'm excited to have you contribute and share your ideas to make this library even better!
How You Can Help
- Fork the repository.
- Create a new branch for your changes.
- Make your improvements, test them, and commit your work.
- Push your branch to your fork.
- Send us a pull request!
Some Tips
- Keep the coding style consistent.
- Write clear and friendly commit messages.
- Don't forget tests and documentation!
- Be kind and respectful in your interactions.
Got Ideas?
Share your thoughts! I'd love to hear your suggestions. Just open an issue and let's chat!
Thanks a bunch for considering lending a hand! 🌟