Skip to content

Instantly share code, notes, and snippets.

@paleite
Created December 17, 2024 11:50
Show Gist options
  • Save paleite/6c69b7d7a3029350f45077d681b25e67 to your computer and use it in GitHub Desktop.
Save paleite/6c69b7d7a3029350f45077d681b25e67 to your computer and use it in GitHub Desktop.
Error with circular references to JSON
/**
* Converts an Error object into a plain object with all its properties.
* It includes non-enumerable properties like "message", "name", and "stack".
*
* @param {Error} error - The Error object to convert.
* @returns {Object} A plain object containing the properties of the Error.
*/
const convertErrorToPlainObject = (error) =>
Object.fromEntries(
Object.getOwnPropertyNames(error).map((propertyName) => [
propertyName,
error[propertyName],
])
);
/**
* Creates a replacer function for JSON.stringify to handle circular references.
* If a circular reference is detected, the value is replaced with the string "[Circular]".
*
* @returns {(this: any, key: string, value: any) => any} A replacer function that can be used with JSON.stringify.
*/
const createCircularReferenceReplacer = () => {
/**
* Tracks already visited objects to detect cycles.
*
* WeakSet is used to track already visited objects. WeakSet is preferred
* because it doesn't prevent garbage collection (unlike Set) and is
* specifically designed to hold objects only.
*/
const seenObjects = new WeakSet();
return (_key, value) => {
if (typeof value === "object" && value !== null) {
if (seenObjects.has(value)) {
return "[Circular]"; // Replace circular references with this placeholder.
}
seenObjects.add(value); // Mark this object as seen.
}
return value;
};
};
/**
* Serializes an Error object to a JSON string.
* It converts the Error into a plain object and ensures circular references are handled.
*
* @param {Error} error - The Error object to serialize.
* @returns {string} A JSON string representing the Error object.
*/
const errorToJson = (error) => {
const handleCircularReferences = createCircularReferenceReplacer();
const errorAsPlainObject = convertErrorToPlainObject(error);
return JSON.stringify(errorAsPlainObject, handleCircularReferences, 2);
};
const exampleError = new Error("Something bad happened");
exampleError.self = exampleError; // Simulate a circular reference
console.log(errorToJson(exampleError));
// Prints `{"stack":"Error: Something bad happened\n at <anonymous>:1:22","message":"Something bad happened","self":{"self":"[Circular]"}}`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment