NDJSON / JSONL Viewer — Inspect JSON Lines Online
NDJSON / JSONL Viewer — Inspect Newline-Delimited JSON Online
Every JSON parser you already know expects one JSON document. Hand it a .jsonl file and it fails at once, and the error makes the data look broken. It isn't. NDJSON is a sequence of independent JSON values separated by newlines: the parser finishes the first object, finds a newline and a second { where it expected end of input, and gives up.
This JSON Lines viewer is an NDJSON viewer built for the format as specified: one physical line equals one record. You can view JSONL files, inspect JSONL records one at a time, and a malformed line is reported as a malformed line instead of destroying everything around it.
What NDJSON actually is
NDJSON — also called JSON Lines, JSONL, or newline-delimited JSON — is a tiny specification published at jsonlines.org. Two rules:
- Each line contains exactly one JSON value: an object, an array, a string, a number,
true,false, ornull. - Lines are separated by
\n.
That is the entire format. A trailing newline at the end is conventional, so the file technically ends with an empty line, which readers ignore. The recommended media type is application/x-ndjson, registered with IANA. And because there is no wrapping array between records, a reader can start consuming before the last byte is written — the whole point of the format.
A complete three-record file:
{"id": 1, "event": "page_view", "path": "/pricing", "ms": 812}
{"id": 2, "event": "signup", "path": "/pricing", "ms": 1940}
{"id": 3, "event": "error", "path": "/checkout", "ms": 233}Each line alone is a complete JSON document. Together they are still not one — and that is fine, because they were never meant to be.
Where you will find NDJSON
- LLM training and evaluation datasets. Fine-tuning exports and eval harnesses are published as JSONL so a training loop can read one example at a time.
- AI model and dataset releases. Hugging Face datasets and OLMo-style pretraining mixes ship as
.jsonlshards, which makes them a natural fit for an NDJSON dataset viewer. - BigQuery and Dataproc exports.
bq exportand Dataproc write table rows as newline-delimited JSON, so exported tables arrive as.jsonl.gz. - Application and server logs. JSON-formatted Pino, Winston, and Serilog emit one object per line, so JSONL logs stay greppable while the app runs.
- Data pipelines and ETL. Kafka Connect, Airflow tasks, and batch loaders pass records through as a sequence; a file is that sequence on disk.
- API and event exports. Analytics dumps, audit trails, webhook delivery logs, and clickstream sessions are routinely saved as JSONL.
What this NDJSON viewer does
Drop a file on the page, pick one with the file picker, or paste the raw text in. Then:
- Every line is parsed independently, producing a numbered record list where each row is one physical line.
- Each record carries a validity state — valid, invalid, or empty — counted separately so a blank line never looks like corruption.
- Malformed lines keep their evidence: the raw text beside the JSON parser's error message and character position, so you know whether it was a trailing comma or an unquoted key.
- Open any record and it is pretty-printed at once, which makes this an NDJSON formatter as much as a reader.
- Search matches the raw line text, so it works even on unparseable records, with a live match count.
- Filter to invalid records only, turning "something in this export is wrong" into a short, fixable list.
- Schema hints show which keys appear across your records and how consistently.
- Virtualized rows mount only what is on screen, so scrolling millions of lines stays responsive.
- Export the valid, invalid, visible, or complete set of records as
.jsonl.
Common edge cases handled
Blank lines are counted as empty rather than flagged as errors, because a trailing newline at the end of every well-formed file produces one — so a trailing newline is free. Surrounding whitespace is trimmed before parsing. Escaped \n inside a string value stays part of the record, because the newline that separates records is a break in the file, not in the data. Nested objects and arrays work however deeply they nest, since each line is a complete value in its own right. Top-level primitives are valid, so a file of bare numbers or bare strings is a legitimate records file. Unicode survives as written, and very long lines parse without a length limit. Malformed records never abort the file.
Why ordinary JSON parsers fail on JSONL
The whole problem in six lines:
const text = await file.text();
// Throws: Unexpected non-whitespace character after JSON at position 21
const data = JSON.parse(text);
// Works — one JSON value per line
const records = text.split("\n").filter(Boolean).map(JSON.parse);The split is the fix, and it has to stay a plain split. You must not treat an escaped \n sequence as a separator: those two characters inside a string are data, not a boundary, and honouring them would cut records in half. Splitting only on real line breaks keeps one line equal to one JSON value, the invariant the format is built on.
For a file you want as one document, use the JSON Formatter or the JSON Validator. This viewer detects the single-document case and offers to hand it off.
Working with large files
Never parse a big NDJSON export into one array and hand it to React as state — that is how a tab runs out of memory and the page goes white. Instead: read and split the file in chunks on a background worker, keep only lightweight per-line metadata in the list, render through a virtualized list, and materialize a record's parsed value only when you open it. JSON.parse per line stays the right primitive: native, fast, and the best error messages you can get.
Privacy
Everything runs in your browser. Files are read with the browser's File API, parsing uses local JavaScript, and there is no upload endpoint, no backend, and no database. Your logs, exports, and training data never leave your machine.
Frequently Asked Questions
Why does JSON.parse throw on my JSONL file?
It expects one complete JSON value and rejects whatever follows. It finishes the first object, hits a newline and a second { where end-of-input was expected, and reports an unexpected token. The file is valid NDJSON; treating it as a single document is what failed.
Are blank lines an error?
No. A blank or whitespace-only line carries no value, so readers ignore it. This viewer marks such lines empty rather than invalid: counted separately, hidden from the invalid-only filter, skipped on export.
A newline appeared inside one of my string values — what went wrong?
A real line break inside a JSON string is not allowed; it must be the escaped sequence \n. If a writer emitted a literal newline, the record splits into two physical lines and both halves become invalid records.
One broken line means the file is unusable?
The opposite. Line independence is the format's core guarantee, so a malformed record only invalidates itself. The rest keeps parsing, the bad record is labelled with the parser's message and its raw text, and exporting the valid records gives a clean file.
Can it open a multi-gigabyte export?
Yes. Chunked reading and parsing run on a background worker, the record list is virtualized so only visible rows mount, and a record's parsed value is created only when you open it.
Is my data uploaded?
Never. Reading, splitting, parsing, searching, and exporting all run locally — no server, no database.
What does the export produce?
A .jsonl file written one record per line with the application/x-ndjson media type, so BigQuery bq load, jq, and pandas read_json(lines=True) consume it directly. Choose the valid, invalid, visible, or complete record set.
What if the file is really one big JSON array?
Then it is not NDJSON — the newlines are indentation, not separators. The viewer notices and offers to treat the file as one record, or to open it in the JSON Formatter where it belongs.
Related tools
- JSON Formatter — pretty-print and validate a single JSON document
- JSON Validator — check one document's syntax with precise error positions
- JSON Tools Hub — the full set of JSON converters, generators, and inspectors