Parsing JSON in JavaScript: JSON.parse and JSON.stringify

beginner
11 min

Parsing JSON in JavaScript: JSON.parse and JSON.stringify

JavaScript ships with a built-in JSON object that does exactly two things, and it does them extremely well: JSON.parse turns a JSON string into live values, and JSON.stringify turns values into a JSON string. Between them they power every fetch call, every localStorage save, and every API request body you will ever write. In this lesson of our JSON tutorial series, we go beyond the basics into the options both methods accept.

JSON.parse: String to Data

javascript
const text = '{"name":"Ada","skills":["math","logic"]}'; const user = JSON.parse(text); console.log(user.skills[1]); // "logic"

If the string is not valid JSON, JSON.parse throws a SyntaxError. Because network responses and user input are never guaranteed to be well formed, production code wraps parsing in try/catch:

javascript
try { const data = JSON.parse(input); } catch (err) { console.error("Bad JSON:", err.message); }

The Reviver Function

JSON.parse accepts a second argument, a reviver, called for every key and value during parsing. Its classic use is turning ISO date strings back into Date objects:

javascript
const data = JSON.parse(text, (key, value) => { if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T/.test(value)) { return new Date(value); } return value; });

JSON.stringify: Data to String

javascript
const body = JSON.stringify({ query: "json", page: 2 }); // '{"query":"json","page":2}'

Stringify silently handles awkward values: undefined, functions, and symbols are dropped from objects and become null inside arrays. A Date becomes its ISO string because Date defines a toJSON method. Circular references throw a TypeError, which you will meet the first time you stringify a DOM node or a complex framework object.

Pretty-Printing with the Space Argument

The third argument controls indentation, which is invaluable for logs and config files:

javascript
console.log(JSON.stringify(user, null, 2)); // 2-space indented output

Filtering with the Replacer

The second argument, a replacer, controls what gets serialized. Pass an array of keys to whitelist fields, or a function for custom logic such as stripping secrets:

javascript
JSON.stringify(user, ["name", "email"]); // only these keys JSON.stringify(user, (k, v) => k === "password" ? undefined : v);

Everyday Patterns

  • Fetch: const data = await fetch(url).then(r => r.json()); uses the same parser internally.
  • Sending: fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }).
  • Storage: localStorage.setItem("cart", JSON.stringify(cart)) and parse it back on load.
  • Deep copy: structuredClone(obj) is now preferred, but JSON.parse(JSON.stringify(obj)) remains a widely seen idiom with known limits (drops functions, dates become strings).

Key Takeaways

  • JSON.parse converts strings to values and throws on invalid input, so wrap it in try/catch.
  • JSON.stringify drops undefined and functions, and throws on circular references.
  • Revivers restore rich types like dates; replacers filter or transform output.
  • The space argument gives you readable, pretty-printed JSON for free.

Next up: Working with JSON in Python, where the json module mirrors these ideas with loads and dumps.

Parsing JSON in JavaScript: JSON.parse and JSON.stringify - JSON | CodeYourCraft | CodeYourCraft