Back to blog
Tutorials10 min read

How to Parse JSON in JavaScript: JSON.parse & JSON.stringify

Master JSON in JavaScript: JSON.parse and JSON.stringify, the reviver and replacer callbacks, handling Dates, BigInt, and undefined, common errors, and the security rules for untrusted input.

By Saifur Rahman Shochib

JavaScript has the cleanest JSON support of any language — two built-in functions, JSON.parse and JSON.stringify, handle almost everything. But the moment you deal with Dates, BigInt, undefined, or untrusted input, the edge cases appear. This guide covers the core API, the powerful reviver and replacer callbacks most developers never use, the errors you will actually hit, and the security rules for parsing data you did not create.

JSON.parse: text to object

JSON.parse takes a JSON string and returns the corresponding JavaScript value: an object, array, string, number, boolean, or null. For example, JSON.parse('{"id": 1, "active": true}') returns an object with a numeric id and a boolean active. If the string is not valid JSON, it throws a SyntaxError, so production code should wrap it in a try/catch.

Unlike the dangerous eval, JSON.parse only accepts valid JSON and never executes code, which is exactly why you should never parse JSON with eval.

Parse a JSON stringjavascript
const obj = JSON.parse('{"id":1,"active":true}');
obj.id;     // 1
obj.active; // true

JSON.stringify: object to text

JSON.stringify does the reverse, turning a JavaScript value into a JSON string. Pass a third argument to control indentation: JSON.stringify(obj, null, 2) pretty-prints with two-space indentation, which is ideal for logs and files. With no spacing argument you get compact, minified output suitable for network payloads.

Serialize back to JSONjavascript
JSON.stringify({ id: 1 });          // '{"id":1}'
JSON.stringify({ id: 1 }, null, 2); // pretty-printed

The reviver: transform values while parsing

JSON.parse accepts an optional second argument, the reviver function, called for every key/value pair as the object is built. It is the clean way to restore types that JSON cannot represent. A common use is converting ISO date strings back into Date objects: in the reviver, detect a date-shaped string and return new Date(value); otherwise return the value unchanged.

The reviver can also strip dangerous keys (returning undefined removes the property), which is one defense against prototype pollution from untrusted input.

A reviver restores types while parsingjavascript
JSON.parse(text, (key, value) =>
  key === "createdAt" ? new Date(value) : value
);

The replacer: control what gets serialized

JSON.stringify accepts an optional second argument, the replacer, which can be a function or an array of allowed keys. As a function it is called for each value and lets you transform or omit it — for example redacting a password field or serializing a custom type. As an array, ['id', 'name'] limits output to just those keys, a quick way to whitelist fields before sending data to a client.

Values JSON cannot represent

  • undefined, functions, and symbols are dropped from objects and become null inside arrays.
  • BigInt throws a TypeError on JSON.stringify unless you handle it in a replacer (for example converting it to a string).
  • Date objects are serialized via their toJSON method to an ISO string, but JSON.parse will not turn them back into Dates without a reviver.
  • NaN and Infinity are serialized as null, silently losing information.
  • Map, Set, and typed arrays are not serialized usefully and need custom handling.

Common parsing errors

The classic error is 'Unexpected token in JSON', which means the string is not valid JSON — often because it is actually HTML (an error page returned by a failing API), an empty string, or a JavaScript object literal with single quotes and trailing commas. When fetching, confirm the response is JSON before parsing, and log the raw text on failure so you can see what actually arrived.

If you use the Fetch API, response.json() parses the body for you and rejects the promise on invalid JSON, so handle that rejection rather than assuming success.

Security: parsing untrusted JSON

JSON.parse itself is safe — it never executes code — but the data it produces can still be hostile. Validate untrusted input against a schema with a library like Zod, Ajv, or Joi before trusting it, both to guarantee shape and to block prototype-pollution payloads that target __proto__. For deep-cloning objects in modern code, prefer structuredClone over the old JSON.parse(JSON.stringify(obj)) trick, which silently drops undefined, functions, and Dates.

Debugging JSON outside your code

When a payload will not parse, it is faster to inspect the data than to add console.logs. Paste it into a JSON validator to get the exact line and column of the syntax error, a formatter to make the structure readable, or a repair tool if it arrived with trailing commas or code fences from an LLM. Fixing the data is usually quicker than chasing a SyntaxError stack trace.

Frequently asked questions

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

JSON.parse converts a JSON string into a JavaScript value (deserialization); JSON.stringify converts a JavaScript value into a JSON string (serialization). They are inverses of each other.

How do I pretty-print JSON in JavaScript?

Pass a spacing argument to JSON.stringify, for example JSON.stringify(obj, null, 2) for two-space indentation. The second argument can be null or a replacer; the third controls indentation.

Why do I get 'Unexpected token in JSON'?

The string is not valid JSON. Common causes are an HTML error page returned instead of JSON, an empty response body, single quotes, or trailing commas. Log the raw text to see what you actually received before parsing.

How do I parse JSON with dates in JavaScript?

JSON has no date type, so dates arrive as ISO strings. Use the reviver argument of JSON.parse to detect date-shaped strings and return new Date(value), converting them back to Date objects during parsing.

Is JSON.parse safe for untrusted input?

JSON.parse never executes code, so it is safe from code injection — unlike eval. However, the resulting data can still be malicious (for example prototype pollution), so validate untrusted JSON against a schema before using it.

Related tools

Try these tools

Keep reading

Related guides