JSON to JSONL

How to convert a JSON array to JSONL

rows.page converts a JSON file up to 1.5 GB to JSONL in 2 steps, free with no signup: drop the file, then pick JSONL in the Export menu. Nested objects come out as dot-path keys, so use jq when you need the original nesting or the file is too big for the browser.

.json
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).

Convert JSON to JSONL in your browser with rows.page

Drop your .json file onto rows.page, choose it from disk, or click Paste data and paste the text. DuckDB-WASM reads it inside your browser tab, so nothing is uploaded unless you press Share. Rows load in pages of 100 as you scroll.

  1. Open the .json file on rows.page, or paste the JSON.
  2. Optional: filter, sort, hide columns or run SQL in the query bar above the grid to choose what gets exported.
  3. Open the Export menu and choose JSONL. You get one JSON object per line.

The file doesn't have to be a bare [...] array. If it is one object such as {"data": [...], "next": "page2"}, rows.page finds the biggest list up to 4 levels deep, opens its items as rows and shows the note: Showing the N items in "data"; the other top-level fields were skipped.

Check what your next tool expects before you export. rows.page flattens nested objects into dot-path columns such as user.address.city, up to 8 levels deep and 200 child fields per object, and the JSONL export keeps those as flat keys like "user.address.city":"Utrecht". Arrays stay arrays.

Convert a JSON array to JSONL with jq

Use jq when every nested object must keep its braces, or when the file is over 1.5 GB, which rows.page refuses with "Too big for this browser". .[] walks the top-level array and -c prints each item on one compact line:

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

API responses often wrap the array in an object next to paging fields. Point jq at that key first, so only the array items become lines:

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

For {"data": [{"id": 1, "user": {"city": "Utrecht"}}, {"id": 2, "user": {"city": "Ghent"}}], "next": "page2"} that writes 2 lines, nesting intact:

json
{"id":1,"user":{"city":"Utrecht"}}
{"id":2,"user":{"city":"Ghent"}}

Plain jq reads the whole file into memory before it prints a line. For a file that doesn't fit, add --stream: jq then reads the file as a stream of path and value events, and fromstream(1|truncate_stream(inputs)) rebuilds each array item and prints it as soon as it is complete. The output matches jq -c '.[]' line for line.

bash
jq -cn --stream 'fromstream(1|truncate_stream(inputs))' data.json > data.jsonl

Which JSON to JSONL method to use

JSON to JSONL conversion methods
MethodKeeps nestingWorks on huge files
rows.pageNo: objects become dot-path keys (8 levels, 200 fields); arrays stay arraysUp to 1.5 GB per browser tab
jq -c '.[]'YesOnly if the file fits in memory
jq -cn --streamYesYes, it streams the file

Use rows.page when you want to look at the data, drop bad records or reshape it with SQL before you write the .jsonl file. Use jq when the structure must stay exactly as it is or the file is over 1.5 GB.

Filter or reshape your JSON before exporting to JSONL

The Export menu writes the current view: the visible columns, the active filter and the sort order. In the query bar, country:NL matches a value, price:>20 compares numbers, name:* keeps rows where the field has a value and -name:* keeps rows where it is null. Clicking a histogram bar or a top value in the Columns panel adds a filter too, and a filtered view exports every matching row.

To rename fields, add columns or remove duplicates, type SQL that starts with SELECT, WITH or FROM in the same bar and press Enter. The table is called data, and flattened names with dots need double quotes, such as "user.city":

sql
SELECT DISTINCT * EXCLUDE (__rid) FROM data WHERE "user.city" = 'Amsterdam' ORDER BY __rid

The hidden __rid column holds the row number, so EXCLUDE (__rid) keeps it out of the duplicate check and ORDER BY __rid keeps file order. SQL results export up to 1,000,000 rows; filtered views have no cap.

Why tools ask for JSONL instead of a JSON array

A JSON array wraps every record in one outer [ and ] with commas in between, so a reader has to track that structure to split the records. JSONL, also called NDJSON or JSON Lines, puts one complete JSON value on each line, so tools can read, split and append records line by line.

  • OpenAI's Batch API starts from a .jsonl file with one request per line.
  • BigQuery loads JSON only as newline-delimited JSON, one object per line.
  • Log pipelines append one event per line, so a file grows without rewriting a closing bracket.

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

What is the difference between JSONL, NDJSON and LDJSON?

Nothing: all three name the same layout, one JSON value per line. The rows.page file picker lists .jsonl and .ndjson, a dropped .ldjson file opens the same way, and the export is always saved as .jsonl.

Can I open a JSON file from a URL and export it as JSONL?

Yes. Put the public URL after rows.page/, as in https://rows.page/https://example.com/data.json, then export JSONL. Your browser fetches the file itself, or through the rows.page proxy when the host blocks cross-origin requests (up to 100 MB, 30 seconds and 5 redirects), and nothing is stored.

Why do some numbers come out as 7.0 in the JSONL file?

A column that mixes whole numbers and decimals, such as 12.5 and 7, is read as DOUBLE, so the export writes 7 as 7.0. JavaScript reads both as 7, but Python's json module turns 7.0 into a float.

What happens if a JSON field holds more JSON as a string?

If at least 90% of the first 1,000 non-null values in a text column are JSON objects, rows.page expands the column into dot-path columns and shows a note such as Expanded the JSON in "payload" into 3 columns. It skips the expansion when that would add more than 200 columns.

Can I share the converted file?

Share uploads the data you opened, not the export, and gives you a https://rows.page/<id> link; to host the JSONL itself, push it with curl -T data.jsonl https://rows.page. One push is capped at 100 MB, and the link expires after 7 days unless you claim it with the Keep it banner on the dataset page.