Working with JSON in JavaScript
A practical cookbook for JavaScript developers — parse and stringify values, fetch JSON from an API, persist it in localStorage, and sidestep the gotchas.
JSON is the lingua franca of the web, and JavaScript gives you a tiny but powerful built-in JSON object for working with it. This guide walks through the everyday tasks you will hit in real projects: turning strings into objects and back again, loading JSON over the network, saving it between page loads, formatting it for humans, iterating over it, and avoiding the surprises that bite even experienced developers.
Parsing and stringifying
The two methods you will use most are JSON.parse(), which turns a JSON string into a JavaScript value, and JSON.stringify(), which turns a JavaScript value back into a JSON string. They are exact mirror images of each other.
// String -> value
const user = JSON.parse('{"name":"Ada","age":36}');
user.name; // "Ada"
// Value -> string
const text = JSON.stringify({ name: 'Ada', age: 36 });
text; // '{"name":"Ada","age":36}'Parsing has more depth than it first appears — the reviver argument, error handling, and equivalents in other languages. For a full breakdown, read our JSON.parse() guide.
Fetching JSON from an API
Most JSON you handle arrives over the network. The fetch() API returns a response object, and calling res.json() reads the body and parses it for you — no manual JSON.parse() needed.
async function getUser(id) {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) {
throw new Error(`Request failed: ${res.status}`);
}
const user = await res.json();
return user;
}Always check res.ok before reading the body. fetch() only rejects on network failures — a 404 or 500 still resolves successfully, so an error page can sneak through as if it were valid data.
Storing JSON in localStorage
localStorage can only hold strings, so you stringify on the way in and parse on the way out. This pattern is perfect for caching settings, drafts, or small bits of state between visits.
// Save: value -> string
const settings = { theme: 'dark', fontSize: 14 };
localStorage.setItem('settings', JSON.stringify(settings));
// Read: string -> value
const saved = JSON.parse(localStorage.getItem('settings'));
saved.theme; // "dark"If the key has never been set, getItem() returns null, and JSON.parse(null) happens to yield null rather than throwing — but it is safer to guard for a missing value before parsing.
Pretty-printing JSON
By default JSON.stringify() produces a single compact line. Pass a third argument — the indentation — to get readable, multi-line output for logs, files, or debugging.
const data = { name: 'Ada', roles: ['admin', 'editor'] };
JSON.stringify(data, null, 2);
// {
// "name": "Ada",
// "roles": [
// "admin",
// "editor"
// ]
// }The second argument is a replacer (often null) and the third is the number of spaces per level. You can pass '\t' instead of a number to indent with tabs.
Looping over JSON data
Once a JSON string is parsed, it is just an ordinary object or array — so you iterate with the same tools you already use. For objects, Object.entries() gives you key/value pairs:
const scores = JSON.parse('{"ada":91,"linus":88}');
for (const [name, score] of Object.entries(scores)) {
console.log(`${name}: ${score}`);
}
// ada: 91
// linus: 88For arrays of records, map() is the idiomatic way to transform each item:
const users = JSON.parse('[{"name":"Ada"},{"name":"Linus"}]');
const names = users.map((user) => user.name);
names; // ["Ada", "Linus"]Common gotchas
JSON is a subset of JavaScript, so some values survive the round trip and some quietly do not. Watch out for these:
- undefined and functions disappear.
JSON.stringify()drops object properties whose value isundefinedor a function, and turns them intonullinside arrays. - Dates become strings. A
Dateis serialized to an ISO string, and parsing it back gives you a string — not aDate. Use a reviver to restore it. - Circular references throw. If an object references itself (directly or through a chain),
JSON.stringify()throws aTypeErrorabout a circular structure. - NaN and Infinity become null. These non-finite numbers cannot be represented in JSON, so they are stringified as
null.
Format and validate your JSON instantly
Working with an API response or a localStorage blob? Paste it into our free formatter to pretty-print it, validate the structure, and catch errors before JSON.parse() ever throws.