NDJSON to TableNDJSON to Table

Paste NDJSON to see it as a table

One JSON object per line — the shape a log pipeline or a bulk export produces.

A line that will not parse is reported by number and skipped, not fatal.

Why your JSON viewer choked on this file

You have an export — from BigQuery, an Elasticsearch bulk dump, a CloudWatch or Loki query, an OpenAI batch job, or anything that has been through jq -c. You paste it into a JSON viewer and get an error somewhere around character forty. The file is not broken. It is not JSON.

It is NDJSON — also called JSON Lines, usually saved as .jsonl or .ndjson — and the difference is that each line is a complete JSON value, with no array brackets around the whole thing and no commas between records. That is a deliberate design: a process can append one more line without rewriting the file, and a reader can handle a hundred million records without holding them all in memory. It also means a JSON parser fed the whole file stops at the end of line one and complains about what follows.

So this page reads it the way the format intends: one line at a time. And the consequence of that is the thing worth coming here for — a line that will not parse does not cost you the file. Real exports are large and machine-written, and eventually one gets truncated by a killed process or a full disk. A parser that gives up on line 12,853 of 40,000 has thrown away 39,999 good records to tell you about one bad one. Here the bad lines are listed by number so you can go and look at them, and everything else becomes a table.

Two smaller things that also go wrong elsewhere. Records in a real export do not share a schema — a field added last March exists on newer rows and not older ones — so the columns here are the union across every record rather than whatever the first line happened to contain. And the long identifiers these files are full of, account references and ICCIDs and snowflake IDs, keep every digit instead of being rounded at the sixteenth by a JavaScript number.

Nothing is uploaded. Log exports and database dumps are exactly the kind of file that should not be pasted into a site that sends it somewhere.

Reading an export

  1. Paste the NDJSON, or upload the file – One JSON value per line. Blank lines are ignored — a trailing newline at the end of a file is universal and is not an error. If you paste a JSON <em>array</em> by mistake, you are told that rather than shown a parse error, and pointed at the page that converts it.
  2. Check the line-error note if one appears – It names the lines that would not parse, in the numbering your editor uses. Those records are missing from the table; everything else is there. Usually it is one truncated line at the end of a file, which tells you the export did not finish.
  3. Read, sort, search – Click a column to sort, type to filter across every field. Nested objects and arrays are shown inline and can be expanded, so a record with a nested <code>location</code> block is still one row.
  4. Take it somewhere else – Use <a href="/ndjson-to-json">NDJSON to JSON</a> if something downstream needs a real array, or <a href="/json-to-ndjson">JSON to NDJSON</a> to go back the other way when you are building a bulk-load file.

If the last line of a file is the only bad one, the export was cut short — a killed job, a full disk, or a stream that was still being written when it was copied. That is worth knowing before you use the data, because the records are fine and the set is incomplete. A bad line in the middle is a different story and usually means something non-JSON got into the stream, such as a log line from the exporting process itself.

What happens when a line is truncated

The Sample button loads a clean file. This is the other case — an export cut short mid-write, which is what a killed job or a full disk leaves behind. A parser handed the whole file gives up at line 3; reading line by line means the other records still arrive, and you are told exactly which one to go and look at.

.jsonl export → table line 3 is truncated
subscribers.jsonl4 lines, 1 broken
# one complete JSON value per line.
# no [ ] around it, no commas between.
{"msisdn":"447700900142","plan":"Unlimited 5G","rsrp":-92}
{"msisdn":"447700900458","plan":"Pay As You Go","rsrp":-104}
{"msisdn":"4477009007
{"msisdn":"447700900991","plan":"Business 200GB","rsrp":-78}

# line 3 was cut off mid-write.
# a JSON parser given the whole file
# stops there and returns nothing.
the table3 records, line 3 named
msisdnplanrsrp
447700900142Unlimited 5G-92
447700900458Pay As You Go-104
447700900991Business 200GB-78

What people use it for

Reading a log or analytics export

Structured logs come out of almost everything as one JSON object per line, and reading them as raw text means counting braces. As a table you can sort by timestamp, filter to one request ID, and see which fields are actually populated. This is the bulk of what the page is for.

Checking a bulk-load file before you send it

BigQuery calls it newline-delimited JSON and will not accept an array; the Elasticsearch bulk API wants alternating action and document lines. Looking at the file as a table before a load beats reading the rejection report afterwards.

Finding the corrupt line in a file that failed to import

An import rejected your file and named an offset rather than a line. Paste it here and the line numbers are listed directly. This is the use that people arrive at through search, and it is the one the page is built around.

Seeing which fields a schema-less export actually has

Because the columns are the union across every record, the header row is a complete list of every field present anywhere in the file. That is often the quickest way to find out what an undocumented export contains, and to spot the field that only appears on 3% of rows.

Questions that come up

What is the difference between NDJSON, JSON Lines and .jsonl?

Nothing that matters. They are three names for one convention: one JSON value per line, separated by newlines, with no enclosing array and no commas between records. jsonlines.org and the ndjson spec differ only in wording. Files carry .jsonl, .ndjson, or frequently just .json, which is how most people end up confused in the first place.

One line is broken. Why did the rest still work?

Because each line is a complete document and is parsed on its own, which is what the format is for. Handing the whole file to a JSON parser makes one bad byte fatal for the entire export — the common implementation, and the wrong one. The bad lines are named by number here and the rest is tabulated.

My columns are missing a field that I know is in the file.

That should not happen here, and it is worth saying why it happens elsewhere. Many tools take the keys of the first record as the column set, so a field added partway through an export is invisible. The columns on this page are the union of the keys across every record, so a field on one row out of forty thousand still gets a column.

Are my long ID numbers safe?

Yes. JSON.parse is exact only to about 15 digits because a JavaScript number is an IEEE-754 double, so a 19-digit identifier comes back rounded — 8901240544102066246 becomes 8901240544102066000, with no error. These values are read as text here and the digits reach the table unchanged. RFC 8259 is explicit that JSON itself sets no limit on numeric precision — the limit is the parser.

I pasted a JSON array and it did not work.

A JSON array is not NDJSON, and the page says so rather than showing a parse error. JSON to NDJSON converts one to the other, and JSON to Table will tabulate an array directly if that is all you wanted.

How do I produce NDJSON in the first place?

Most tools that emit a lot of records already do. From an existing JSON array, jq does it with jq -c '.[]' file.json — the -c is what keeps each record on one line, and without it you get pretty-printed JSON that is no longer line-delimited at all.

Related tools