JSON.stringify() and JSON.parse() are two of the most-used functions in JavaScript. Most developers use them at their most basic level — but they have powerful options that solve real problems.

JSON.stringify() basics

const data = { name: "Alice", age: 28, active: true };

JSON.stringify(data)
// '{"name":"Alice","age":28,"active":true}'

JSON.stringify(data, null, 2)  // pretty-print with 2-space indent
// '{
//   "name": "Alice",
//   "age": 28,
//   "active": true
// }'

JSON.stringify(data, null, '	') // tab indent

The replacer parameter

The second argument to JSON.stringify() is a replacer — it filters or transforms properties:

const user = { name: "Alice", password: "secret123", age: 28 };

// Array replacer — only include these keys
JSON.stringify(user, ['name', 'age'])
// '{"name":"Alice","age":28}' — password excluded

// Function replacer — full control over each value
JSON.stringify(user, (key, value) => {
  if (key === 'password') return undefined; // exclude
  if (typeof value === 'number') return value * 2; // transform
  return value;
})
// '{"name":"Alice","age":56}'

JSON.parse() basics

const json = '{"name":"Alice","age":28}';
const data = JSON.parse(json);

console.log(data.name); // "Alice"
console.log(typeof data.age); // "number"

// Always use try/catch
try {
  const data = JSON.parse(untrustedInput);
} catch (error) {
  console.error('Invalid JSON:', error.message);
}

The reviver parameter

JSON.parse() accepts a reviver function to transform values as they're parsed:

const json = '{"name":"Alice","createdAt":"2023-11-14T22:13:20Z","score":"95"}';

const data = JSON.parse(json, (key, value) => {
  // Convert date strings to Date objects
  if (key === 'createdAt') return new Date(value);
  // Convert numeric strings to numbers
  if (key === 'score') return Number(value);
  return value;
});

console.log(data.createdAt instanceof Date); // true
console.log(typeof data.score); // "number"

What JSON.stringify() ignores

const obj = {
  name: "Alice",
  fn: function() {},      // functions → undefined (excluded)
  sym: Symbol('id'),      // symbols → undefined (excluded)
  undef: undefined,       // undefined values → excluded
  inf: Infinity,          // Infinity → null
  nan: NaN,               // NaN → null
  date: new Date(),       // Date → ISO string
  regex: /abc/,           // RegExp → {} (empty object!)
};

JSON.stringify(obj)
// '{"name":"Alice","inf":null,"nan":null,"date":"2023-11-14T...","regex":{}}'

Handle circular references

// This throws: "TypeError: Converting circular structure to JSON"
const obj = { name: "Alice" };
obj.self = obj; // circular reference
JSON.stringify(obj); // throws!

// Fix 1: Use a replacer to skip circular refs
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;
  });
}

// Fix 2: Use structuredClone() first to detect issues
const clone = structuredClone(obj); // throws on circular refs with clear error

Deep clone with JSON

// Quick deep clone (most common pattern)
const clone = JSON.parse(JSON.stringify(original));

// Limitations:
// - Loses Date objects (becomes strings)
// - Loses undefined values
// - Loses functions
// - Fails on circular references

// Better: use structuredClone() (modern browsers)
const clone = structuredClone(original); // handles more types, no JSON roundtrip

Try it free — JSON Formatter

Validate and format your JSON output from stringify instantly.

Open tool →