The JSON Debugging Checklist
Every common JSON failure, what actually causes it, and the fastest fix. Each recommended tool is 100% client-side — paste your payload, and nothing leaves your browser.
1 · Unexpected token <x> in JSON at position N
The error everyone hits first. The parser stopped at the first character it couldn't reconcile — the position is exact, but the cause is usually one line above or below it.
| Symptom | Real cause | Fix |
|---|---|---|
Unexpected token } / ,] | Trailing comma before } or ] — legal in JS object literals, illegal in JSON | JSON validator with auto-repair fixes it in one click |
Unexpected token ' | Single-quoted keys or string values ({'a': 1}) | Same validator — it quotes them properly |
Unexpected token / | JavaScript-style // or /* */ comments | Strip them, or validate as JSONC with the JSONC validator |
Unexpected token < | You're parsing an HTML error page (500, login redirect, rate-limit page), not JSON | Look at the first characters of the payload; log the raw response before parsing |
Unexpected token / error at position 0 | UTF-8 BOM or invisible whitespace copied from a PDF/webpage | Unescape & clean the string, then re-validate |
2 · Escaped JSON inside JSON
Logs, queues, and webhooks love to double-encode: a JSON string whose value is another JSON document full of \" and \n.
- CHECK Does the payload start with a quote
"instead of{? It's an escaped string → unescape it, then validate the inner document - CHECK Need the reverse (embed JSON as a string value)? Escape JSON and get a copy-paste-ready literal
- CHECK Payload arrived Base64-wrapped? Base64 → JSON handles lenient/URL-safe variants
- CHECK Sending JSON inside a header or cookie? JSON → Base64
3 · "My JSON is valid but the API rejects it"
Syntactically valid ≠ what the endpoint expects. Contracts break in three ways: wrong types ("42" vs 42), missing required fields, and values that violate a format (date-time, email, uri).
- CHECK No schema yet? Generate a JSON Schema (draft 2020-12) from a sample payload, tighten it, keep it as the contract
- CHECK Schema exists? Validate against it with the schema validator — you get the failing path, not just "invalid"
4 · Extracting one value from a 4,000-line payload
- CHECK Point queries ("every
items[*].sku") → JSONPath evaluator with live match counts - CHECK Reshaping/filtering/grouping → jq online — real jq 1.8 compiled to WebAssembly, same filter language as the CLI:
map(select(.status=="failed")),group_by(.role),sort_by(-.latency)
5 · Comparing two payloads
"Why did the response change after the deploy?" Diff them structurally — key order shouldn't matter, so a text diff lies.
- CHECK JSON diff shows added/removed/changed nodes side by side, with a tree view for deep objects
6 · Converting JSON to something else
| Target | Tool |
|---|---|
| CSV (rows/columns) | JSON → CSV |
| TypeScript types | JSON → TypeScript |
| Python models | JSON → Python |
| Java classes | JSON → Java |
| Rust structs | JSON → Rust |
| Go structs | JSON → Go |
| C# classes | JSON → C# |
| YAML / TOML / XML | → YAML · → TOML · → XML |
7 · Shipping: size, ordering, and dialects
- CHECK Payload too big for a log line or a cache entry? Minify with before/after size stats
- CHECK Diffing or eyeballing is easier with sorted keys → Sort keys (recursive, with depth/scope options)
- CHECK Config allows comments/trailing commas? That's JSON5 or JSONC — don't feed them to a strict parser
- CHECK NDJSON / JSON Lines streams fail as one document → validate line by line