JSON Essentials for Developers: Beyond Pretty-Printing
Schemas, validation, common pitfalls, and the parser quirks every developer should know about JSON.
JSON looks deceptively simple. Six data types, two structural constructs, no comments. But the moment you go beyond hello-world, you bump into edge cases that have been confusing developers for two decades.
A 30-second refresher
JSON (JavaScript Object Notation) is a text format for structured data. It supports six types:
- String: double-quoted, with escapes for control characters and unicode
- Number: integer or float, no leading zeros, no
NaNorInfinity - Boolean:
trueorfalse - Null:
null - Array: ordered list, comma-separated
- Object: string-keyed map, comma-separated
That's it. No dates, no binary, no UUIDs as a native type — those are all encoded as strings or numbers by convention.
Test JSON instantly: Paste any payload and see structure, errors, and stats:
Open JSON Viewer →Common pitfalls
1. No trailing commas
JavaScript allows trailing commas in objects and arrays. JSON does not.{"a": 1, "b": 2,} is invalid JSON — most parsers will error on the trailing comma.
2. Keys must be double-quoted strings
{name: "Ada"} is JavaScript, not JSON. Valid JSON requires {"name": "Ada"}. Single quotes are also forbidden — only double quotes.
3. No comments
Standard JSON has no comments. If you need them, you're not using JSON — you're using JSON5, JSONC, or YAML. Many config files use these JSON-with-comments variants, but a strict JSON.parse will reject them.
4. Numbers have surprises
- No
NaN,Infinity, or-Infinity— these are not valid JSON. - JavaScript parses all numbers as 64-bit floats, so integers larger than 2^53 lose precision.
- If you need bigger integers (big database IDs), encode them as strings.
5. Dates are strings
JSON has no native date type. Convention is to use ISO 8601 strings (2026-05-07T08:30:00Z). When parsing, you'll need to convert strings back to Date objects manually.
Schemas: validating shape
For any non-trivial JSON exchange, you should validate the structure. The de-facto standard is JSON Schema — a vocabulary for declaring expected shapes:
{
"type": "object",
"required": ["name", "age"],
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0 },
"email": { "type": "string", "format": "email" }
}
}Libraries like Ajv (Node.js), jsonschema (Python), and json-schema (Java) validate any JSON value against a schema and produce detailed error reports. For TypeScript, libraries like Zod and io-ts give you both runtime validation and static types from a single declaration.
Streaming and large payloads
JSON.parse reads the entire string into memory. For very large payloads, this is a problem. Streaming parsers like jsonstream (Node.js) or ijson (Python) emit events as they walk the input, letting you process gigabyte-sized files without exhausting memory.
JSON alternatives worth knowing
- JSON5: JSON with comments, trailing commas, unquoted keys. Used in config files (Babel, ESLint).
- YAML: human-friendly format with comments, multi-line strings, anchors. Used in DevOps (Kubernetes, GitHub Actions).
- TOML: minimal config-file format used by Rust's Cargo and Python's pyproject.toml.
- MessagePack / CBOR: binary formats with the same data model as JSON, but smaller and faster.
Pretty-print etiquette
Two-space indent is the de facto standard for JSON files in version control. Four spaces is acceptable but uses more disk and bandwidth. Minified JSON (no whitespace) is appropriate for HTTP responses where size matters.
Object key order matters for some use cases (deterministic diffs, content addressing). Most parsers preserve insertion order, but the JSON spec doesn't require it. If you need stable order, sort keys explicitly before serializing.