HomeBlog › JSON.stringify and JSON.parse

JSON.stringify and JSON.parse: The Complete Guide

Published March 5, 2026 • 10 min read

Every JavaScript developer uses JSON.stringify and JSON.parse daily, but few know all their options. This guide covers everything from basic usage to replacers, revivers, circular references, and performance.

JSON.stringify — Basic Usage

const user = { name: "Alice", age: 30, active: true };
JSON.stringify(user);
// '{"name":"Alice","age":30,"active":true}'

Pretty-printing with indentation

JSON.stringify(user, null, 2);
// {
//   "name": "Alice",
//   "age": 30,
//   "active": true
// }

JSON.stringify(user, null, '\t'); // Tab indentation

What JSON.stringify omits

These values are omitted or converted during serialization:

const obj = {
  fn: () => {},        // omitted (functions)
  sym: Symbol('x'),   // omitted (symbols)
  undef: undefined,   // omitted (undefined)
  nan: NaN,           // becomes null
  inf: Infinity,      // becomes null
  date: new Date(),   // becomes ISO string
  regex: /abc/        // becomes {}
};
JSON.stringify(obj);
// '{"nan":null,"inf":null,"date":"2026-03-05T10:00:00.000Z","regex":{}}'

The Replacer Argument

The second argument to JSON.stringify is a replacer — either an array of allowed keys, or a function.

Array replacer — whitelist specific keys

const user = { id: 1, name: "Alice", password: "secret", email: "a@b.com" };
JSON.stringify(user, ['id', 'name']);
// '{"id":1,"name":"Alice"}'  — password excluded

Function replacer — transform values

JSON.stringify(user, (key, value) => {
  if (key === 'password') return undefined; // exclude
  if (typeof value === 'number') return value * 2; // transform
  return value;
});

Custom toJSON method

class Money {
  constructor(amount, currency) {
    this.amount = amount;
    this.currency = currency;
  }
  toJSON() {
    return `${this.amount} ${this.currency}`;
  }
}
JSON.stringify(new Money(42, 'USD')); // '"42 USD"'

JSON.parse — Basic Usage

const jsonString = '{"name":"Alice","age":30}';
const user = JSON.parse(jsonString);
console.log(user.name); // "Alice"

Always use try-catch

function safeParseJSON(str) {
  try {
    return { data: JSON.parse(str), error: null };
  } catch (e) {
    return { data: null, error: e.message };
  }
}

const { data, error } = safeParseJSON(userInput);
if (error) {
  console.error('Invalid JSON:', error);
}

Reviver — transform values on parse

const json = '{"name":"Alice","createdAt":"2026-03-05T10:00:00.000Z"}';

const obj = JSON.parse(json, (key, value) => {
  // Revive ISO date strings back to Date objects
  if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
    return new Date(value);
  }
  return value;
});

console.log(obj.createdAt instanceof Date); // true

Handling Circular References

const a = {};
a.self = a; // circular reference
JSON.stringify(a); // TypeError: Converting circular structure to JSON

Fix using a WeakSet to track seen objects:

function safeStringify(obj) {
  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;
  });
}
safeStringify(a); // '{"self":"[Circular]"}'

Deep Clone with JSON

A common pattern for deep cloning simple objects:

const original = { a: 1, b: { c: 2 } };
const clone = JSON.parse(JSON.stringify(original));
clone.b.c = 99;
console.log(original.b.c); // 2 — original unchanged

Limitation: This does not clone functions, Dates (loses Date object, gets string), undefined values, symbols, or handle circular references. For production deep cloning, use structuredClone() instead.

// Better: structuredClone (modern browsers + Node 17+)
const clone = structuredClone(original);

Performance Tips

Frequently Asked Questions

What is the difference between JSON.stringify and toString?

toString() on an object returns [object Object] — not useful. JSON.stringify() serializes the full structure of the object to a JSON string. Always use JSON.stringify() for data serialization.

Does JSON.parse validate the JSON?

Yes — JSON.parse() throws a SyntaxError if the string is not valid JSON. This is why wrapping it in try-catch is essential when parsing untrusted input. For detailed error information (line/column), use the JSON Validator tool.

Can JSON.stringify handle BigInt?

No. JSON.stringify(BigInt(9007199254740993)) throws a TypeError: Do not know how to serialize a BigInt. Use a replacer to convert BigInt to string: (key, val) => typeof val === 'bigint' ? val.toString() : val.

Validate and format your JSON

Free online JSON validator, formatter, and 65+ more tools.

Open JSON Web Tools →

Also read: JSON Schema Tutorial | JSON vs XML | JSON Cheat Sheet | JSON Formatter