X Xerobit

JSON.stringify Options — replacer, space, and Circular Reference Handling

JSON.stringify accepts three arguments: value, replacer, and space. Learn how to use the replacer function to filter keys, the space parameter for pretty-printing, handle...

Mian Ali Khalid · · 4 min read
Use the tool
JSON Formatter
Format, validate, and beautify JSON online. 100% client-side — your data never leaves your browser.
Open JSON Formatter →

JSON.stringify(value, replacer, space) — most developers use only the first argument. The replacer and space parameters give you fine-grained control over serialization.

Format and validate JSON with the JSON Formatter.

The space parameter (pretty-printing)

const data = { name: 'Alice', age: 30, roles: ['admin', 'editor'] };

// No formatting (production default):
JSON.stringify(data);
// '{"name":"Alice","age":30,"roles":["admin","editor"]}'

// 2-space indent:
JSON.stringify(data, null, 2);
// {
//   "name": "Alice",
//   "age": 30,
//   "roles": [
//     "admin",
//     "editor"
//   ]
// }

// 4-space indent:
JSON.stringify(data, null, 4);

// Tab indent:
JSON.stringify(data, null, '\t');

Array replacer (whitelist keys)

const user = {
  id: 1,
  name: 'Alice',
  email: 'alice@example.com',
  passwordHash: 'secret!',
  internalToken: 'secret!',
};

// Only serialize these keys:
JSON.stringify(user, ['id', 'name', 'email'], 2);
// {
//   "id": 1,
//   "name": "Alice",
//   "email": "alice@example.com"
// }
// passwordHash and internalToken are excluded

Function replacer (transform values)

function replacer(key, value) {
  // Return undefined to exclude the key:
  if (key === 'password' || key === 'token') return undefined;
  
  // Transform values:
  if (value instanceof Date) return value.toISOString();
  if (typeof value === 'bigint') return value.toString();
  if (value === undefined) return null;  // Make explicit
  
  return value;  // Default: keep as-is
}

const data = {
  user: 'Alice',
  password: 'secret',
  createdAt: new Date(),
  bigNumber: BigInt(9007199254740991),
};

JSON.stringify(data, replacer, 2);
// {
//   "user": "Alice",
//   "createdAt": "2026-05-12T14:30:00.000Z",
//   "bigNumber": "9007199254740991"
// }

Handle circular references

// JSON.stringify throws on circular references:
const a = { name: 'a' };
const b = { name: 'b', ref: a };
a.ref = b;  // Circular!

JSON.stringify(a);  // TypeError: Converting circular structure to JSON

// Fix 1: replacer that tracks seen objects:
function safeStringify(obj, indent = 0) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) return '[Circular]';
      seen.add(value);
    }
    return value;
  }, indent);
}

safeStringify(a);  // '{"name":"a","ref":{"name":"b","ref":"[Circular]"}}'

// Fix 2: Use the 'flatted' library:
// npm install flatted
import { stringify, parse } from 'flatted';
stringify(a);  // Handles circular references preserving structure

Custom toJSON method

class User {
  constructor(name, email, passwordHash) {
    this.name = name;
    this.email = email;
    this.passwordHash = passwordHash;
    this.createdAt = new Date();
  }

  toJSON() {
    // Called automatically by JSON.stringify
    return {
      name: this.name,
      email: this.email,
      // Exclude passwordHash
      createdAt: this.createdAt.toISOString(),
    };
  }
}

const user = new User('Alice', 'alice@example.com', 'hashed!');
JSON.stringify(user);
// '{"name":"Alice","email":"alice@example.com","createdAt":"2026-05-12T14:30:00.000Z"}'

Handling edge cases

// undefined values are omitted:
JSON.stringify({ a: 1, b: undefined });   // '{"a":1}'

// NaN and Infinity become null:
JSON.stringify({ a: NaN, b: Infinity });  // '{"a":null,"b":null}'

// Functions are omitted:
JSON.stringify({ fn: () => {} });         // '{}'

// Symbol keys are omitted:
JSON.stringify({ [Symbol()]: 'x' });      // '{}'

// null is preserved:
JSON.stringify({ a: null });              // '{"a":null}'

// Top-level undefined returns undefined (not a string):
JSON.stringify(undefined);               // undefined (not "undefined")

JSON.stringify for debugging

// Pretty-print any value to console:
const prettyLog = (label, value) =>
  console.log(`${label}:`, JSON.stringify(value, null, 2));

prettyLog('Request body', req.body);
prettyLog('User data', user);

// Truncate long JSON for logging:
function truncatedJSON(value, maxLength = 500) {
  const json = JSON.stringify(value);
  return json.length > maxLength
    ? json.slice(0, maxLength) + '... [truncated]'
    : json;
}

Related posts

Related tool

JSON Formatter

Format, validate, and beautify JSON online. 100% client-side — your data never leaves your browser.

Written by Mian Ali Khalid. Part of the Data & Format pillar.