JavaScript has the best built-in JSON support of any language — JSON.stringify and JSON.parse are right there, no imports required. Here's everything you can do with them, plus a few patterns the docs don't cover well.
The basics
Pretty-print JSON in one line:
const data = { users: [{ name: "Alice" }, { name: "Bob" }] };
console.log(JSON.stringify(data, null, 2));
The three arguments to JSON.stringify(value, replacer, space):
- value — the data to serialize.
- replacer — null to include everything, an array of keys to whitelist, or a function for fine-grained control.
- space — number of spaces for indentation, or a string to use as indent unit.
Most calls use JSON.stringify(data, null, 2).
Indent options
JSON.stringify(data, null, 2); // 2 spaces
JSON.stringify(data, null, 4); // 4 spaces
JSON.stringify(data, null, "\t"); // tabs
JSON.stringify(data, null, " "); // custom indent (any string)
JSON.stringify(data); // minified (no indent)
Filtering with the replacer parameter
The replacer can be an array of keys to include:
const data = { name: "Alice", age: 30, password: "secret" };
JSON.stringify(data, ["name", "age"], 2);
// { "name": "Alice", "age": 30 }
Or a function for custom transformations:
JSON.stringify(data, (key, value) => {
if (key === "password") return undefined; // omit
if (typeof value === "string") return value.toLowerCase();
return value;
}, 2);
Useful for stripping sensitive fields before logging, or normalizing values.
Handling special types
JavaScript has a few values that don't round-trip cleanly:
- undefined in an object — silently omitted. In an array — becomes
null. - NaN, Infinity — become
null. - Date — serialized via
toJSON()as an ISO string. Becomes a plain string on parse. - BigInt — throws an error. You must convert to string explicitly.
- Function — silently omitted (in objects) or becomes
null(in arrays). - Symbol — silently omitted as a property key.
Custom toJSON methods
Any object can define a toJSON() method that returns its serialized form:
class Money {
constructor(amount, currency) {
this.amount = amount;
this.currency = currency;
}
toJSON() {
return `${this.amount} ${this.currency}`;
}
}
JSON.stringify({ price: new Money(99.99, "USD") }, null, 2);
// { "price": "99.99 USD" }
This is how Date works internally — its toJSON returns an ISO string.
Sorting keys (no built-in)
Unlike Python's sort_keys=True, JavaScript has no built-in. Implement with a replacer:
function stringifySorted(obj, space = 2) {
return JSON.stringify(obj, (key, value) => {
if (value && typeof value === "object" && !Array.isArray(value)) {
return Object.keys(value).sort().reduce((sorted, k) => {
sorted[k] = value[k];
return sorted;
}, {});
}
return value;
}, space);
}
Useful for deterministic output — useful in tests, snapshot comparisons, and content-addressed storage.
Formatting a JSON file in Node.js
const fs = require("node:fs");
const text = fs.readFileSync("input.json", "utf-8");
const data = JSON.parse(text);
fs.writeFileSync("output.json", JSON.stringify(data, null, 2));
For one-liner CLI usage:
node -e "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync('/dev/stdin','utf-8')), null, 2))" < input.json
In the browser
Identical API to Node.js — same JSON.stringify. For displaying JSON in a webpage with syntax highlighting, two common approaches:
// As text in a <pre> element
document.getElementById("out").textContent = JSON.stringify(data, null, 2);
// With highlighting via a library like highlight.js or prismjs
const pre = document.getElementById("out");
pre.innerHTML = hljs.highlight(JSON.stringify(data, null, 2), { language: "json" }).value;
Large JSON performance
The native JSON.stringify is implemented in C++ in every modern engine — there's nothing faster you can do in JavaScript. For multi-megabyte JSON, the bottleneck is usually I/O, not stringification.
For streaming serialization of very large data, look at libraries like json-stream-stringify that yield chunks incrementally rather than allocating the whole string.
Error handling
Wrap parsing in try/catch:
function safeParse(text) {
try {
return { data: JSON.parse(text), error: null };
} catch (e) {
return { data: null, error: e.message };
}
}
Modern engines include a position offset in the error message that you can extract for line/column reporting.
Quick CLI alternatives
If Node isn't installed, options:
jq . file.json— the standard JSON CLI tool. Available on macOS via Homebrew, on Linux via package manager.python -m json.tool input.json— works wherever Python is installed.- Our JSON Formatter — paste, click, done. Browser-only.
Wrap-up
JSON.stringify with indent=2 covers 95% of cases. Reach for the replacer parameter when you need to filter or transform. Implement your own sorting if determinism matters. And for one-off interactive formatting, just use a web tool.