jsonrepair
jsonrepair turns many common forms of almost-JSON into valid JSON text. It can quote bare keys, convert single and curly quotes, add commas and closing brackets, remove comments and trailing commas, unwrap Markdown fences or JSONP, convert Python and MongoDB literals, join newline-delimited objects into an array, and salvage truncated input. The regular API is a synchronous string-to-string function; Node also gets a Transform stream and the package includes a CLI. It repairs syntax, not the meaning or schema of the data.
One of the best small tools for recovering syntax from human- or model-produced JSON-like text, with a rare streaming implementation and no dependencies. Do not confuse a successful repair with trustworthy data: parse it, validate it, and reject it when strict input is the safer contract.
Use it if
- You receive JSON-like text copied from logs, JavaScript, Python, MongoDB shells, or Markdown and need a best-effort syntactic cleanup
- You need to turn newline-delimited JSON records into one valid JSON array without writing a custom parser
- You process a file too large for a single in-memory string and can use the Node streaming transform with an appropriate buffer
- You want one zero-dependency package that works through ESM, CommonJS, a Node stream, or a command-line pipeline
- You are enforcing a strict API or security boundary: the documented behavior deliberately accepts comments, single quotes, Python constants, JSONP wrappers, MongoDB constructors, code fences, and other text strict JSON should reject
- You need to know that the repaired data is correct: the API returns JSON text and does no schema, range, required-field, authorization, or business-rule validation
- You need browser streaming: jsonrepair/stream imports Node's Transform class, while the browser-compatible regular implementation takes the whole input string
- Your stream can contain a string, number, or whitespace run longer than your configured bufferSize: the README says the moving window then throws an Index out of range error
- You need lossless source editing or comment preservation: repair intentionally strips comments, Markdown fences, ellipses, and JSONP notation, concatenates split strings, and may turn malformed numbers into strings
Setup reality
npm install jsonrepair is the whole package setup: version 3.15.0 has no runtime dependencies, includes TypeScript declarations, and exposes separate ESM and CommonJS entries. Use the named jsonrepair export; the v3 changelog records the old default export as a breaking change. The regular call is synchronous and accepts only a string. It returns another string, not an object, so call JSON.parse yourself and then run schema validation if the result enters application logic. Unrepairable input throws JSONRepairError with a zero-based position. In a browser, the regular implementation keeps the document in memory; the README says it is intended for files up to 512 MB, but your actual memory ceiling may be lower because both input and generated output coexist. Node's jsonrepair/stream subpath exposes a Transform and is the right choice for large or unbounded input. Its default chunkSize and bufferSize are both 65536 bytes. chunkSize controls emitted chunks, while bufferSize is a moving window used for look-ahead and output rewrites. bufferSize must exceed the longest string, number, and whitespace run in the document; increasing it costs memory and can reduce performance, while an infinite buffer removes the window limit but can exhaust memory. The CLI reads a filename or stdin and writes to stdout unless --output is given. --overwrite modifies the source file, so keep it out of automated cleanup until you have backups and tests. Machine-generated or user-submitted text still needs size limits, time limits, JSON.parse, and schema validation after repair. Current versions matter: the changelog records a security fix in 3.13.2 for an XSS risk in regex repair, so do not copy an old lockfile version into a browser-facing path.
Patterns
Quote keys and convert single-quoted stringsrepair-json-like-text
import { jsonrepair } from 'jsonrepair';
const input = "{name: 'Ada', role: 'admin'}";
const repaired = jsonrepair(input);
console.log(repaired); // {"name": "Ada", "role": "admin"}The return value is JSON text. jsonrepair does not parse it into an object or check whether role is an allowed application value.
Repair, parse, then validate separatelyrepair-and-parse
import { jsonrepair } from 'jsonrepair';
const repaired = jsonrepair(rawText);
const value = JSON.parse(repaired);
if (!value || typeof value !== 'object' || typeof value.id !== 'string') {
throw new TypeError('Expected an object with a string id');
}Syntax repair and data validation are different steps. Use a schema validator for nested production payloads instead of growing manual checks.
Convert Python constants and trailing commasconvert-python-literals
const repaired = jsonrepair(
"{name: 'Ada', active: True, note: None,}",
);
console.log(repaired);
// {"name":"Ada", "active": true, "note": null}True, False, and None are mapped to JSON booleans and null. Other Python expressions are not evaluated.
Close a truncated object or arrayfinish-truncated-json
const repaired = jsonrepair('{"items":[1,2,3');
console.log(repaired); // {"items":[1,2,3]}Closing syntax can be inferred, but missing content cannot. Treat a repaired truncated response as partial data unless the schema proves otherwise.
Remove a fenced Markdown wrapperunwrap-markdown-json
const ticks = String.fromCharCode(96).repeat(3);
const response = `${ticks}json\n{answer: 42}\n${ticks}`;
const repaired = jsonrepair(response);
const data = JSON.parse(repaired);Fence repair was added during the v3 line and handles optional language labels such as json. Text outside the fenced JSON can still make the input unrepairable.
Turn newline-delimited objects into an arrayconvert-ndjson-array
const ndjson = [
'{"id":1,"name":"Ada"}',
'{"id":2,"name":"Linus"}',
].join('\n');
const rows = JSON.parse(jsonrepair(ndjson));
console.log(rows.length); // 2The result is one array string, so the regular API still holds the full converted document in memory. Use the stream for a large source.
Strip common MongoDB shell constructorsnormalize-mongodb-values
const input =
'{created: ISODate("2012-12-19T06:01:17.171Z"), count: NumberLong(2)}';
console.log(jsonrepair(input));
// {"created": "2012-12-19T06:01:17.171Z", "count": 2}The ISODate wrapper becomes a string, not a JavaScript Date. Convert and validate dates after JSON.parse if the application needs Date objects.
Report an unrepairable positionhandle-repair-errors
import { jsonrepair, JSONRepairError } from 'jsonrepair';
try {
return jsonrepair(input);
} catch (error) {
if (error instanceof JSONRepairError) {
console.error('Could not repair at offset', error.position);
}
throw error;
}position is a zero-based string offset. It is not a line and column pair, so calculate those separately when presenting an editor diagnostic.
Repair a file through a Node streamstream-large-file
import { createReadStream, createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream/promises';
import { jsonrepairTransform } from 'jsonrepair/stream';
await pipeline(
createReadStream('./broken.json'),
jsonrepairTransform(),
createWriteStream('./repaired.json'),
);Import from jsonrepair/stream, not the root. pipeline propagates read, transform, and write errors and closes the connected streams.
Increase the moving window for long tokenstune-stream-buffer
const repair = jsonrepairTransform({
bufferSize: 1024 * 1024,
chunkSize: 64 * 1024,
});
await pipeline(inputStream, repair, outputStream);bufferSize must exceed the longest string, number, or whitespace run. A larger window uses more memory and can reduce performance; chunkSize only controls emitted chunk size.
Use the CLI in a shell pipelinerepair-from-stdin
npm install --global jsonrepair@3.15.0
cat broken.json | jsonrepair > repaired.jsonThe CLI streams stdin to stdout. Check the command's exit status before replacing or consuming the generated file in automation.
Write a repaired file or replace the inputrepair-file-output
jsonrepair broken.json --output repaired.json
# Destructive: only after reviewing or backing up the source
jsonrepair broken.json --overwrite--output keeps the original and is the safer default. --overwrite replaces the input file, so a bad heuristic choice can destroy the evidence needed to repair it manually.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| dirty-json | npm | You want a permissive parser that returns a JavaScript value directly from messy JSON-like text |
| json5 | npm | You control the input format and want a documented relaxed JSON syntax rather than heuristic repair |
| jsonc-parser | npm | You need comments, trailing commas, parse errors, and edit operations for configuration files or an editor |
| ajv | npm | Your text is already valid JSON and the real requirement is JSON Schema validation |