Is there a way to override the JSON.stringify method within the JSON class of a TypeScript project without using a custom call?

Dealing with a React Native and TypeScript app here. I keep encountering an error from Fabric every week: "JSON.stringify cannot serialize cyclic structures." The frustrating part is that the error seems to pop up randomly, without any specific scenario triggering it. To make matters worse, my project has numerous third-party libraries that rely on JSON.stringify. This makes it impossible for me to manually implement a custom method everywhere to handle this issue. However, there might be a solution. In the root of my project, there's a boot file where all classes can be overridden. So, I came up with a helper function to tackle cyclic structure serialization:

const getCircularReplacer = () => {
  const seen = new WeakSet();

  return (key: any, value: any) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) {
        return jsonStringify.circularReferenceReplacement;
      }
      seen.add(value);
    }

    return value;
  };
};

interface IJsonStringify {
  (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
  circularReferenceReplacement?: any;
}

export const jsonStringify: IJsonStringify = (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string => {
  return JSON.stringify(value, replacer || getCircularReplacer(), space);
};

However, when attempting to override JSON.stringify in my boot file like so:

JSON.stringify = (value: any) => {
  return jsonStringify(value);
};

I encounter a different error: "Maximum call stack size exceeded." Can someone point out where I'm going wrong or suggest a better way to override the JSON class using my helper function?

Answer №1

If you're looking to eliminate cyclic references and any already seen objects, consider implementing the following method:

function removeCycles(obj, stack = []) {
    if (!obj || typeof obj !== 'object')
        return obj;

    if (stack.includes(obj))
        return null;

    let s = stack.concat([obj]);

    return Array.isArray(obj)
        ? obj.map(x => removeCycles(x, s))
        : Object.fromEntries(
            Object.entries(obj)
                .map(([k, v]) => [k, removeCycles(v, s)]));
}

To use this method, simply call it as follows:

JSON.stringify(removeCycles(yourJson))
.

Regarding the error message:

Maximum call stack size exceeded

This typically occurs when a recursive function lacks an exit condition.

Answer №2

One potential solution is to implement json-stringify-safe

const {getSerialize} = require('json-stringify-safe');

const stringifyCore = JSON.stringify;
JSON.stringify = function (obj, replacer, spaces, cycleReplacer) {
    return stringifyCore(obj, getSerialize(replacer, cycleReplacer), spaces);
};

By utilizing this method, it may resolve the issue with the Maximum call stack exceeded error.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Encountering a 500 error on Chrome and Internet Explorer while trying to sign

I am currently working on an ASP.NET Core application that handles identity management through Azure AD B2C using the ASP.Net Core OpenID Connect. The front end is developed using AngularJS 2 with TypeScript. In my Logout function, the user is redirected t ...

Modifying .vue files within Laravel seems to unexpectedly impact unrelated CSS styles

I've been working on a Laravel project that involves building Vue components. Strangely, every time I update a .vue file and add it for a commit, modifications are also made to the app.css and app.js files. These changes seem to be undoing a particula ...

Unable to transfer data through Ionic popover

I've encountered an issue when trying to pass data to my popover component, as the data doesn't seem to be sent successfully. Code HTML <div class="message" id="conversation" *ngFor="let message of messages.notes"> <ion-row class= ...

What is the best way to generate an @ symbol using JavaScript?

When coding in Javascript, a challenge I am facing is creating a variable that includes the @ symbol in a string without it being misinterpreted as something else, especially when dealing with URLs. Does anyone have any suggestions on how to handle this ...

Is there a way to prevent the imported JQuery from causing issues with current code implementations?

Being a novice developer in Html/Javascript/CSS/Jquery coding, I recently encountered an issue while integrating Jquery into my project. When I imported Jquery, the styling of simple buttons went haywire. Jquery worked perfectly fine when using its classes ...

Tips for automatically inserting a "read more" link once text exceeds a certain character count

Currently utilizing an open-source code to fetch Google reviews, but facing an issue with long reviews. They are messing up the layout of my site. I need to limit the characters displayed for each review and provide an option for users to read the full rev ...

Error in TypeScript: The property 'data' is not found within type '{ children?: ReactNode; }'. (ts2339)

Question I am currently working on a project using BlitzJS. While fetching some data, I encountered a Typescript issue that says: Property 'data' does not exist on type '{ children?: ReactNode; }'.ts(2339) import { BlitzPage } from &q ...

What is preventing me from utilizing a dynamic import while working with Nuxt3?

I'm currently working on developing a component that allows me to dynamically import icons based on the provided icon name using unplugin-icons. However, I'm facing an issue where dynamic imports don't seem to work when the import path is dy ...

The jQuery pop-up fails to activate on the initial click

I have multiple "Buy Now" buttons for different products. If the button is labeled as "sold-out," it should not do anything, but if it's available, it should trigger a jQuery Magnific Popup. Currently, the popup only opens after the second click becau ...

What is the best way to integrate ag-grid with Observable in Angular 2?

After conducting extensive research on the Internet, I am still struggling to connect the pieces. My angular2 application utilizes an Observable data source from HTTP and I am attempting to integrate ag-grid. However, all I see is a loading screen instead ...

Developing the headers for a service using React.js

As someone new to ReactJs, I'm curious about the various methods we can use to include Headers in our service Url before making a call. While I'm familiar with how GET/POST Calls are made in angular Js after including headers, I'd like to l ...

The Content property of the HttpRequestMessage is populated with characters that are invalid and cannot be

After receiving the return from HttpRequestMessage.Contenc, it appears to be encrypted. Has anyone else experienced something similar? var client2 = new HttpClient(); client2.DefaultRequestHeaders.Accept.Clear(); client2.DefaultReq ...

How can I restrict the navigation buttons in FullCalendar to only allow viewing the current month and the next one?

I recently downloaded the FullCalendar plugin from Is there a way to disable the previous button so that only the current month is visible? Also, how can I limit the next button so that only one upcoming month is shown? In my header, I included this code ...

Instructions on incorporating domains into next.config.js for the "next/image" function with the help of a plugin

Here is the configuration I am currently using. // next.config.js const withImages = require("next-images"); module.exports = withImages({ webpack(config, options) { return config; }, }); I need to include this code in order to allow images from ...

The invocation of res.json() results in the generation of CastError

An issue occurs with CastError when using res.json() with an argument: CastError: Failed to cast value "undefined" to ObjectId for the "_id" field in the "Post" model Interestingly, using just res.status(), res.sendStatus(), or res.json() without argument ...

Automating the movement of a slider input gradually throughout a specified duration

I am working on a website that includes a range input setup like this: <input type="range" min="1036000000000" max="1510462800000" value="0" class="slider" id ="slider"/> Additionally, I have integrated some D3 code for visualizations. You can view ...

Retrieve custom content from a database using Laravel and Ajax when clicking on a navigation bar

Recently, I've started working with Laravel 7 and AJAX. One of the features I want to implement is a 'product's name' navbar that displays product details in a div without refreshing the page when clicked. I came across a demo showcasin ...

Massive Memory Drain Due to XMLHttp POST Request

Is there a way to prevent XHR POST Memory leak in my web app? I have searched extensively for solutions but have not found any satisfactory answers. My issue is similar to the one described in this blog post that outlines the problem without offering any f ...

"Sending the selected pass selector as a parameter to the dispatched action is causing a typing

When a selector changes its value, I want to trigger an action. To achieve this, I passed the selector with a subscription instead of passing an observable. selectedSchedulingsOnPopup$ = this.store.pipe(select(selectSchedulingsByBranch)); this.store.disp ...

Error when deserializing JSON: "Starting value 'W' is not valid"

Looking to develop a basic console game, but encountering an error while deserializing JSON. The specific issue reads: System.Text.Json.JsonException: "'W' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0." Below ...