Sling Academy
Home/Node.js/Solving NestJS TypeError: Converting circular structure to JSON

Solving NestJS TypeError: Converting circular structure to JSON

Last updated: December 31, 2023

When working with Node.js and NestJS, developers might occasionally encounter an error message that reads ‘NestJS TypeError: Converting circular structure to JSON’. This error typically occurs when you try to convert a circular data structure into a JSON string, something which JSON.stringify() cannot handle due to the nature of JSON.

Understanding the Circular Structure Error

In JavaScript, a circular reference occurs when an object refers back to itself. This is common when creating relationships between objects or entities. For example, in a parent-child relationship, a parent may reference a child, which in turn has a reference back to the parent. When attempting to serialize (convert to a string) an object with circular references, JSON.stringify() will throw the mentioned error because it ends up in an infinite loop trying to resolve the references.

Using Class-transformer Library

One common solution to dealing with circular references in NestJS is to use the ‘class-transformer’ library. The library provides decorators that allow for custom transformation logic when serializing and deserializing objects. To resolve the circular structure error, we can implement a custom transformation that ignores the circular references.

First, make sure to install the class-transformer package if it’s not already part of your project:

npm install class-transformer

Next, let’s consider the following code example where a circular reference is likely:

import { Exclude, Expose } from 'class-transformer';

class Parent {
    child: Child;
}

class Child {
    @Exclude()
    parent: Parent;

    @Expose()
    getName(): string {
        return this.name;
    }
}

let parent = new Parent();
let child = new Child();
parent.child = child;
child.parent = parent;

In the above example, we’re creating two classes: Parent and Child. Each class references the other, creating a circular reference. By using the @Exclude() decorator from class-transformer, we tell the library to ignore the ‘parent’ property in the Child class when serializing the object. Note that the @Expose() decorator is optional but used here to highlight that the getName method should be included in the serialized result.

When you want to serialize the object, you’d use the classToPlain function from class-transformer:

import { classToPlain } from 'class-transformer';

let serializedObj = classToPlain(child);
console.log(JSON.stringify(serializedObj));

This will serialize the Child object without the parent property, preventing the circular structure error.

Design Circular References Mindfully

As a long-term approach, it’s usually better to design your data structures to avoid circular references where possible. If your use case allows, consider restructuring your data so that it retains a hierarchical model, without cross-references. This would natively solve the issue when serializing objects to JSON.

In cases where a simple structure isn’t possible or ideal, make sure to apply a thoughtful approach on how and when objects should reference each other. Sometimes a middle-ground can be found by using identifiers (such as database IDs) to reference related objects instead of holding a direct reference to the entire object in-memory.

Custom toJSON Method

JavaScript objects can have a custom toJSON method that JSON.stringify() will call when serializing the object. This method can be designed to deal with circular references:

class Parent {
    child: Child;

    toJSON() {
        const { child, ...otherProps } = this;
        return otherProps;
    }
}

class Child {
    parent: Parent;

    toJSON() {
        const { parent, ...otherProps } = this;
        return otherProps;
    }
}

let parent = new Parent();
let child = new Child();
parent.child = child;
child.parent = parent;

console.log(JSON.stringify(parent));

In each class’s toJSON method, we destructure the object to separate the circular reference from the other properties. We then return the rest of the properties, effectively excluding the problematic reference from serialization. In this way, JSON.stringify() no longer throws an error, as it uses our custom toJSON method which avoids the circular reference.

Ultimately, dealing with the NestJS TypeError for circular structures involves either excluding the circular reference at serialization time, restructuring the data, or providing custom serialization logic. With these methods, you can ensure that your application can handle and serialize complex object relationships without errors.

Next Article: Fixing NestJS Error in Production: Cannot Find Module ‘@nestjs/microservices’

Previous Article: NestJS: How to Delete a File after Response is Sent to Client

Series: Nest.js Tutorials: From Basics to Advanced

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates