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.
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:
[
{"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:
{"id": 1, "user": {"city": "Amsterdam"}, "price": 15}
{"id": 2, "user": {"city": "Berlin"}, "price": 25}JSON vs JSONL compared: streaming, appending and memory
| Property | JSON | JSONL |
|---|---|---|
| Structure | One root value (array or object) with commas between items | One JSON value per line, no outer brackets |
| Streaming | Needs the whole file or a streaming token parser | Read and parse one line at a time |
| Appending | Remove the closing ], add a comma and the object, close the array again | Write one more line at the end of the file |
| Memory use | Standard parsers load the whole document | One line in memory at a time |
| Tooling | Native in browsers, editors and APIs | Line-based Unix tools, jq, DuckDB and rows.page |
| Half-written file | Invalid, because the closing ] is missing | Every 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:
jq -c '.[]' data.json > data.jsonl
jq -s '.' data.jsonl > data.jsonrows.page
Use rows.page when you want to filter the records before converting, or skip the command line:
- Drop a
.json,.jsonl,.ndjsonor.ldjsonfile on rows.page, or click Paste data and paste it. - Optionally filter the rows or run a SQL query to keep only the records and columns you need.
- 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
.jsonfile is refused with "Too big for this browser", while a bigger.jsonlfile 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:NLorprice:>20, or a SQL statement against the tabledatawith 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
| What | Limit or price |
|---|---|
| Open a file in your browser | Files 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.