JSONL to JSON Converter

Paste your lines or drop a .jsonl file and get one JSON array back. Every record keeps the shape it had, nesting and all, and if a line is broken the message tells you which one.

Need to filter records or drop fields on the way? Open the app

Why the next tool wants an array

Nobody sets out to convert JSONL. You have a file of lines because something wrote it that way, and then you hit a piece of software that will not take it. Usually one of these:

  • A parser with one entry point. json.load in Python, JSON.parse in a browser, a Go struct decoder. Each expects one document. Feed it the second line and it stops at the first character it did not expect.
  • A viewer or a diff tool. Comparing yesterday's eval output with today's is far easier when both sides are arrays a JSON diff can walk, instead of two piles of lines that shifted by one.
  • A request body. Batch endpoints take an array. Pasting sixty lines into a body and hoping is not a plan.
  • A repository snapshot. A fixture checked into git reviews better as an indented array. A reviewer can see what changed inside record fourteen instead of a rewritten line.
  • Somebody who is not going to install jq. A colleague who wants to read the file needs it in a shape their editor will fold and colour.

Every one of those wants the same thing: brackets around the outside, commas in between, records untouched. That is all this page does.

Worked example: three lines with a nested object

Three product events. Each has a user object inside it, which is where most converters start doing damage. This is also the file behind the "Try an example" button under the drop zone, so you can run it without finding anything of your own.

{"id":1,"event":"signup","user":{"name":"Ada Lovelace","plan":"pro"},"at":"2024-11-03T09:12:00Z"}
{"id":2,"event":"login","user":{"name":"Grace Hopper","plan":"free"},"at":"2024-11-03T09:14:22Z"}
{"id":3,"event":"upgrade","user":{"name":"Alan Turing","plan":"pro"},"at":"2024-11-03T10:01:47Z"}

With the controls where they start, JSON array and Pretty, the result is:

[
  {
    "id": 1,
    "event": "signup",
    "user": {
      "name": "Ada Lovelace",
      "plan": "pro"
    },
    "at": "2024-11-03T09:12:00Z"
  },
  {
    "id": 2,
    "event": "login",
    "user": {
      "name": "Grace Hopper",
      "plan": "free"
    },
    "at": "2024-11-03T09:14:22Z"
  },
  {
    "id": 3,
    "event": "upgrade",
    "user": {
      "name": "Alan Turing",
      "plan": "pro"
    },
    "at": "2024-11-03T10:01:47Z"
  }
]

Look at user. It is still an object with two keys in it, indented one level further in. There is no user.name anywhere, because nothing here is trying to make your data rectangular. The result panel says 3 records, and events.jsonl downloads as events.json.

Nothing about the records changes

This is worth being explicit about, because the phrase "JSONL to JSON" is also what people search when they want a table, and a converter that guesses wrong will quietly rewrite a training file. Here the guarantee is narrow and total:

  • A nested object stays a nested object, at whatever depth it was. No dotted keys, no flattening, no depth limit to trip over.
  • An array inside a record stays an array. A messages list from a chat export arrives with the same items in the same order.
  • Key order is the order the line had. Diffing the output against a colleague's copy stays meaningful.
  • Types are left alone. Numbers stay numbers, null stays null, false does not become the string "false".
  • Lines that are bare values work too. A file of quoted strings or plain numbers becomes an array of exactly those, not an array of objects wrapping them.
  • Text is not re-escaped. Accented names and emoji come through as themselves rather than as escape sequences.

If what you actually want is columns, that is a genuinely different job and it lives on JSONL to CSV, which unions ragged keys and flattens nesting on purpose.

When one line is broken

A JSONL file with a bad record is normally a good file with a typo, and the only question that matters is which line. So the error names it. Convert a file whose second line is missing its closing brace and you get:

Line 2 is not valid JSON: Expected ',' or '}' after property value in JSON at position 23

