Skip to content
jsonbeautifiers
English

JSON Repair

Fix trailing commas, single quotes, comments and Python literals, with a list of every change.

Filter with JSONPath

RFC 9535 syntax. The result replaces the pane you opened this from.

 

Nothing you paste leaves your browser. The connect-src allowlist makes that a browser guarantee rather than a promise. Check it yourself

Repair takes something that is nearly JSON and makes it valid. Trailing commas, single quotes, unquoted keys, comments, Python literals, typographic quotes, unclosed brackets, invisible whitespace.

The output is not the interesting part. The changelog is. A repair tool that silently rewrites your payload is worse than no repair tool at all, because you cannot tell what it decided on your behalf. Every change is listed with its line and column, and the ones that involved a judgement call are listed separately from the ones that did not.

What it fixes without needing to guess

These have exactly one sensible interpretation, so they are applied without comment beyond the changelog entry.

Trailing and doubled commas
Removed. Legal in JavaScript and JSON5, never in JSON.
Single-quoted strings
Converted to double quotes, with the contents re-escaped so an apostrophe inside does not break the result.
Unquoted keys
Quoted. JavaScript allows bare identifiers as keys; JSON does not.
Comments
Removed, both // and /* */ forms.
Python literals
True, False and None become true, false and null.
Typographic quotes
The curly quotes autocorrect produces become straight ASCII quotes.
Invalid whitespace
No-break spaces and their relatives become ordinary spaces; zero-width characters are removed.
A byte order mark
Stripped from the start of the document.
Missing commas and colons
Inserted where the grammar makes the intent unambiguous.
Raw control characters in strings
Escaped, so a literal newline becomes \n.

What it flags as a judgement call

These change meaning, and no default is right for everyone. They are applied, listed separately, and configurable.

Leading zeros
The default is to quote the value: 02134 becomes the string "02134". Leading zeros in real data are nearly always a zip code, an account number or a SKU, where dropping them destroys the value silently. If it genuinely is a number, switch the policy to strip and it becomes 2134.
NaN, Infinity and undefined
Converted to null, which is what most encoders substitute. Python emits NaN and Infinity from json.dumps by default; pass allow_nan=False to catch it where it starts.
Bare words used as values
Quoted as strings. {"status": pending} becomes {"status": "pending"}, which is usually right and occasionally not.
Unclosed brackets
Closed at the end of the document. If the file was truncated rather than mistyped, this produces valid JSON that is missing data, so the change is always listed.
NDJSON
Several complete values one per line are wrapped in an array by default. You can also keep only the first record, or leave the input alone.

What it will not do

It will not invent structure. If the input is not close to JSON, the repair fails and says which errors it could not resolve, rather than producing something that parses but means nothing.

It also runs a bounded number of passes. Each pass can uncover a problem the previous one was hiding, but the process converges rather than looping.

How to do this in code

Doing this in code, and the honest caveat that lenient parsing at the consumer usually means something upstream is producing bad JSON that will keep producing it.

py Python, dict repr

ast.literal_eval only evaluates literal structures, so unlike eval it cannot run arbitrary code.

import ast, json

# A Python dict printed with str() or print() is not JSON.
text = "{'name': 'Priya', 'active': True}"

value = ast.literal_eval(text)   # safe: literals only, no eval
clean = json.dumps(value)        # '{"name": "Priya", "active": true}'
js JavaScript, JSON5

JSON5 is a superset with a real specification, which makes it a better target than an ad-hoc lenient parser.

import JSON5 from 'json5';

// Accepts comments, trailing commas, unquoted keys, single
// quotes, hex numbers and more.
const value = JSON5.parse(text);
const strict = JSON.stringify(value);
ts TypeScript, JSONC
import { parse } from 'jsonc-parser';

// What VS Code uses for its own settings files: comments and
// trailing commas, and nothing else.
const errors: ParseError[] = [];
const value = parse(text, errors);
sh Shell
# Strip comments and trailing commas with jq's relaxed reader
jq --args . <<< "$text"

# Or normalise a JSON5 file
npx json5 -c config.json5 > config.json

Questions

Will repair ever change my data?
Only in the ways listed under judgement calls, and every one of those appears in the changelog with its line and column. Safe repairs affect syntax only. If you disagree with a judgement call, change the setting and run it again.
Why does 02134 become a string rather than the number 2134?
Because quoting is lossless and stripping is not. Leading zeros in real data are almost always significant, and a converter that silently turned a zip code into a smaller number would be doing exactly the kind of quiet damage this site exists to avoid. The strip option is one click away.
It says it could not repair my document. Now what?
Run it through the validator. Repair only handles problems with an unambiguous fix; a document with genuinely unrecoverable structure needs a human to decide what was intended.