JSON Viewer

JSON Lines (NDJSON): what it is and when to use it

One JSON value a line. Why logs and data exports use it, and how to read, write and convert it.

Updated 2026-11-04 · 6 minute read

JSON Lines is a file where each line holds one complete JSON value.

{"id": 1, "event": "login", "at": "2026-11-04T09:00:00Z"}
{"id": 2, "event": "view", "at": "2026-11-04T09:00:04Z"}
{"id": 3, "event": "logout", "at": "2026-11-04T09:12:31Z"}

That is the whole format. No outer brackets, no commas between the records. It also goes by the names NDJSON (newline delimited JSON) and JSONL, and the file usually ends in .jsonl or .ndjson.

Why it exists

A normal JSON file holds one value. If that value is a list of ten million records, a reader must read the whole file before it can use the first record, because the file is not complete until the final ] arrives.

JSON Lines turns that around. Each line is complete on its own. So:

Who uses it

The rules

  1. One value on each line. It does not have to be an object, but in practice it almost always is.
  2. No line break inside a record. This is the rule people break. A record must be on one line, so the writer must not pretty-print it. A \n inside a text value is fine, because it is written as the two characters \ and n, not as a real line break.
  3. UTF-8, and \n as the line separator.
  4. An empty line is usually allowed and ignored. Do not depend on it.

Reading it

On the command line

wc -l events.jsonl                 # how many records
head -3 events.jsonl               # look at the first three
grep '"event": "error"' events.jsonl | head
jq -c 'select(.event == "error")' events.jsonl
jq -s '.' events.jsonl > events.json   # make it one array

In this viewer. Open the file and the tool sees the form by itself: it shows the records as a list, with an index for each one. Everything else then works as usual — the tree, the search, JSONPath, the table view and the conversion to CSV. Press Format and you get one proper JSON array, which is the usual way to turn JSONL into JSON.

In Python

import json

with open('events.jsonl') as f:
    for line in f:
        if line.strip():
            record = json.loads(line)
            process(record)

In Node

import { createReadStream } from 'node:fs'
import { createInterface } from 'node:readline'

const lines = createInterface({ input: createReadStream('events.jsonl') })
for await (const line of lines) {
  if (line.trim()) process(JSON.parse(line))
}

Writing it

The one rule that matters: do not pretty-print.

import json

with open('out.jsonl', 'w') as f:
    for record in records:
        f.write(json.dumps(record) + '\n')     # no indent
for (const record of records) {
  stream.write(JSON.stringify(record) + '\n')  // no second argument
}

Flush or close the file at the end. A half-written last line is the most common fault in a JSONL file.

When not to use it

JSON Lines against CSV

Both hold one record a line, and people often choose between them.

JSON Lines CSV
Nested data Yes No
Types Text, number, true, false, null Everything is text
Each record names its fields Yes Only the header does
Size Bigger, keys repeat Smaller
A spreadsheet opens it No Yes

Choose CSV when the data is a flat table and a person will open it in a spreadsheet. Choose JSON Lines when records are nested, or when the fields differ from record to record.

The viewer converts between them: open a JSONL file and use Tools → To CSV.

Try it on your own file. The tool runs in your browser. Nothing is uploaded, and nothing is stored on a server.

Open the JSON Viewer

Read next

How to compare two JSON files

Why a plain text diff fails on JSON, what a real JSON comparison does, and how to read the result.

How to turn JSON into CSV

The rules for flattening nested data into columns, the traps, and three ways to do it.