Repair broken JSON

Paste the JSON that will not open: a chat answer with the code block around it, a config file with comments, a Python print with True and None, a log with one object per line. Out comes valid JSON, with the list of every fix and of the spot where it was made. If the text was cut off, the page closes it and tells you so plainly. Nothing leaves your browser.

The text never leaves your browser: the repair happens here, on your device, and it is not sent to any server or saved anywhere.

Where broken JSON comes from

Hardly ever from a program: programs write correct JSON. It comes from a chat answer, which puts it inside a code block with a sentence before and one after, and now and then adds a comment to explain a field to you. It comes from a config file written by hand, where the comma after the last item and the comments are normal because the editor accepts them. It comes from a Python print, which writes single quotes and True, False and None. And it comes from a log, where every line is an object of its own, often with the time or the service name in front, and the whole file is not one JSON but many in a row.

In all these cases the program that has to read it stops at the first error and says something like «Unexpected token». Fixing one error by hand is fine; forty scattered across two thousand lines, running it again every time, is not. Here you paste the lot, even with the chat sentence around it.

Every fix is listed, with the line and the column

A repair tool that hands back valid JSON without saying what it touched is a black box: the file opens now, but you do not know whether the data that was in it is still there. Here every change has a line in the list, with the exact spot in the text you pasted: line 14, column 3, trailing comma removed.

The fixes are not all alike, and the list says so. Removing a comment, an extra comma or the markdown block does not change any data. Others are decisions, and they are marked as such: NaN and Infinity become null because JSON has no way to write them, and JSON.stringify does the same; a number written 007 becomes 7, and if it was a postcode those zeros were data; several objects in a row become a list, because a JSON file holds one value only.

The dangerous case: JSON cut off halfway

It happens all the time with chats: the answer is long, the model reaches its limit and stops in the middle of a list, often in the middle of a word. The text you have is not wrong, it is incomplete, and those are two different problems. Putting back the missing closings makes it valid, and that is done here; but JSON closed that way holds less data than the original, and a program reading it has no way of noticing.

That is why in that case the page does not just say «valid». It says the text is cut off, at which line and column it ends, inside what (a text, a number, a list still open), which closings it added and which piece it removed. And the rule is strict: to close it, what gets added is only quotes and brackets. Whatever was left halfway and cannot be closed without making something up is removed: the name of a key broken in two, because a cut key is another key; a «tru» that could only be true; a comma left hanging.

An example with numbers: a list of 50 products that stops inside the name of the thirty-eighth comes out as a list of 38 items, the last one with its name cut short, and the page flags it as a cut-off value. The other twelve are not there and nobody can rebuild them: you have to ask the chat to continue, or to answer in several pieces. The file you download in that case has the word incomplete in its name, so you do not mistake it for a good one.

Quotes: straight, curly and single

The curly quotes arrive when the JSON goes through Word, an email or a phone keyboard, which «prettifies» them as you type. Where they act as delimiters they become straight. Inside a text, instead, they are content and stay as they are: a sentence with typographic quotes must not come out different from how it went in. The same goes for // and # inside a web address, which are not comments, and for the word True inside a sentence.

The single quotes are the ones of Python and JavaScript. Here the apostrophe inside the text is recognised too, the one in don't: a single quote closes the string only if what follows can follow a value, that is a comma, a colon, a bracket or the end of the line. The straight quotes inside a text without the backslash that protects them, on the other hand, are not guessed: there the page stops and says where.

The backslashes follow the same idea. If a text holds even one that JSON does not know, as in C:\Users\anna\new, that text was written by a person, and all its backslashes stay real backslashes: even the one in front of new, which JSON would read as a line break.

What stays the same, and how it is checked

JSON that is already valid comes out with the same value, only formatted. It sounds obvious and it is not: many tools go through JSON.parse, which turns an identifier like 12345678901234567890 into 12345678901234567000, and a rounded identifier is another identifier. Here numbers stay the text they were, 1.50 included. The order of the keys stays too, and repeated keys both stay, flagged: nearly every program keeps only the last one, and choosing which to throw away is up to you.

The test for this tool is not a handful of examples picked by hand. A program generates hundreds of valid JSON documents, breaks them in known ways noting where it put each fault, and demands that the repaired value is exactly the starting one, read back by the Python standard library, and that the list names precisely those faults, at those spots. On cut-off texts it demands the longest piece that can be kept: nothing complete thrown away, and the closings that were missing, not one more.

What it does not do

It does not guess. A word without quotes where a value is due, like status: active; a date or a version without quotes, like 2024-01-15 or 3.5.1, which are not numbers; a bracket closed with the wrong one, or one too many with more data after it; two commas in a row. In these cases there is more than one possible repair, and picking one at random would mean handing you made-up data that looks real. The page stops, gives the line and the column and shows you the spot with an arrow. And it does not throw data away quietly: what it removes before and after the JSON is only the chat sentence.

It does not check that the data is right. Repaired JSON is JSON that can be read, not JSON that tells the truth: if the chat got a price wrong, the price stays wrong. And it does not know the schema your program expects.

It does not do the other jobs. To indent, compact or sort the keys of JSON that is already valid there is JSON formatter and validator. To turn it into a table to open in Excel there is JSON to CSV. If the file is YAML, the format with indentation and no brackets, there is YAML to JSON. And if from the same chat answer you also need the other code blocks, there is Extract code from AI.