JSON.parse()
ES5+Parses a JSON string and reconstructs the JavaScript value it describes — objects, arrays, strings, numbers, booleans, and null. An optional reviver function lets you transform each value as it is restored, for example turning ISO date strings back into Date objects.
Syntax
JSON.parse(text, reviver)Parameters
text string The string to parse as JSON
reviver Function optionalA function that transforms the results
Return Value
The JavaScript value corresponding to the given JSON text
Examples
const json = '{"name":"John","age":30}';
const obj = JSON.parse(json);
console.log(obj.name);
console.log(obj.age); 📌 When to Use
Use JSON.parse() at every boundary where structured data arrives as text: HTTP responses read with response.text(), values retrieved from localStorage or sessionStorage (which store strings only), messages from WebSockets and postMessage, configuration files, and queue payloads. It is the exact inverse of JSON.stringify(), so the two form the standard round trip for persisting and transmitting state. Prefer response.json() when using fetch — it parses for you — but reach for JSON.parse() directly when you already hold the string, need a reviver, or want to control error handling around malformed input. The reviver parameter is the built-in hook for restoring types JSON cannot express: Dates, BigInts serialized as strings, Maps and Sets encoded as arrays. Treat every parse of external input as a fallible operation — network responses get truncated, users hand-edit localStorage, and servers occasionally return HTML error pages where JSON was expected — so a try-catch wrapper (or a small safeParse helper returning a result object) is standard practice. As a bonus, engines parse large pure-data literals faster through JSON.parse("...") than through JavaScript object-literal syntax, which is why bundlers sometimes emit big embedded data this way.
⚠️ Common Mistakes
Trusting numeric precision blindly - JSON numbers become IEEE-754 doubles, so 64-bit IDs like 9007199254740993 from a backend silently round to a nearby representable value before your code ever sees them. APIs with big integer IDs must send them as strings, or you must parse with a BigInt-aware strategy.
Double-parsing double-encoded JSON - when a server accidentally stringifies twice, the first parse returns a string that itself looks like JSON, and code that never checks typeof keeps working with a string. Conversely, parsing something already parsed throws. When parse errors mention an unexpected token at position 0, log the raw payload first.
Assuming duplicate keys are an error - duplicate keys in the source text are accepted and the last occurrence silently wins, so malformed producers can drop or override data without any exception being raised on your side.
Not wrapping JSON.parse() in try-catch - invalid JSON throws a SyntaxError.
Assuming Date objects are preserved - they are parsed as strings and need a reviver to convert.
Using JSON.parse() on already-parsed objects, causing errors.
✅ Best Practices
Wrap parsing in a tiny helper that returns a discriminated result - function safeParse(s) { try { return { ok: true, value: JSON.parse(s) }; } catch (e) { return { ok: false, error: e }; } } - so call sites handle failure explicitly instead of letting one corrupted localStorage entry crash the whole page.
Validate the parsed shape before using it - JSON.parse guarantees syntax, not structure. Follow it with a schema check (zod, ajv, or hand-rolled guards) whenever data crosses a trust boundary, because "valid JSON" still includes null, [], or a completely different object than the one you expect.
Parse once at the boundary and pass the object around - re-parsing the same string in different modules wastes CPU and risks divergent error handling; hoist the parse into the API or storage layer and share the result.
Always validate or try-catch JSON.parse() for untrusted input to prevent crashes.
Use a reviver function to convert date strings back to Date objects.
⚡ Performance Notes
JSON.parse() is implemented in native code and is dramatically faster than any JavaScript-level parser — and notably faster than the JavaScript parser itself for equivalent data, which is why bundlers sometimes ship large embedded datasets as JSON.parse("...") rather than object literals. Cost scales linearly with input size; multi-megabyte payloads can still block the main thread for tens of milliseconds, so parse huge documents in a Web Worker or split APIs into smaller pages. Supplying a reviver changes the cost profile significantly: the function is invoked for every key at every nesting level, so a reviver over a large response can dominate total parse time — keep it to cheap checks (typeof tests, regex only when the string plausibly looks like a date) and prefer transforming just the few known fields after parsing when the schema is fixed. The parsed object tree also occupies several times the memory of the source string, worth remembering when caching parsed results.
🌍 Real World Example
Safe API Response Parser
This API-response parser packages the two habits production parsing needs. A dateReviver spots ISO-8601 timestamp strings by regex and revives them into real Date objects during the parse itself, so downstream code can call getTime() or compare dates without conversion logic sprinkled everywhere. The try-catch wrapper converts malformed payloads into a { success, error, data } result object instead of an exception, letting callers branch on failure cleanly — the shape you want when a flaky backend or truncated response must degrade gracefully rather than crash the UI.
function parseApiResponse(jsonString) {
const dateReviver = (key, value) => {
// Convert ISO date strings to Date objects
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value);
}
return value;
};
try {
const data = JSON.parse(jsonString, dateReviver);
return { success: true, data };
} catch (error) {
return {
success: false,
error: error.message,
data: null
};
}
}
const response = '{"user":"John","createdAt":"2024-01-15T10:30:00.000Z"}';
const result = parseApiResponse(response);
console.log(result.data.createdAt instanceof Date); // true