NDJSON to JSON
Turn line-delimited records into one array
NDJSON Input
JSON Output
When the thing downstream wants an array
NDJSON exists because appending a line to a file is cheap and rewriting an array is not. That is the right trade for anything producing records continuously — logs, exports, streams. It is the wrong shape the moment you want to hand the data to something that expects a single JSON document: a browser fetch, a request body, a fixture file, a tool that calls JSON.parse once and expects to be finished.
This wraps the lines in [ ], puts commas between them, and gives you an array. That is genuinely most of it — the interesting part is what happens when the file is not perfect.
A line that will not parse is named by its line number and skipped, rather than taking the file down with it. The alternative, which is what a one-line implementation does, is to fail the whole conversion because one record out of forty thousand was truncated by a killed export. The count of what was skipped is shown with the output, so you are converting a known-incomplete file rather than an apparently-complete one.
Long integers keep their digits. These files carry account numbers and event IDs that are longer than a JavaScript number can hold exactly, and a naive round trip rounds them at the sixteenth digit with no error at all. Nothing is uploaded.
Converting a file
- Paste the NDJSON or upload the file – One JSON value per line. Blank lines are ignored, including the trailing newline every file ends with.
- Choose how the output is laid out – Two or four spaces to read it, or minified when it is going into a request body or a file where the whitespace is only cost.
- Check the skipped-line note – If any line failed, it is listed by number. Those records are not in the array — worth knowing before you treat the output as the complete set.
- Take it on – JSON Formatter to validate it independently, JSON to Table to read it, or JSON to CSV for a spreadsheet.
If you only need to look at the data, you probably do not need this page at all — NDJSON to Table reads the file directly and shows you which lines failed. Converting to an array is worth doing when something else is going to consume the result, and that distinction matters for large files: an array has to be held in memory all at once, which is the exact constraint NDJSON was designed to avoid.
Four lines, one of them truncated
The third line was cut off mid-write, which is what a killed export looks like. The array holds the three records that survived, and the count of what did not is reported rather than quietly absorbed.
{"eventId":9007199254740993,"type":"attach"}
{"eventId":9007199254740994,"type":"detach"}
{"eventId":9007199254740995,"typ
{"eventId":9007199254740996,"type":"handover"}
# line 3 was cut off mid-write[
{
"eventId": 9007199254740993,
"type": "attach"
},
…
]
# 3 records. line 3 named, not fatal.
# the ids are past 2^53 and exact.What people use it for
Feeding an API or a test fixture
Request bodies, mock data and configuration files all want a single JSON document. An export that arrived as NDJSON has to be wrapped before it can be posted anywhere or committed as a fixture.
Getting an export into a tool that only reads JSON
Plenty of viewers, diff tools and schema validators call JSON.parse once and stop. They are not wrong — they were built for documents rather than streams — but it does mean converting first.
Salvaging what is left of a truncated export
A job died partway through and left a file ending mid-record. Converting here gives you every complete record plus an explicit count of what was lost, which is a much better position than a parse error or, worse, a silently short array.
Counting the records in a file
A minor use that comes up constantly. The chip beside the output is the number of records that parsed, which is the answer to "did the export actually contain everything" without opening a terminal.
What it handles
- A bad line does not fail the file. It is named by line number and skipped, and the rest converts.
- Long integers stay exact. A 19-digit identifier keeps every digit instead of being rounded to a JavaScript number.
- Two, four or no indentation, depending on whether a person or a program is reading the result.
- A pasted JSON array is recognised and explained rather than producing a parse error about line 1.
- Nothing is uploaded. Log exports stay in this tab.
Questions that come up
Why not just add brackets and commas myself?
For a small clean file, do — it is a two-minute edit. It stops being that when the file is large, when any line is malformed, or when the records contain identifiers longer than fifteen digits. Those three are the reason this page exists rather than a sed command.
What is NDJSON, exactly?
One complete JSON value per line, newline separated, with no enclosing array and no commas between records. It goes by JSON Lines and .jsonl as well — jsonlines.org and the ndjson spec describe the same convention. It is what you get from jq -c, from most log shippers, and from bulk export APIs.
My long IDs came back wrong somewhere else. Will they here?
No. A JavaScript number is an IEEE-754 double and exact only to about 15 digits, so JSON.parse turns 8901240544102066246 into 8901240544102066000 without complaint. The digits are carried through as text here and written back as a bare JSON number. RFC 8259 puts no limit on numeric precision — the limit belongs to the parser, not the format.
Should I convert a very large file?
Think about what happens next. An array must be held in memory in one piece, which is the constraint NDJSON was designed to sidestep — a million-record export is far happier being processed a line at a time. For reading rather than passing on, NDJSON to Table avoids the conversion entirely.
Can I go back?
JSON to NDJSON takes an array and writes one record per line, which is what a bulk-load endpoint wants.
Related tools
Worth reading
- JSON Lines – The convention, its rules, and why each line has to be self-contained
- The jq manual – jq -c is how most NDJSON gets produced from an existing array