Pretty-printing is just the beginning. JSON (RFC 8259) rules every public API, every config file, every browser DevTools panel — and most teams never go further than a basic formatter. This guide shows the techniques that separate fluent developers from the rest: schema validation, tree-view navigation, key sorting for diffable output, minification economics, JSONPath / JMESPath queries, and the strict spec rules (no comments, no trailing commas, only double quotes) that catch 80% of production bugs.
- Why Formatting Matters
- JSON Spec Rules That Trip Everyone Up
- Validation: Find Errors Instantly
- Tree View: Navigate Deeply Nested Data
- Key Sorting for Diffable JSON
- Minification: Bytes vs Readability
- JSONPath, JMESPath & jq
- Schema Validation with JSON Schema
- Performance Tips for Large Files
- Common Mistakes
- Tools
- FAQ
- References
Why Formatting Matters
An unformatted 80 KB Stripe webhook payload is one line of unreadable text. Formatted, it becomes a navigable document that reveals customer IDs, line items, metadata, and signatures at a glance. Beyond reading, consistent formatting unlocks diffing, code review, caching by content hash, and cryptographic signing (canonical form).
JSON Spec Rules That Trip Everyone Up
| Rule | Allowed? | Note |
|---|---|---|
| Single-quoted strings | No | JSON requires " |
| Trailing commas | No | JS allows; JSON doesn't |
// comments | No | Use JSONC for configs |
| Unquoted keys | No | All keys must be "strings" |
NaN, Infinity, undefined | No | Use null or omit |
| Hex / octal numbers | No | Decimal only |
Leading + on numbers | No | +1 is invalid |
| Duplicate keys | Tolerated | Behavior undefined; last-wins in most parsers |
| BOM byte order mark | No | Must be UTF-8 without BOM |
Numbers above 2^53 | Loss | Use string IDs for large integers |
🚫 Big-int trap: JavaScript's JSON.parse silently rounds integers above 2^53. Always serialize 64-bit IDs (Snowflake, Twitter, Discord) as strings.
Validation: Find Errors Instantly
Our JSON Formatter validates as you type. Common errors and their fixes:
| Error message | Likely cause | Fix |
|---|---|---|
Unexpected token } in JSON | Trailing comma | Remove the last comma |
Unexpected token ' in JSON | Single quotes | Replace with " |
Unexpected end of JSON input | Missing closing bracket | Match braces/brackets |
Bad control character | Raw newline in string | Escape as
|
Unexpected token N | NaN in payload | Replace with null |
Tree View: Navigate Deeply Nested Data
Once a payload exceeds ~200 lines, scrolling becomes hostile. Tree view collapses every object and array into a clickable node, lets you focus on a single subtree, and shows the type + child count at every level. It's the GraphQL Explorer experience for any JSON.
📌 In our JSON Formatter, click any object/array node to copy that exact subtree to clipboard — perfect for sharing reproducers.
Key Sorting for Diffable JSON
Two JSON objects with identical content but different key orders look completely different in a text diff. Canonical JSON (RFC 8785) defines a deterministic ordering — sort keys lexicographically at every level. Use it for:
- Comparing staging vs production configs
- Hashing payloads for cache keys / dedupe
- Signing JSON cryptographically (JWS, COSE)
- Producing stable Git diffs of generated files
Minification: Bytes vs Readability
| Mode | Size | Use for |
|---|---|---|
| Pretty (2-space) | +30–50% | Editing, code review |
| Pretty (4-space) | +50–80% | Documentation |
| Minified | baseline | API responses, network |
| Minified + gzip | −65–80% | Static assets, REST/GraphQL |
JSONPath, JMESPath & jq
For extracting subsets of large payloads:
| Language | Example | Result |
|---|---|---|
| JSONPath | $.users[?(@.role=='admin')].email | All admin emails |
| JMESPath | users[?role=='admin'].email | Same, AWS-flavoured |
| jq | .users[] | select(.role=="admin") | .email | Same, CLI-friendly |
Schema Validation with JSON Schema
For data contracts between services, validate against a JSON Schema. It catches typos, missing required fields, wrong types, out-of-range values, and unknown properties at the boundary — before they cause cascading failures.
{
"type": "object",
"required": ["id", "email"],
"properties": {
"id": { "type": "string", "format": "uuid" },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 }
},
"additionalProperties": false
}
Performance Tips for Large Files
Stream parse >100 MB files with oboe.js / stream-json instead of JSON.parse.
Lazy-render the tree — only expand visible nodes (virtualized lists).
Use NDJSON (newline-delimited) for log streams instead of one giant array.
Compress on the wire — Brotli or gzip cuts payloads 5–10× with zero code change.
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Using JSON for configs with comments | Can't document choices | Switch to JSONC, JSON5, TOML, or YAML |
| Returning numbers for IDs | Precision loss above 2^53 | Always strings for large IDs |
JSON.stringify with Date | Loses timezone | Serialize as ISO 8601 strings |
| Stringifying circular references | TypeError | Use a replacer function or break the cycle |
| Escaping unicode unnecessarily | é instead of é | Output raw UTF-8 |
Tools
- 🔧 JSON Formatter — pretty/minify, tree view, sort keys, validate
- 🔧 JSON to CSV — flatten arrays of objects to spreadsheet
- 🔧 YAML ↔ JSON — round-trip configs
- 🔧 URL Encoder — for embedding JSON in query strings
- 🔧 Base64 Encoder — for safe transmission of JSON blobs
Frequently Asked Questions
Why doesn't JSON support comments?
Douglas Crockford intentionally removed them so JSON would not be used as a programming language. For commented configs, use JSONC, JSON5, or YAML.
Are duplicate keys legal?
The spec discourages them but does not forbid them. Most parsers keep the last value. Don't rely on either behavior.
How do I represent dates in JSON?
Use ISO 8601 strings such as "2026-05-02T14:30:00Z". There is no native date type.
Why does my 19-digit ID lose digits?
JavaScript numbers are IEEE-754 doubles, accurate only up to 2^53. Serialize big IDs as strings.
Should I sort keys before signing JSON?
Yes — use canonical JSON (RFC 8785). Otherwise the same payload produces different signatures.
What is NDJSON?
Newline-delimited JSON: one valid JSON value per line. Ideal for logs, streaming, and append-only data because each line can be parsed independently.
References
- 📄 RFC 8259 — The JSON Data Interchange Format
- 📄 RFC 8785 — JSON Canonicalization Scheme
- 📄 JSON Schema specification
- 📄 JMESPath reference
- 📄 jq manual
- 📄 NDJSON spec
🚀 Free ToolZilla tools used in this article
All client-side, no signup, no upload — open them in a new tab while you read:
- 🔧 JSON Formatter — try it free in your browser.
- 🔧 JSON to CSV Converter — try it free in your browser.
- 🔧 YAML / JSON Converter — try it free in your browser.
- 🔧 URL Encoder & Decoder — try it free in your browser.
- 🔧 Base64 Encoder & Decoder — try it free in your browser.
- 🧰 Browse all 60+ free tools →
Mastering JSON is less about syntax and more about discipline: validate at every boundary, sort keys for diffable output, minify for the wire, stringify big IDs, and reach for tree view or jq the moment a payload outgrows your screen. Pretty-printing is the first 10% — the rest is where the real productivity lives.

