JSON
JSON — JavaScript Object Notation — is a text format for exchanging data. Almost every web API sends and receives it, configuration files are written in it, and browsers store data with it. JavaScript converts between JSON text and real values with two functions: JSON.stringify and JSON.parse.
JSON is text
JSON looks like a JavaScript object literal, but it's a string with stricter rules:
{
"id": 42,
"name": "Ana",
"active": true,
"roles": ["editor", "admin"],
"manager": null,
"address": { "city": "Lisbon" }
}
- Keys must be in double quotes. Strings must use double quotes too.
- Allowed values: strings, numbers,
true/false,null, arrays and objects. - No functions,
undefined, dates, comments or trailing commas.
JSON.stringify: value → text
const user = { id: 42, name: "Ana", roles: ["editor"], active: true }; const text = JSON.stringify(user); console.log(text); console.log(typeof text);
{"id":42,"name":"Ana","roles":["editor"],"active":true}
stringPass a third argument to pretty-print with indentation — great for debugging and config files:
console.log(JSON.stringify({ name: "Ana", tags: ["a", "b"] }, null, 2));
{
"name": "Ana",
"tags": [
"a",
"b"
]
}What stringify drops or changes
const data = { title: "Report", created: new Date(Date.UTC(2026, 0, 15)), notes: undefined, render() {}, score: NaN, big: Infinity, }; console.log(JSON.stringify(data));
{"title":"Report","created":"2026-01-15T00:00:00.000Z","score":null,"big":null}Functions and undefined properties disappear, NaN and Infinity become null, and dates become ISO strings. Maps, Sets and class instances lose their special behaviour. Keep data you serialise to plain objects, arrays and primitives.
JSON.parse: text → value
const text = '{"product":"Lamp","price":30,"tags":["home","light"]}'; const product = JSON.parse(text); console.log(product.price * 2); console.log(product.tags[1]);
60 light
Handling invalid JSON
JSON.parse throws a SyntaxError if the text isn't valid JSON — always wrap it in try/catch when the text comes from outside your program:
function safeParse(text, fallback = null) { try { return JSON.parse(text); } catch { return fallback; } } console.log(safeParse('{"ok": true}')); console.log(safeParse("{ok: true}")); console.log(safeParse("", []));
{ ok: true }
null
[]The second example fails because the key isn't quoted — valid JavaScript, invalid JSON.
Reviver and replacer functions
Both functions accept an optional callback that runs for every key–value pair. A reviver in parse can turn date strings back into Date objects:
const json = '{"event":"Launch","at":"2026-11-01T09:00:00.000Z"}'; const parsed = JSON.parse(json, (key, value) => key === "at" ? new Date(value) : value ); console.log(parsed.at instanceof Date, parsed.at.getUTCFullYear());
true 2026
A replacer in stringify can filter or transform values — for example, passing an array of keys keeps only those properties:
const user = { id: 1, name: "Ana", passwordHash: "x9f…" }; console.log(JSON.stringify(user, ["id", "name"]));
{"id":1,"name":"Ana"}Custom serialisation with toJSON
class Money { constructor(cents) { this.cents = cents; } toJSON() { return (this.cents / 100).toFixed(2); } } console.log(JSON.stringify({ total: new Money(1999) }));
{"total":"19.99"}Common uses
- APIs —
fetchresponses are usually JSON;await response.json()parses them (lesson 49). - Storage —
localStorageonly stores strings, so objects are stringified on save and parsed on load (lesson 48). - Configuration —
package.json,tsconfig.jsonand many other config files.