viewer.csslab.dev

JSON, JSONL, and NDJSON are not the same file

Because the file is probably JSONL, not JSON. A .json file contains exactly one document — one object or one array — and a parser reads it whole. A .jsonl or .ndjson file contains one complete JSON document per line with no commas and no enclosing brackets, so a normal parser reads the first line, finds more content after the document ends, and reports a syntax error. The fix is to parse line by line, not to repair the file.

What each format actually is

JSON, as defined by RFC 8259, is a single value. A file holding an array of ten thousand records is one array — the parser must read the closing bracket before it can hand you anything, which means the whole document has to be in memory at once.

JSON Lines (.jsonl) and Newline-Delimited JSON (.ndjson) are the same idea under two names: each line is an independent JSON document, UTF-8 encoded, separated by \n. There is no top-level array and no commas between records. Both names describe the same layout, and tools generally accept either extension.

Why the streaming forms exist

A process can emit one line and move on, and a reader can handle one line and discard it. Neither side needs the whole dataset in memory, which is what makes these formats the default for logs, exports, and anything measured in gigabytes.

They also fail better. If a JSON array is truncated halfway through, the entire document is invalid and you get nothing. If a JSONL file is truncated, every complete line before the cut is still readable — you lose the tail, not the file.

Appending is trivial for the same reason: writing another record means writing another line. Appending to a JSON array means rewriting the closing bracket, which is why log files are never JSON arrays.

Telling them apart, and converting

Look at the first character. If the file starts with [ and ends with ], it is one JSON array. If it starts with { and there is another { at the start of a later line, it is JSONL. A file that starts with { and has commas at the end of lines is a pretty-printed single document.

To read JSONL, split on newlines and parse each line separately. To turn JSONL into JSON, wrap the parsed lines in an array. To go the other way, write each element of the array on its own line with no separators. Both conversions are a few lines of code and neither needs a library.

One caveat when converting to JSONL: a record containing a literal newline must have it escaped as \\n inside the string, because in JSONL the newline is the record separator. A pretty-printed JSON object cannot simply be pasted onto one line.

Tools for this

Specifications this follows

Updated 2026-09-05