LLM JSON repair
Language models are asked to return JSON constantly, and they constantly return JSON that almost parses — wrapped in a markdown fence, sprinkled with trailing commas, using single quotes, or cut off mid-object when the response hit a token limit. This tool applies the standard sequence of safe repairs and then validates the result with a real parser, so you get usable JSON instead of a stack trace.
How it works
The repair runs as an ordered pipeline. First it strips markdown fences and
any prose before the first { or [ and after the last matching bracket. Then
it normalizes smart quotes to straight quotes, converts single-quoted
strings and keys, quotes bare keys, and removes trailing commas before
closing brackets. Finally it scans for unbalanced braces, brackets, and an
unterminated string — the signature of a truncated response — and appends the
closing characters needed to make it parse. Every result is run through
JSON.parse to confirm validity before it is shown.
Notes and limits
- Repairs are syntactic. Quotes, commas, and brackets get fixed; your values are not interpreted or altered.
- Truncation recovery is best-effort. Closing an interrupted structure can drop a half-written final value — the tool tells you when it closed brackets so you can spot-check.
- Review when warned. If the tool reports it normalized quotes or balanced brackets, glance at the output around the end of the data.
- Everything is local. Nothing is uploaded; paste sensitive payloads freely.
Why LLMs produce malformed JSON in the first place
Understanding the failure modes helps you avoid them in your prompts and handle them more gracefully in code.
Markdown fences. Many models are trained on documentation and code examples that always wrap JSON in triple-backtick fences. When instructed to “return JSON,” they default to what they learned — wrapping the output in ```json ... ```. The fix in your prompt is “return raw JSON with no markdown formatting,” but the repair tool handles it regardless.
Trailing commas. JSON forbids trailing commas after the last property or array element. JavaScript allows them, and many configuration formats (JSON5, JSONC) allow them. Models trained on JavaScript and config file corpora often produce them.
Single quotes. JavaScript object literals use single quotes freely; JSON requires double quotes. A model prompted to produce “a JavaScript object” rather than “JSON” will often use single quotes throughout.
Token-limit truncation. If the model hits its context window or token output limit mid-response, the JSON stops wherever the model was cut off. The resulting fragment has unbalanced braces, brackets, or an unterminated string. This is the repair that requires the most care — closing an interrupted structure can drop the last partial value.
Smart quotes. Word processors and some locales replace straight quotes (") with typographic curly quotes (" and "). If a user pastes text from a document into a prompt, and the model echoes it back, the resulting JSON uses curly quotes that a parser rejects immediately.
A real repair walkthrough
Suppose a model returns:
Here's the data you asked for:
```json
{
'name': 'O\'Brien',
"scores": [95, 87, 92,],
"active": true
}
The repair pipeline does the following in order:
1. **Strip the markdown fence and prose.** The `Here's the data...` prefix and the ` ```json ... ``` ` wrapper are removed, leaving just the object.
2. **Normalise single quotes.** `'name'` and `'O\'Brien'` are converted to `"name"` and `"O'Brien"`.
3. **Remove the trailing comma.** The comma after `92` in the scores array is deleted.
4. The result passes `JSON.parse` and is pretty-printed as valid JSON.
The name apostrophe is preserved correctly because the repair converts the string boundary quotes while leaving the content intact.