JSON.parse()
Parses a JSON string into a JavaScript value, optionally transforming each value with a reviver.
JSON.parse(text)
JSON.parse(text, reviver)- Added in JavaScript ES5
Parameters
| Parameter | Type | Description |
|---|---|---|
$text | string | The string to parse as JSON. It must conform to the JSON grammar; the value is coerced to a string first. |
$reviveroptional | function= undefined | Called as reviver(key, value, context) for every key/value pair, innermost first, with the containing object as this. Return a replacement value, or undefined to delete the property. Non-callable values are ignored. |
Return value
Object | Array | string | number | boolean | nullThe JavaScript value corresponding to the JSON text, after each value has passed through the reviver if one was given.
Errors
Throws a SyntaxError if the text does not conform to the JSON grammar — trailing commas, single quotes, unquoted keys, comments, and NaN or Infinity literals are all rejected.
Changelog
- PHP ES2025The reviver receives a third argument, context, when the value is a primitive. context.source holds the original JSON text for that value, which lets you recover full precision for large numbers.
JSON.parse() turns JSON text into live values. Reach for it on any response body, file, or environment variable that carries structured data as a string.
The reviver runs bottom-up
If you pass a reviver it is called for every key, starting at the deepest leaves and finishing with the root under the key "". Because children are visited first, the value you receive for an object already has its own properties revived. Returning undefined deletes that key from the result, and this is the object currently being rebuilt. This is the idiomatic place to turn ISO date strings into Date objects or arrays back into a Map.
Numbers and precision
Every JSON number becomes a double, so 12345678901234567890 comes back rounded and 1e999 becomes Infinity. In a current engine the reviver's third argument gives you context.source, the original digits as written, so you can hand them to BigInt or keep them as a string.
What it rejects
JSON is stricter than JavaScript object syntax. Trailing commas, single-quoted strings, unquoted keys, comments and undefined all raise SyntaxError, so wrap parsing of anything you did not produce in a try block.
Example
When to use it
- Decode a JSON response body read as text before working with its fields.
- Revive ISO date strings into Date objects while reading a stored record.
- Deep-clone a plain data object with JSON.parse(JSON.stringify(value)).
- Recover an exact 64-bit id from an API using context.source and BigInt.
Frequently asked questions
Why do I get "Unexpected token < in JSON at position 0"?
The text being parsed is not JSON at all — it usually starts with an HTML error page returned by the server instead of the expected payload. Log the raw string before parsing, and check the response status and content type first.
How do I convert date strings back into Date objects?
Pass a reviver that returns new Date(value) for the keys you know hold timestamps, for example (key, value) => (key === "createdAt" ? new Date(value) : value). JSON has no date type, so a plain parse always leaves them as strings.
Is JSON.parse(JSON.stringify(obj)) a good way to deep-clone?
It works only for plain JSON-compatible data, and drops undefined values, functions, symbols, Maps, Sets, and class identity while turning Dates into strings. Use structuredClone() for a faithful copy that also handles cycles.
More examples
The reviver visits leaves before their parents
The log shows "qty" first, then "0" for the array element, then "items", then "code", and finally the root under the empty-string key. Array indices arrive as strings, and by the time a container is visited its children have already been revived.
const order = JSON.parse('{"items":[{"qty":2}],"code":"A1"}', function (key, value) {
console.log("visit", JSON.stringify(key), "->", JSON.stringify(value));
return value;
});
console.log(order.items[0].qty);Keeping full precision with context.source
The plain parse rounds the id to 12345678901234567000 because it becomes a double. context.source hands back the digits exactly as they appeared in the text, so BigInt can hold the id and the trailing zero of 1.50 survives as a string. Requires an engine with JSON source-text access.
const text = '{"id":12345678901234567890,"price":1.50}';
console.log(JSON.parse(text).id);
const exact = JSON.parse(text, (key, value, context) => {
if (key === "id") return BigInt(context.source);
if (key === "price") return context.source;
return value;
});
console.log(exact.id.toString(), exact.price);Guarding untrusted input
An empty string, the text "undefined", and a trailing comma are each a SyntaxError rather than a value, so every one falls through to the supplied default. This is the shape most "unexpected end of JSON input" bugs take.
function safeParse(text, fallback = null) {
try {
return JSON.parse(text);
} catch {
return fallback;
}
}
console.log(safeParse('{"ok":true}'));
console.log(safeParse("", { ok: false }));
console.log(safeParse("undefined", { ok: false }));
console.log(safeParse("[1, 2, 3,]", []));
Discussion