Tutorials

JSON.parse() vs JSON.stringify(): What’s the Difference?

Nathan Corbett··8 min read

JSON.parse() and JSON.stringify() are opposite operations. Parse reads text; stringify writes text. If you remember which side starts with a string, the names stop being confusing: JSON.parse('{"ready":true}') returns an object, while JSON.stringify({ ready: true }) returns the string '{"ready":true}'.

That simple rule covers most uses, but JavaScript values and JSON values are not identical. The differences explain the mysterious missing fields, changed dates, and runtime errors developers encounter during a round trip.

JSON.parse converts JSON text to a value

JSON.parse(text) checks that the entire string follows JSON syntax, then creates the matching JavaScript object, array, string, number, boolean, or null value.

const text = '{"name":"Ada","active":true,"roles":["admin"]}';
const user = JSON.parse(text);
console.log(user.name); // Ada

Use it when reading a JSON string from localStorage, a file, a message queue, or a raw HTTP response. Modern response.json() already parses the response for you, so calling JSON.parse() on its result is a double parse and usually fails with an unexpected-token error.

Parsing is strict. Property names and string values need double quotes; trailing commas, comments, single-quoted strings, undefined, and NaN are invalid. Check a questionable payload with the JSON validator, or follow the step-by-step guide to fix invalid JSON.

JSON.stringify converts a value to JSON text

JSON.stringify(value) walks a JavaScript value and returns its JSON representation. This is what you use before putting structured data into string-only storage or an HTTP request body.

const user = { name: 'Ada', active: true };
const text = JSON.stringify(user);
// {"name":"Ada","active":true}

For readable output, provide indentation as the third argument: JSON.stringify(user, null, 2). The JSON formatter does the same job interactively and makes deeply nested output easier to inspect.

The round trip in practice

A normal browser storage round trip looks like this:

localStorage.setItem('settings', JSON.stringify(settings));
const settings = JSON.parse(localStorage.getItem('settings') ?? '{}');

For an API request, stringify the body and declare its media type:

await fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(user),
});

The Content-Type header describes the bytes being sent; stringify creates those bytes as text. They solve separate parts of the request.

Values that do not survive stringify

JSON supports objects, arrays, strings, finite numbers, booleans, and null. JavaScript supports more, so a round trip can be lossy:

  • Object properties containing undefined, functions, or symbols are omitted.
  • Those values become null in arrays.
  • NaN, Infinity, and -Infinity become null.
  • A Date becomes an ISO 8601 string.
  • Map and Set normally become empty objects unless converted first.
  • BigInt and circular references throw a TypeError.

This is why JSON.parse(JSON.stringify(value)) is not a universal deep-clone technique. Use structuredClone() for supported in-memory JavaScript types, and use JSON only when you intentionally want JSON's portable data model.

Replacer and reviver functions

The second argument to stringify is a replacer. It can filter properties or transform values before serialization. The second argument to parse is a reviver. It can transform values while rebuilding the result.

const text = JSON.stringify(user, (key, value) =>
  key === 'password' ? undefined : value
);

const data = JSON.parse(text, (key, value) =>
  key === 'createdAt' ? new Date(value) : value
);

A replacer is useful for shaping output, but it is not a substitute for a deliberate API allowlist. A reviver should only convert fields whose schema you control; converting every date-shaped string can mutate ordinary user text.

Escaping is a different operation

Stringify serializes a complete value. Escaping only makes special characters safe inside a JSON string. If you need to embed a quote, newline, or backslash in an existing string, use the JSON escape tool; to turn escape sequences back into characters, use JSON unescape. Do not repeatedly stringify a value to escape it—double encoding creates strings full of backslashes.

The rule to remember

Use JSON.stringify() when a JavaScript value must leave memory as JSON text. Use JSON.parse() when valid JSON text arrives and must become a usable value. Validate at the boundary, account for types JSON cannot represent, and inspect the final structure with the JSON viewer when a round trip behaves unexpectedly.

Try the tools

Frequently Asked Questions

What is the difference between JSON.parse and JSON.stringify?

JSON.parse converts valid JSON text into a JavaScript value. JSON.stringify performs the opposite conversion, turning a JavaScript value into JSON text. A common flow is stringify before storage or transmission, then parse after reading the text back.

When should I use JSON.parse?

Use JSON.parse when you have a string that contains JSON, such as a localStorage value, a copied API payload, or a raw response body. Do not call it on a value that is already an object. Invalid JSON causes a SyntaxError, so untrusted input should be parsed inside error handling.

Why does JSON.stringify remove undefined values?

undefined is a JavaScript value but is not part of the JSON data model. In an object, properties whose values are undefined, functions, or symbols are omitted. In an array, those entries become null so the array positions remain intact.

Does JSON.parse convert date strings to Date objects?

No. JSON has strings but no Date type, so an ISO date remains a string after parsing. You can pass a reviver function to JSON.parse to recognize selected date fields and construct Date objects deliberately.

Can JSON.stringify handle circular references?

Not by default. If an object points back to itself, JSON.stringify throws a TypeError. Remove the cycle, replace repeated objects with IDs, or use a custom replacer or a serialization format designed for object graphs.

NC

Nathan Corbett writes for CodeUtilityKit, where the team builds free, privacy-first developer tools that run entirely in your browser. Every guide is written and reviewed by developers who use these tools daily.