The first half is ours, the second half is your browser's JSON parser talking about that line on its own, which is why its position count restarts. Ignore the tail and go to the line number. A few details that follow from how the counting works:

  • Blank lines are counted, not renumbered. Line 2 means the second line of the file as your editor numbers it, so you can jump straight there.
  • Blank lines are still skipped. They are ignored as records, including the trailing newline at the end of a file and any gaps left by a concatenation.
  • Windows line endings are fine. Carriage returns are handled, so a file written on Windows and read on a Mac needs no cleanup.
  • Nothing is silently dropped. The conversion fails instead of skipping the record. A training set that quietly lost one example is a bug you find much later.
  • A truncated last line is the usual suspect. When a writer is killed mid-flush, the final line stops in the middle. Deleting it is almost always the right fix.

The two controls, and a tidier hidden in them

  • Structure. JSON array is the point of the page. Leave it on JSON Lines instead and you get a JSONL cleaner: every record re-written compactly, one per line, spacing normalised, download named .jsonl. Useful when a file has been through three tools and the lines no longer look alike.
  • Formatting. Pretty is two-space indentation, which is what the example above shows. Minified puts the whole array on one line, which is what you want in a request body. The setting has no effect on JSON Lines output, because indenting a record would break the one-per-line contract that format exists for.
  • Brackets already there. Hand it a pretty-printed array and it converts anyway, with the note "That is already a JSON array, so it was re-formatted rather than re-shaped." A file named .jsonl that turns out to be an array is common enough to be worth catching.
  • Files and paste both work. Drop .jsonl, .ndjson, .json or .txt, or paste lines straight from a terminal. Up to 100 MB, no row cap, no daily limit. Larger than that and the widget hands you the full editor, which streams instead.
  • It runs in your tab. There is no upload endpoint behind this page, which is the part that matters when the records are chat transcripts, eval prompts or customer data.

Frequently Asked Questions

What is JSONL, and how is it different from JSON?

A .json file holds one JSON value. A .jsonl file holds many, one per line, with no wrapping brackets and no commas joining them. Both are made of ordinary JSON, so the records themselves look identical; only the container differs. That container decides what a program can do with the file. An array has to be parsed whole before the first record is available. Lines can be read one at a time, appended to, split across workers and counted with wc -l.

Does converting to an array change my records?

No. This is a re-bracketing, not a transformation. A line holding a nested object comes out as the same nested object at the same depth, arrays stay arrays, key order is kept, and nulls and booleans are untouched. Nothing is flattened into dotted keys, which is what the JSONL to CSV page does and what makes it a different tool.

Is NDJSON the same as JSONL?

For every practical purpose, yes. NDJSON, newline-delimited JSON and JSON Lines all mean one complete JSON value per line. Two specifications were written independently, which is why there are two names and two file extensions. This page accepts .jsonl, .ndjson, .json and .txt, and it reads the content rather than trusting the extension.

One line in my file is broken. What does it tell me?

It names the line. The message starts with something like "Line 2 is not valid JSON" and then repeats what the browser's own parser said. Line numbers count blank lines too, so the number matches what your editor shows in the gutter and you can jump straight to it. The conversion stops rather than dropping the record, because losing an example out of a dataset without being told is worse than an error.

What if my file already has square brackets around it?

It still converts. A pretty-printed array fails on line one, since an opening bracket on its own is not a JSON value, so the engine retries the whole document as a single array. It succeeds, and the result carries the note "That is already a JSON array, so it was re-formatted rather than re-shaped." Handy when a file is named .jsonl but was written as an array.

Can I go back to JSON Lines, or minify the array?

Yes to both. Structure switches between a JSON array and JSON Lines, and Formatting switches between pretty two-space indentation and minified. Set Structure back to JSON Lines and you have a JSONL tidier: every record is re-written compactly, one per line, and the download is named .jsonl instead of .json.

Turn your lines into an array

Drop the .jsonl or .ndjson file, or paste the lines. Copy the array or download the .json. No sign-up, no upload, no row cap.

Back to the converter