JSON Formatting and Validation: Best Practices for Clean, Readable JSON
JSON is the universal data interchange format, but poorly formatted or invalid JSON is a common source of bugs. Learn JSON syntax rules, formatting best practices, how to validate JSON, and common pitfalls to avoid.
What Is JSON?
JSON (JavaScript Object Notation) is a lightweight, text-based data interchange format. Despite its name, it is language-agnostic and is supported natively by virtually every modern programming language.
JSON has six value types:
- string —
"hello"(must use double quotes) - number —
42,3.14,-7,1.5e10 - boolean —
true,false - null —
null - array —
[1, "two", true] - object —
{"key": "value"}
JSON vs JavaScript Objects
JSON looks like JavaScript but is more restrictive:
| Feature | JSON | JavaScript object |
|---|---|---|
| Key quoting | Double quotes required | Optional |
| String quoting | Double quotes only | Single or double |
| Trailing commas | Not allowed | Allowed |
| Comments | Not allowed | Allowed |
undefined | Not allowed | Allowed |
| Functions | Not allowed | Allowed |
NaN, Infinity | Not allowed | Allowed |
// This is NOT valid JSON (comment + trailing comma)
{
"name": "Alice", // person's name
"age": 30,
}
// This IS valid JSON
{
"name": "Alice",
"age": 30
}
Parsing and Serialising in JavaScript
// Parse a JSON string → JavaScript value
const data = JSON.parse('{"name":"Alice","age":30}');
data.name; // "Alice"
// Serialise a JavaScript value → JSON string
const json = JSON.stringify({ name: "Alice", age: 30 });
// '{"name":"Alice","age":30}'
// Pretty-print with 2-space indentation
const pretty = JSON.stringify(data, null, 2);
Formatting for Readability
Minified JSON (no whitespace) is optimal for network transmission. Pretty-printed JSON (with indentation) is optimal for human reading. The difference is purely whitespace — the data is identical.
// Minified
{"user":{"name":"Alice","roles":["admin","editor"]}}
// Pretty-printed (2-space indent)
{
"user": {
"name": "Alice",
"roles": [
"admin",
"editor"
]
}
}
Use minified JSON in production APIs (saves bandwidth) and pretty-printed JSON in configuration files (readable by developers).
Common Validation Errors
Trailing commas
{
"a": 1,
"b": 2, ← invalid trailing comma
}
Single quotes
{
'name': 'Alice' ← must use double quotes
}
Missing quotes on keys
{
name: "Alice" ← key must be quoted
}
Comments
JSON does not support // or /* */ comments. If you need comments in configuration files, use JSONC (JSON with Comments) — supported by VS Code and TypeScript's tsconfig.json.
NaN and Infinity
These JavaScript values have no JSON representation. JSON.stringify(NaN) produces "null".
The JSON.parse Reviver
The second argument to JSON.parse is a reviver function, useful for transforming values during parsing — for example, converting ISO 8601 strings back to Date objects:
JSON.parse(jsonString, (key, value) => {
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value);
}
return value;
});
The JSON.stringify Replacer
The second argument to JSON.stringify filters or transforms values:
// Strip all values where key starts with underscore (private fields)
JSON.stringify(obj, (key, value) => {
if (key.startsWith("_")) return undefined;
return value;
});
// Only include specific keys
JSON.stringify(user, ["name", "email"]);
JSON Schema for Validation
For runtime validation of JSON structure, JSON Schema allows you to define the expected shape:
{
"type": "object",
"required": ["name", "age"],
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0 }
}
}
Libraries like ajv (JavaScript) validate data against a JSON Schema at runtime, which is essential for API input validation.
Large JSON Performance
JSON.parse is fast for typical payloads but blocks the JavaScript event loop. For very large JSON files (>100MB), consider:
- Streaming parsers like
jsonstream— parse line by line or chunk by chunk - Server-side processing — don't send 100MB JSON to a browser
- Pagination — split large datasets into pages