DevLab
JSON

JSON.stringify and JSON.parse: Edge Cases You Should Know

Master JavaScript JSON serialization — what stringify drops, how to handle dates and undefined, the replacer and reviver functions, and circular reference errors.

The Basics

JSON.stringify({ name: "Alice", age: 30 })
// → '{"name":"Alice","age":30}'

JSON.parse('{"name":"Alice","age":30}')
// → { name: "Alice", age: 30 }

What stringify Silently Drops or Converts

JSON.stringify({
  fn: () => "hello",       // functions → dropped
  undef: undefined,         // undefined → dropped
  sym: Symbol("x"),         // symbols → dropped
  date: new Date(),         // Date → ISO string
  nan: NaN,                // NaN → null
  inf: Infinity,            // Infinity → null
  regex: /pattern/gi,       // RegExp → {}
  map: new Map([[1, 2]]),  // Map → {}
})

Circular Reference Error

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

// Fix with a WeakSet replacer:
const seen = new WeakSet();
JSON.stringify(a, (key, val) => {
  if (typeof val === 'object' && val !== null) {
    if (seen.has(val)) return '[Circular]';
    seen.add(val);
  }
  return val;
});

Replacer and Reviver

// Replacer: filter/transform during stringify
JSON.stringify(data, ['name', 'age'])  // only include these keys

// Reviver: transform during parse (restore Date objects)
JSON.parse(jsonStr, (key, val) => {
  if (typeof val === 'string' && /^d{4}-d{2}-d{2}T/.test(val)) {
    return new Date(val);
  }
  return val;
})

Pretty Printing

JSON.stringify(data, null, 2)    // 2-space indent
JSON.stringify(data, null, "	") // tab indent

Deep Clone Patterns

// Quick — loses functions, undefined, Dates become strings
const clone = JSON.parse(JSON.stringify(obj));

// Better: structuredClone() — handles Date, Map, Set, circular refs
const clone = structuredClone(obj);  // Node 17+, modern browsers

Practice with these tools

More Learning Topics