Home › Guides › NDJSON vs JSONL — and how to salvage a file with broken lines

NDJSON vs JSONL — and how to salvage a file with broken lines

Direct answer: there is no format difference to pick between: NDJSON and JSONL both mean one complete JSON value per line. NDJSON is the older spec name (.ndjson); JSONL / JSON Lines (.jsonl) is what logging and ML tooling settled on. The interesting problem is not the name — it is the broken lines every real file accumulates, and those are salvageable line by line with the tool below.

Salvage your line-delimited file

Each line is handled independently: valid lines pass through untouched, broken lines are repaired, hopeless lines are quarantined with their original line numbers. Processed locally in your browser — nothing is uploaded.

One idea, two names

A line-delimited JSON file is a stream of independent documents, one per line:

{"id":1,"event":"login"}
{"id":2,"event":"click"}
{"id":3,"event":"logout"}

NDJSON ("Newline Delimited JSON", ndjson.org) specified this first and allows any JSON value per line. JSON Lines (jsonlines.org) recommends objects per line and the .jsonl extension you will see across ML datasets and observability exports. In the wild the extensions are used interchangeably and every reader accepts both — if a tool claims to support one and not the other, it is describing its community, not a grammar difference.

The rules that make it work

How files break — and what salvage does about it

DamageSalvage outcome
A line with single quotes / trailing comma / Python literalsRepaired per line, with the rules applied shown in the line table
A plain-text log line among JSON linesQuarantined with its original line number and the reason
Last line truncated (writer killed mid-write)Repaired by closure if the record is completable, otherwise quarantined — never silently kept half-parsed
A whole pretty-printed document pasted insteadDetected — you are pointed to JSON Repair with a one-click transfer
Empty linesSkipped and counted separately — they never shift the line numbers of real records

The discipline that matters: salvage distinguishes repaired from quarantined and keeps original line numbers stable, so when the producer asks "which records were bad?", the quarantine file is the answer — the original text, the line number, and the reason, rather than a shrug and a smaller file.

Frequently asked questions

NDJSON vs JSONL — is there any real difference?

In the data itself, no: both are one complete JSON value per line, UTF-8, lines separated by \n. NDJSON (ndjson.org, .ndjson) is the older specification; JSONL / JSON Lines (jsonlines.org, .jsonl) is the format most logging, streaming and ML tooling standardised on. Tools that read one read the other; the names signal community, not grammar.

Why use line-delimited JSON at all?

Streaming and damage control. A consumer can process record 1 without waiting for record 10,000; appending is trivial; and a corrupt line costs one record instead of the whole document — which is exactly the property the salvage tool on this page exploits.

What breaks NDJSON/JSONL files in practice?

A pretty-printed record sneaked into the stream (one record spanning lines), a log line that is not JSON at all, a writer killed mid-line (the last line is truncated), non-JSON values from a JS/Python producer on some lines, and CRLF endings from Windows tooling confusing naive splitters.