JSON vs JSONL

JSON vs JSONL: differences and when to use each

JSON stores a whole dataset as 1 value, usually an array, while JSONL writes 1 JSON value per line, so you can append to it and read it line by line. rows.page opens both formats up to 1.5 GB per browser tab and converts between them, free with no signup.

.json.jsonl
Drop a file here
Stays in your browserUp to 1.5 GB

No file handy? Open Every country, as nested JSON (250 rows, 1.4 MB).

What is the difference between JSON and JSONL?

JSON

A .json file is one JSON value, usually an array of objects or a wrapper object such as {"data": [...]}. The records sit inside outer brackets with commas between them:

json
[
  {"id": 1, "user": {"city": "Amsterdam"}, "price": 15},
  {"id": 2, "user": {"city": "Berlin"}, "price": 25}
]

JSONL

A .jsonl file, also called NDJSON (.ndjson) or .ldjson, drops the outer brackets and the commas. Each line is a complete JSON value, and a newline separates the records:

jsonl
{"id": 1, "user": {"city": "Amsterdam"}, "price": 15}
{"id": 2, "user": {"city": "Berlin"}, "price": 25}

JSON vs JSONL compared: streaming, appending and memory

JSON vs JSONL
PropertyJSONJSONL
StructureOne root value (array or object) with commas between itemsOne JSON value per line, no outer brackets
StreamingNeeds the whole file or a streaming token parserRead and parse one line at a time
AppendingRemove the closing ], add a comma and the object, close the array againWrite one more line at the end of the file
Memory useStandard parsers load the whole documentOne line in memory at a time
ToolingNative in browsers, editors and APIsLine-based Unix tools, jq, DuckDB and rows.page
Half-written fileInvalid, because the closing ] is missingEvery complete line before the cut-off is valid JSON

The last row matters for logs and exports. If a process crashes halfway through writing a .json array, the missing ] makes the whole file invalid. In a .jsonl file every line written before the crash still parses, and you lose only the last, incomplete line.

When should you use JSON or JSONL?

JSON

Use JSON for payloads small enough to parse in one go, or when the consumer expects one document tree: configuration files, REST API responses and nested documents that aren't a list of rows.

JSONL

Use JSONL for logs, event streams, database exports and files that keep growing. Because each line stands alone, you can split the file across workers, tail -f it while it is being written, or process it without loading it all into memory.

How do you convert JSON to JSONL and back?

jq

Turn a JSON array into JSONL with -c for compact one-line output. Turn JSONL back into an array with -s (slurp), which reads everything into memory:

bash
jq -c '.[]' data.json > data.jsonl
jq -s '.' data.jsonl > data.json

rows.page

Use rows.page when you want to filter the records before converting, or skip the command line:

  1. Drop a .json, .jsonl, .ndjson or .ldjson file on rows.page, or click Paste data and paste it.
  2. Optionally filter the rows or run a SQL query to keep only the records and columns you need.
  3. Open Export and pick JSONL for one object per line, or JSON for one array of objects.

rows.page flattens nested objects into dot-path columns such as user.address.city when it opens a file, and its exports keep those dot-path keys instead of nesting them again; lists stay real arrays. If you need the nested tree untouched, use jq.

How do you open and query JSON or JSONL files?

rows.page opens both formats with no account. DuckDB-WASM reads the file in your browser, and nothing is uploaded unless you press Share.

  • Size: up to 1.5 GB per browser tab. A bigger .json file is refused with "Too big for this browser", while a bigger .jsonl file loads its first rows with the note "Loaded the first N rows: the file is X, more than the browser can hold."
  • Wrapper objects: a single top-level object such as {"data": [...]} is unwrapped to its biggest list, up to 4 levels deep, with a note that the other top-level fields were skipped.
  • Single records: click a row to open a side drawer with a JSON/Fields toggle and Copy as JSON. There is no whole-file tree view.
  • Filter and SQL: type country:NL or price:>20, or a SQL statement against the table data with dot-path columns in double quotes, such as "user.city". SQL shows up to 1,000,000 result rows, and the grid loads 100 rows at a time as you scroll.

rows.page limits and prices

WhatLimit or price
Open a file in your browserFiles up to 1.5 GB, $0, no account, nothing uploaded
Share a link without an account$0, files up to 100 MB, link deleted 7 days after creation
Free account$0, 10 datasets kept, last 3 versions
Pro$12/month, 100 datasets, files up to 500 MB, private links
Max$39/month, 1,000 datasets, files up to 2 GB, private links

Questions

Is NDJSON the same thing as JSONL?

Yes. JSONL (JSON Lines), NDJSON (newline-delimited JSON) and LDJSON all mean one JSON value per line, and NDJSON files often use the media type application/x-ndjson. rows.page reads .jsonl, .ndjson and .ldjson the same way.

Why does jq -s run out of memory on a large JSONL file?

The -s flag slurps every line into one in-memory array before it writes anything, so memory grows with the file. The other direction, jq -c '.[]' data.json > data.jsonl, writes one line per item, but jq still parses the whole input array first.

How does rows.page handle nested objects and arrays?

Nested objects become dot-path columns such as user.address.city, up to 8 levels deep and 200 child fields per object. Arrays stay list columns that show the first 6 items and "+N", and you can expand them in SQL with unnest().

Can I open a remote JSON or JSONL URL without downloading it?

Yes, put the public URL after rows.page/, for example https://rows.page/https://example.com/data.jsonl, and your browser fetches it directly without storing anything on rows.page. If the host blocks cross-origin requests, rows.page uses its proxy, which handles up to 100 MB, 30 seconds and 5 redirects.

Can I share a JSON or JSONL file with a link?

Press Share in the explorer or run curl -T data.jsonl https://rows.page to upload the file and get a link. Without an account you get 100 MB per request, 50 pushes and 1 GB per IP address per UTC day, and links expire after 7 days.