Working with JSON

JavaScript · Practical · 8 min

JSON is the format of nearly every web API, config file and local storage entry.

JSON is a text format based on JavaScript literals, but stricter: keys must be double-quoted strings, there are no comments or trailing commas, and the only values are strings, numbers, booleans, null, arrays and objects.

JSON.stringify(value) turns a value into JSON text; JSON.parse(text) turns text back into values. A third argument to stringify pretty-prints: JSON.stringify(data, null, 2).

Not everything survives the round trip:

  • undefined, functions and symbols are dropped from objects (and become null in arrays).
  • Date objects become ISO strings (via their toJSON method) and come back as plain strings.
  • Map, Set and class instances become plain {} or lose their prototype.
  • NaN and Infinity become null.
  • BigInt throws a TypeError.
  • Circular references throw.

You can customise both directions. Objects can define toJSON() to control their serialised form. The second argument of stringify (a replacer function or array of keys) filters or transforms properties, and the second argument of parse (a reviver) transforms values on the way in — for example turning date strings back into Dates.

JSON.parse throws a SyntaxError on invalid input, so wrap parsing of anything external — user input, files, localStorage — in try...catch.

A tempting trick, JSON.parse(JSON.stringify(obj)), makes a deep copy but silently loses dates, undefined and more. Use structuredClone(obj) instead.

Example

const event = {
  title: "Launch",
  date: new Date("2025-06-01T10:00:00Z"),
  notes: undefined,
  attendees: new Set(["ada"]),
};

const text = JSON.stringify(event);
console.log(text);
// {"title":"Launch","date":"2025-06-01T10:00:00.000Z","attendees":{}}

const revived = JSON.parse(text, (key, value) =>
  key === "date" ? new Date(value) : value);
console.log(revived.date instanceof Date);   // true

function safeParse(raw, fallback) {
  try { return JSON.parse(raw); }
  catch { return fallback; }
}
console.log(safeParse("{bad json}", {}));     // {}
try { JSON.stringify({ id: 1n }); }
catch (e) { console.log(e.name); }           // TypeError (BigInt)

Remember

  • stringify drops undefined/functions, turns Dates into strings and Maps/Sets into {}
  • JSON.parse throws on bad input — guard external data
  • Use a reviver or toJSON to customise conversion; structuredClone for deep copies

Watch out for

  • Expecting dates to come back from JSON.parse as Date objects.

Check yourself

  1. What does JSON.stringify({ a: undefined, b: 1 }) return?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON