When you get a piece of JSON, the reflex is to format it. That is fine, but formatting only answers one question: can it be parsed? It does not tell you whether the structure is right, what changed since the last version, or where the field you need is buried. This guide chains formatting, repair, validation, extraction, diffing and conversion into one repeatable order using a single order sample, and states the limits of every step.
First, classify what you are holding
"JSON" from different sources is really four different things, and each needs a different first move. Classifying first saves most of the debugging time.
| Input type | Typical source | Signature | First tool |
|---|---|---|---|
| Strict JSON | API responses, database exports | Double quotes, no comments, no trailing commas | JSON Formatter, inspect the tree |
| JSONC / JSON5 | tsconfig, editor settings, hand-written config | Comments, trailing commas, single quotes, bare keys | JSON Repair, then continue with standard JSON |
| Polluted text | Log snippets, chat pastes, Python print output | Smart quotes, True/None, BOM, stray text around it | JSON Repair, then verify by eye |
| Escaped string | A log message field, JSON nested in a string | Whole value wrapped in quotes with \" sequences inside | JSON Escape tool to unescape first |
Step 1: format, and confirm the structure is what you think it is
Paste the content into the JSON Formatter. Input is auto-formatted after about 300 ms, and the output defaults to a collapsible tree. Each node can be expanded, copied or deleted, which makes it a good way to see the hierarchy before deciding what to do next.
One thing worth knowing: the formatter tries standard JSON parsing first and falls back to JSON5 when that fails. So input with comments and trailing commas is formatted successfully, and the output is always standard JSON. That is convenient, but it also means some invalid syntax is quietly forgiven. Here is the same sample used throughout this article.
{
// order sample
"orderId": "A-1001",
"items": [
{"sku": "kb-01", "price": 349.5, "qty": 1},
{"sku": "ms-02", "price": 129, "qty": 2},
],
"paid": true,
}Native JSON.parse rejects this (a comment and two trailing commas), but the formatter accepts it and outputs:
{
"orderId": "A-1001",
"items": [
{
"sku": "kb-01",
"price": 349.5,
"qty": 1
},
{
"sku": "ms-02",
"price": 129,
"qty": 2
}
],
"paid": true
}Step 2: repair only the deterministic problems
The JSON Repair page handles problems that have clear rules: it removes // and /* */ comments (but not text inside strings), drops trailing commas before } and ], replaces curly smart quotes with straight ones, strips a leading BOM, converts Python-style True / False / None to true / false / null, and then formats the result as standard JSON with 2-space indentation.
It does not guess. Missing commas, truncated payloads, unclosed brackets and fields containing undefined are not auto-completed. That is deliberate: a wrong repair is more dangerous than an error, because you end up with data that looks fine but is wrong. For those cases the page shows the parser message and you go back to the source.
Step 3: check the shape before the content with schema generation and validation
When JSON comes from a third-party API, syntactically valid does not mean usable. A missing field, a number that became a string, or a null slipped into an array are all legal JSON with broken business meaning. The routine: generate a draft from a known-good sample with the JSON Schema Generator, edit it, then validate new payloads with the JSON Schema Validator.
For the order sample, the generated schema marks every present field as required, detects price as number and qty as integer, and adds a format when a string looks like a date, email or URL. One thing to watch: for an array with more than one element, the generator creates one schema per element and combines them with oneOf. When two elements have identical shapes, validation reports that exactly one oneOf branch should match but 2 did. So after generating, manually collapse items into a single schema before using it.
The validator supports type, required, properties, items, enum, const, minimum / maximum, minLength / maxLength, pattern, minItems / maxItems, additionalProperties, allOf / anyOf / oneOf, and the email, date, date-time and uri formats, and lists each mismatch as a path plus a reason. It is a lightweight implementation, not a full-specification validator. Do not expect $ref and other advanced features. It is fine for everyday debugging; for compliance gates use the proper validation library in your project.
Step 4: extract with JSONPath instead of counting levels by eye
Once the structure is confirmed and you only need a few fields, use the JSONPath Query page. For the order above:
$.items[*].price → [349.5, 129]
$.items[?(@.price>200)].sku → ["kb-01"]
$.items[*].qty → [1, 2]This beats clicking through a tree for deep structures, and the expression can be reused in code or tests. Note that JSONPath implementations differ in details, especially filter and script expressions, so verify the expression with the library you actually use in production.
Step 5: diff versions to see what really changed
After an API upgrade or a config change, paste both documents into the JSON Diff page. The result lists added, removed, changed and unchanged entries by path, and unchanged entries can be hidden. If you change price from 129 to 119 and add a coupon field, the diff shows items[1].price as changed and coupon as added, which is instant to locate.
One key limitation: arrays are compared by index, with no smart matching. If the new version inserts an element at the start of an array, every following element appears as changed. When you need alignment by id, sort by the primary key in your own script before diffing.
Step 6: convert and measure
| Goal | Tool | Good for | Watch out |
|---|---|---|---|
| Switch config format | JSON ↔ YAML | Kubernetes, CI config | Re-check YAML implicit types such as yes / no after converting |
| Hand to non-developers | JSON → CSV / Excel | Arrays of same-shaped objects | Flatten nested objects first or columns get odd |
| Flatten nesting | JSON Flatten / Unflatten | Path keys like a.b.0.c | Use another delimiter if keys contain dots |
| Draft type definitions | JSON → TypeScript | Frontend API type drafts | Inferred from one sample; optional fields need manual edits |
| Gauge size | JSON Stats | Depth, key count, type mix, minified size | Describes the sample, not production averages |
Common pitfalls and the order to diagnose them
- Look at the first character. If it is <, you almost certainly have an HTML error page, not a JSON problem. Check the status code and the gateway.
- When the reported position is near the end of a line, the usual cause is a missing comma or an unclosed quote on the previous line. Look one line up.
- NaN and Infinity: the JSON5 fallback accepts them, but when output is written as standard JSON they become null. The numeric information is already lost, so fix it at the source.
- Windows paths such as C:\Users: strict JSON rejects the illegal escape, but the JSON5 fallback treats \U as a plain U and gives CUsers, while \b becomes a backspace character. Backslashes in paths must be written as \\.
- Large integers: integers beyond 2 to the power of 53 lose precision in JavaScript (12345678901234567890 displays as 12345678901234567000). Send IDs as strings.
- Duplicate keys: standard parsers do not complain and keep the last one. If you suspect overwritten data, search the raw text for repeated key names.
Combining tools by task: five common paths
The same tools run in a different order depending on the job. The table below turns the five most common tasks into fixed paths and states what to confirm at each step, so you do not skip later checks just because formatting appeared to succeed.
| Task | Suggested order | What to confirm at each step |
|---|---|---|
| Integrating a third-party API | Format → generate schema → validate schema | Are all fields present, do types match the vendor docs, are optional fields wrongly marked required |
| Investigating a config change | Repair → format → diff | Did changes land only on the expected paths, was any value quietly rewritten |
| Exporting data for operations colleagues | Format → flatten → JSON to CSV or Excel | Are column names sensible, how many columns did nested arrays turn into |
| Writing frontend API types | Format → JSON to TypeScript → manual edits | Should fields that are null or missing in the sample be optional |
| Assessing a very large response | JSON Stats → JSONPath to pull key fields | Is the maximum depth, the longest string or the minified size unusual |
Every sample-based inference (schema generation, type generation) shares one limit: situations absent from the sample are not covered. If a field happens to always have a value in your sample, the output treats it as required. So treat inferred results as drafts, test them with a second and third different sample, then revise by hand.
Four minimal conventions for a team
- Before pasting a JSON sample into a ticket or chat, format and redact it so others do not have to tidy it up.
- For every config file, state in its header or documentation whether the programs reading it support comments and trailing commas.
- Say in the API documentation whether array order is meaningful; only then does index-based comparison make sense.
- Agree that IDs, amounts and other precision-sensitive fields travel as strings, avoiding precision loss for large integers and decimals in JavaScript.
When not to use browser-based tools
- Very large files (tens of MB and up): browser memory and tree rendering become strained. A command-line tool such as jq is a better fit.
- Automated validation in CI: a web page cannot be invoked by a script. Put schema checks in your test code.
- Full JSON Schema specification support or $ref resolution: use a dedicated library such as Ajv.
- In-place editing that must keep comments: formatter and repair output is standard JSON and comments are dropped, so do not use it to overwrite your tsconfig.