The Complete JSON.stringify API
JSON.stringify is the built-in JavaScript function for converting values to JSON strings. It is available in all modern browsers and Node.js. Understanding all three of its parameters unlocks powerful use cases beyond basic serialisation.
// ── The three parameters ──────────────────────────────────────────────
// 1. Minified (no whitespace) — use for network transmission
JSON.stringify({ a: 1, b: [2, 3] })
// '{"a":1,"b":[2,3]}'
// 2. 2-space indented — most common for readability
JSON.stringify({ a: 1, b: [2, 3] }, null, 2)
// {
// "a": 1,
// "b": [
// 2,
// 3
// ]
// }
// 3. Tab indented — useful when tabs are the project standard
JSON.stringify({ a: 1 }, null, '\t')
// {
// \t"a": 1
// }
// 4. Custom string prefix (unusual but valid)
JSON.stringify({ a: 1 }, null, '|-')
// {
// |-"a": 1
// }The Replacer Parameter — Filtering and Transforming
The second parameter (replacer) is one of the most underused features of JSON.stringify. It gives you control over which keys are included and how values are transformed.
// ── Array replacer — include only these keys ─────────────────────────
const user = { id: 1, name: 'Alice', password: 'secret', email: '[email protected]' };
JSON.stringify(user, ['id', 'name', 'email'], 2)
// {
// "id": 1,
// "name": "Alice",
// "email": "[email protected]"
// }
// Note: "password" is excluded because it's not in the array
// ── Function replacer — transform values ─────────────────────────────
JSON.stringify(user, (key, value) => {
if (key === 'password') return undefined; // exclude this key
if (typeof value === 'string') return value.toUpperCase(); // transform
return value; // pass through everything else
}, 2)
// ── Exclude null values ───────────────────────────────────────────────
const data = { a: 1, b: null, c: 'hello', d: null };
JSON.stringify(data, (k, v) => v === null ? undefined : v, 2)
// {
// "a": 1,
// "c": "hello"
// }
// ── Date to ISO string (this happens automatically actually) ──────────
JSON.stringify(new Date('2026-08-06'))
// '"2026-08-06T00:00:00.000Z"'JSON.parse — Reconstructing Data from JSON Strings
// ── Basic parsing ────────────────────────────────────────────────────
const json = '{"name":"Alice","age":30}';
const obj = JSON.parse(json);
console.log(obj.name); // 'Alice'
console.log(typeof obj.age); // 'number'
// ── The reviver function — transform during parsing ───────────────────
const withDates = '{"name":"Event","date":"2026-08-06T00:00:00.000Z"}';
const parsed = JSON.parse(withDates, (key, value) => {
// Convert ISO date strings back to Date objects
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value);
}
return value;
});
console.log(parsed.date instanceof Date); // true
// ── Safe JSON.parse wrapper ───────────────────────────────────────────
function safeJsonParse(str, fallback = null) {
try {
return JSON.parse(str);
} catch {
return fallback;
}
}
safeJsonParse('{"a":1}'); // { a: 1 }
safeJsonParse('invalid'); // null (fallback)Handling Edge Cases and Special Values
// ── Functions are omitted ─────────────────────────────────────────────
JSON.stringify({ fn: () => 'hello', name: 'test' })
// '{"name":"test"}' — fn is silently dropped
// ── undefined in objects is omitted; in arrays becomes null ───────────
JSON.stringify({ a: undefined, b: 'keep' })
// '{"b":"keep"}'
JSON.stringify([1, undefined, 3])
// '[1,null,3]'
// ── NaN and Infinity become null ─────────────────────────────────────
JSON.stringify({ n: NaN, i: Infinity, ni: -Infinity })
// '{"n":null,"i":null,"ni":null}'
// ── Circular references throw ─────────────────────────────────────────
const a = {};
a.self = a;
try {
JSON.stringify(a);
} catch (e) {
console.error(e.message); // "Converting circular structure to JSON"
}
// Fix circular references with a custom replacer:
const seen = new WeakSet();
const safeStringify = (obj, indent = 2) => JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return '[Circular]';
seen.add(value);
}
return value;
}, indent);
// ── BigInt throws ─────────────────────────────────────────────────────
// JSON.stringify({ big: 9007199254740993n }); // TypeError: Do not know how to serialize a BigInt
// Fix: convert to string in replacer
JSON.stringify({ big: 9007199254740993n }, (k, v) =>
typeof v === 'bigint' ? v.toString() : v
);
// '{"big":"9007199254740993"}'Formatting JSON in React and Next.js
// ── Display formatted JSON in a React component ──────────────────────
function JsonDisplay({ data }) {
return (
<pre className="bg-gray-900 text-green-400 p-4 rounded overflow-auto text-sm">
{JSON.stringify(data, null, 2)}
</pre>
);
}
// ── JSON pretty-print in a Next.js API route ──────────────────────────
// pages/api/data.js or app/api/data/route.js
export async function GET() {
const data = { message: 'Hello', timestamp: new Date().toISOString() };
return new Response(JSON.stringify(data, null, 2), {
headers: { 'Content-Type': 'application/json' }
});
}
// ── Log formatted JSON to console during debugging ─────────────────────
// Instead of:
console.log(response.data); // [object Object]
// Do this:
console.log(JSON.stringify(response.data, null, 2)); // readable JSON
// Even better — console.dir
console.dir(response.data, { depth: null, colors: true }); // (Node.js)Performance: When to Format vs When to Minify
Formatting adds bytes. A rule of thumb:
- Development logs, debugging, documentation — always format. Readability is worth the extra bytes in development contexts.
- HTTP API responses in production — minify. Whitespace typically adds 10–40% to JSON payload size. This matters at scale.
- Configuration files in version control — format and sort keys. Formatted JSON produces clean, meaningful diffs in code reviews.
- localStorage / IndexedDB — minify. Browser storage quotas are limited; every byte saved extends how much data you can store.
Key Facts
- Format (pretty print):
- JSON.stringify(obj, null, 2)
- Minify:
- JSON.stringify(obj) — no third arg
- Re-format a string:
- JSON.stringify(JSON.parse(str), null, 2)
- Filter keys:
- JSON.stringify(obj, ['a','b'], 2)
- Transform values:
- JSON.stringify(obj, (k,v) => ..., 2)
- Parse with transform:
- JSON.parse(str, (k,v) => ...)
Related JSON Tools
- Format JSON Online — interactive formatter
- Pretty Print JSON — multi-language examples
- Minify JSON Online — compress JSON for production
- JSON Validator Online — validate without formatting
- JSON Path Finder — query nested JSON
- JSON to TypeScript — generate TypeScript types from JSON