What is NDJSON?
NDJSON is JSON with one complete value on each line and no array around it. That one change is what makes a file streamable — and what breaks it if you pretty-print it.
Last reviewed
The format in one line
NDJSON — newline-delimited JSON — is a text file in which every line is one complete, independent JSON value. There is no enclosing array, no comma between records, and no trailing bracket. A file of three records is three lines.
You will see the same layout called JSON Lines, and the file extension is usually .jsonl or .ndjson. The names come from two separate specifications written around the same time; in practice they describe an identical file, and any tool that reads one reads the other. The only meaningful difference is that the NDJSON spec is explicit that the separator is a line feed rather than a carriage-return pair.
{"id":101,"name":"Ha-eun","role":"engineer"}
{"id":102,"name":"Marco","role":"analyst"}
{"id":103,"name":"Priya","role":"engineer"}Why the array had to go
A JSON array is a single value, and a parser cannot hand you the first element until it has read to the closing bracket — because until then it cannot know the document is well-formed. For a 40 GB export that means holding 40 GB in memory before doing any work at all.
Removing the array removes that constraint. Each line stands alone, so a consumer reads a line, parses it, processes it and discards it. Memory use is bounded by the largest single record rather than by the size of the file, which is why this is the format used wherever data arrives in bulk.
- BigQuery and Redshift load newline-delimited JSON, not JSON arrays.
- The Elasticsearch bulk API takes one action and one document per line.
- OpenAI and Anthropic fine-tuning datasets are .jsonl files.
- Structured application logs are almost always one JSON object per line.
- Kafka, Fluentd and most log shippers emit a record per line by default.
The mistake that breaks a file
In NDJSON the line break is the record separator. That makes indentation not a matter of taste but a structural property of the file — a record pretty-printed across eight lines is not one nicely formatted record, it is eight broken ones.
This is the single most common way a hand-edited NDJSON file stops loading. If you have opened one in an editor that reformats on save, the file is very likely no longer valid, and the error the loader reports will point at line two rather than at the formatting that caused it.
{"id":101,"tags":["a","b"]}{
"id": 101,
"tags": ["a", "b"]
}What NDJSON does not give you
The format is deliberately minimal, and it is worth being clear about what it leaves out. There is no header, so nothing declares what fields a record should have — records in the same file can have completely different shapes and the file is still valid.
There is also no document-level structure. You cannot express metadata about the collection, a total count, or a pagination cursor, because there is nowhere to put them. Producers that need those things usually emit a separate manifest file alongside the data.
- No schema and no header row — validate records individually if you need guarantees.
- No place for collection-level metadata such as counts or cursors.
- No comments, exactly as in ordinary JSON.
- Order is preserved only because the file is read top to bottom; nothing enforces it.
Converting between the two
Going from an array to NDJSON means minifying each element onto its own line; going the other way means parsing each line and collecting the results. Both directions are lossless, so a round trip returns exactly what you started with.
When a conversion fails, the number that matters is the source line. A single truncated record in a 50,000-line export is entirely normal, and knowing it is line 31,402 is the difference between a one-minute fix and an afternoon. Convert2JSON reports the source line number rather than the index of the record it was building.
Keep reading
- What is JSON? — JSON is a text format for structured data. It has six value types, one page of grammar, and a handful of rules that trip people up constantly.
- How to handle large JSON files — The limit is rarely the file size. It is what loading it into memory as objects, and rendering it as DOM nodes, actually costs.
- JSON vs CSV — CSV holds rows of text. JSON holds a typed tree. Every conversion between them either flattens something or invents something.