JSONL to JSON: Convert JSON Lines (NDJSON) to a JSON Array and Back
How JSON Lines (NDJSON) works, why one object per line wins for logs, streaming, and LLM datasets, and how to wrap JSONL into a JSON array or unwrap it.
JSONL to JSON: Convert JSON Lines (NDJSON) to a JSON Array and Back
Two files can hold the exact same records and still refuse to talk to each other. One is a .json file with a tidy array inside square brackets. The other is a .jsonl file where every line is its own little object. A notebook wants the array. A fine-tuning uploader wants the lines. A log shipper wants the lines too. And the moment you hand the wrong one to the wrong tool, you get a parse error that tells you almost nothing.
This post is about that gap and how to cross it cleanly: what JSON Lines (also called NDJSON) actually is, why so many serious data pipelines prefer it, and how converting between JSONL and a JSON array is really just adding or removing a wrapper and some commas.
What JSON Lines (NDJSON) Actually Is
Here is the one concrete fact that makes everything else click: JSONL is one complete JSON value per line, with no enclosing array and no commas between lines. Each line stands entirely on its own. A reader can take a line, parse it, do something with it, throw it away, and move to the next line without ever holding the whole file in memory.
A regular JSON file is the opposite. It holds a single value, and for record data that value is almost always an array like [{"id":1},{"id":2}]. The whole thing is one expression. To read the second object, a parser has to consume the opening bracket, the first object, the comma, and only then arrive at the second. You parse all of it or none of it.
So the difference between the two formats is mechanical, not philosophical. To turn JSONL into a JSON array, you wrap the lines in [ and ] and join them with commas. To go back, you strip the brackets and replace the commas with newlines, writing one compact object per line. That is the entire transformation, and it is exactly what the JSONL to JSON Converter does in your browser tab.
Why JSONL Wins for Logs, Streaming, and LLM Datasets
If the array format is so familiar, why does half the data world ship JSONL? Because of how files grow and how they are read.
An application log never stops. A service appends one event per line as things happen, and {"event":"login","user":42} lands at the end of the file the instant it occurs. You cannot do that with a JSON array. To append to an array you would have to find the closing bracket, back up over it, add a comma and the new element, and rewrite the tail. With JSONL you just >> a line onto the end. Append is free.
Streaming is the second reason. A Kafka consumer, a Spark job, or a tail -f on a log sink reads one record, processes it, and releases the memory before reading the next. A 40 GB NDJSON export from BigQuery streams through a process that never needs more than one line of RAM. Feed that same job a 40 GB JSON array and it has to buffer the entire thing before the parser will hand you the first object.
The third reason is the one that pushed JSONL into everyday developer life: LLM datasets. OpenAI-style fine-tuning files are JSONL, where each line is one training example. The format is a natural fit because training sets grow by appending examples, and the trainer reads them example by example. If you have been prototyping with a JSON array of examples, the upload step is going to ask you to flatten it into one object per line first.
A Worked Example: Three Lines Into an Array
Say you pulled three events out of a log:
{"id":1,"event":"signup"}
{"id":2,"event":"login"}
{"id":3,"event":"purchase"}
That is valid JSONL: three complete objects, three lines, no commas, no brackets. But your charting widget calls JSON.parse on the whole blob and expects an array. Paste those lines into the converter with the direction set to JSONL to JSON array, and you get:
[
{ "id": 1, "event": "signup" },
{ "id": 2, "event": "login" },
{ "id": 3, "event": "purchase" }
]
One parseable value, every record in order, ready for array.map and filter. Pick compact output for the smallest payload, or 2 or 4 spaces when a human is going to read it. Flip the direction and paste an array, and each element drops back onto its own compact line, no indentation and no trailing comma, which is precisely what a streaming reader or a fine-tuning uploader expects.
The Errors JSONL Hides, and How to Catch Them
I run a lot of NDJSON through loaders, and the failure mode that used to cost me the most time was a single broken line in a giant file. A BigQuery load fails with "invalid JSON" and no location. A Spark job dies the same way. The file looks like one undifferentiated wall of text, so spotting the stray comma or the smart quote that snuck in from a copy-paste is genuinely hard by eye. I once spent twenty minutes bisecting a 9,000-line export by hand before I started doing the obvious thing: let a line-by-line parser tell me the row number.
That is the quiet superpower of converting JSONL: a good converter parses one line at a time and stops at the first failure with the line number and the parser's own message, something like line 7: Unexpected token } in JSON. You jump straight to that row in your editor, fix it, and re-run the load. No bisection, no guessing.
A few mistakes cause most of these errors. Pasting a full JSON array while the direction is still set to JSONL to JSON array fails immediately, because the outer brackets and inter-element commas are not legal on a single line. Hand-building JSONL by copying array elements is another classic: people leave the trailing commas in, and a line ending in a comma is not valid JSON on its own. Every line has to be a complete value with nothing after it.
When You Need a Different Tool
Converting between JSONL and an array changes the shape of the data. If you only want your JSONL to look prettier while staying JSONL, that is a different job, and the JSON Lines formatter re-indents each line in place without collapsing the file into one array. And once you have a clean JSON array, a general JSON formatter is the right place to validate, sort keys, and pretty-print the result before you commit it.
The rule of thumb is simple. Reach for the converter when a tool on the far side speaks the other dialect: an array consumer fed a stream, or a streaming consumer handed an array. Reach for a formatter when the format is already correct and you just want it readable. Keep those two intentions separate and the parse errors mostly stop showing up.
JSONL is not a fancier JSON. It is JSON with the wrapper removed so the file can stream and grow. Once that clicks, converting in either direction stops feeling like magic and starts feeling like what it is: adding brackets and commas, or taking them away.
Made by Toolora · Updated 2026-06-13