JSON Repair — Java source
Fix broken JSON - trailing commas, single quotes, unquoted keys, comments, Python constants, BOM and truncated documents - and get clean pretty-printed JSON plus a list of every repair applied. Runs entirely in your browser.
This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.
// JSON repair pipeline — Java (17+) port of the json-repair tool: excerpt of
// the 7-pass pipeline in typescript.ts / go.go (quote, Python-constant,
// trailing comma, truncation repair passes).
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class JsonRepair {
static final Pattern STRINGS = Pattern.compile("\"(?:[^\"\\\\]|\\\\.)*\"");
static final Pattern PY = Pattern.compile("\\b(True|False|None)\\b");
static final Map<String, String> PY_MAP = Map.of("True", "true", "False", "false", "None", "null");
static final Pattern TRAILING = Pattern.compile(",(\\s*[}\\]])");
// Single-quoted strings -> double-quoted: escape inner double quotes,
// collapse \' to ', keep every other escape; double-quoted copy verbatim.
static String singleToDoubleQuotes(String text) {
StringBuilder out = new StringBuilder();
int i = 0;
while (i < text.length()) {
char c = text.charAt(i);
if (c != '\'') { out.append(c); i++; continue; }
out.append('"');
i++;
while (i < text.length() && text.charAt(i) != '\'') {
char d = text.charAt(i);
if (d == '\\' && i + 1 < text.length()) {
out.append(text.charAt(i + 1) == '\'' ? '\'' : "" + d + text.charAt(i + 1));
i += 2;
} else if (d == '"') { out.append("\\\""); i++; }
else { out.append(d); i++; }
}
out.append('"');
i++;
}
return out.toString();
}
static String outsideStrings(String text, Function<String, String> map) { // outside "..." only
Matcher m = STRINGS.matcher(text);
StringBuilder out = new StringBuilder();
int last = 0;
while (m.find()) {
out.append(map.apply(text.substring(last, m.start()))).append(m.group());
last = m.end();
}
return out.append(map.apply(text.substring(last))).toString();
}
static String fixPythonConstants(String t) { return outsideStrings(t, s -> PY.matcher(s).replaceAll(m -> PY_MAP.get(m.group()))); }
// Commas followed only by whitespace and a closing } or ] — dropped.
static String stripTrailingCommas(String t) { return outsideStrings(t, s -> TRAILING.matcher(s).replaceAll(m -> m.group(1))); }
// Recover truncated JSON: close an unterminated string, drop a dangling
// comma, give a dangling colon a null value, then close open brackets.
static String closeTruncated(String text) {
ArrayDeque<Character> stack = new ArrayDeque<>();
boolean inString = false;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (inString) {
if (c == '\\') i++; // skip the escaped character
else if (c == '"') inString = false;
} else if (c == '"') inString = true;
else if (c == '{' || c == '[') stack.addLast(c);
else if (c == '}' || c == ']') { if (!stack.isEmpty()) stack.removeLast(); }
}
String out = (inString ? text + "\"" : text).replaceAll("[\\s,]+$", "");
if (out.endsWith(":")) out += " null";
StringBuilder closers = new StringBuilder();
while (!stack.isEmpty()) closers.append(stack.removeLast() == '{' ? '}' : ']');
return out + closers;
}
// The canonical repair() also reports which passes fired and pretty-prints.
static String repair(String text) {
return List.<Function<String, String>>of(JsonRepair::singleToDoubleQuotes,
JsonRepair::fixPythonConstants, JsonRepair::stripTrailingCommas,
JsonRepair::closeTruncated)
.stream().reduce(text, (work, pass) -> pass.apply(work), (a, b) -> a);
}
public static void main(String[] args) {
// {"name": "Ada", admin: true, tags: ["x", "y"]}
System.out.println(repair("{'name': 'Ada', admin: True, tags: ['x', 'y',],"));
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →