JSON Lines (NDJSON) Validator

Paste a .jsonl or .ndjson file to check every record. Problems are reported per line, with the same plain-English explanations as the JSON validator.

Input

Settings

History

Load from URL

One JSON value per line

JSON Lines (also called NDJSON or LDJSON) stores one complete JSON value on each line, separated by newlines. It is the format of OpenAI and Vertex AI fine-tuning datasets, BigQuery and Elasticsearch bulk imports, many structured loggers and streaming APIs. Because each line is parsed on its own, one malformed record can break an import at row 31,207 while every other row is fine. That is exactly the case this validator is built for.

For a file to be valid:

  • every non-empty line is a complete JSON value, usually an object;
  • each value follows strict JSON rules: double quotes, no trailing commas, no comments, no NaN;
  • a record must not be spread over several lines.

Blank lines are tolerated and ignored, which matches what most readers do. Records do not all have to be objects or share the same keys; a line holding an array or a plain string is valid JSON Lines, even if your importer expects something narrower.

Errors that name the record

Every message starts with the record it concerns, as in Record on line 2: Trailing comma before '}', followed by a hint like “JSON does not allow a comma after the last property”. The line is highlighted in the editor, and the rest of the file stays readable. In the output pane, the result from the last clean pass is kept on screen in a faded state while you repair the record, so you can compare before and after.

A pretty-printed record that spans several lines is a special case. Strictly it breaks the format, but the intent is obvious, so the validator joins it into one line and adds an informational note instead of an error. If your producer emits multi-line records, fix it at the source: most JSON Lines readers split on newlines and will fail.

Common causes of bad records

Exports written by string concatenation produce most broken rows: a trailing comma left by a loop, single quotes from a Python str(dict), or an unescaped newline inside a message field. Truncated last lines are another classic, when a log file is copied while it is still being written. And sometimes the whole file is a JSON array rather than JSON Lines; an array on a single line is technically one valid record, so use JSON Lines to JSON or JSON to JSON Lines to switch between the two shapes deliberately.

The check is syntax only. It does not verify that every record has the same keys, that a messages array follows a fine-tuning schema, or that timestamps are sorted; the Table view helps you eyeball consistency across records. Files are parsed in your browser, so logs with user IDs or prompts with private data stay on your machine.

Examples

Trailing comma in one event

Invalid: record 2 has a comma before its closing brace, and the message names line 2 directly.

Input
{"event":"signup","user":"usr_42","ts":"2026-09-14T08:21:05Z"}
{"event":"purchase","user":"usr_42","total":129.9,}
{"event":"logout","user":"usr_42","ts":"2026-09-14T08:40:12Z"}
Result
Line 2, column 50: Record on line 2: Trailing comma before '}'
Open this example in the tool

Python-style quotes in a dataset row

Invalid: the second record uses single quotes, which JSON Lines inherits as an error from JSON.

Input
{"prompt":"Summarise order ord_8f2k1","completion":"Shipped on 14 Sep"}
{'prompt':'Summarise order ord_9a1x2','completion':'Awaiting payment'}
Result
Line 2, column 2: Record on line 2: Object keys must use double quotes, not single quotes
Open this example in the tool

A record split across lines

Accepted with a note: the first record is joined into one line because JSON Lines requires one record per line.

Input
{"level":"info","msg":"server started",
 "port":8080}
{"level":"warn","msg":"slow query","ms":812}
Output
{"level":"info","msg":"server started","port":8080}
{"level":"warn","msg":"slow query","ms":812}
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
Record on line 2: Trailing comma before '}'
Explained
The writer appended a comma after the last property of that record.Remove the comma, or use Fix it on that record.
Record on line 2: Strings must use double quotes, not single quotes
Explained
The record was produced with str() or repr() in Python rather than json.dumps().Regenerate the file with json.dumps(), or replace the quotes in that record.
Record on line 2: Unexpected word 'not' — strings must be in double quotesA plain text line, such as a log banner or a stack trace line, is mixed into the file.Delete non-JSON lines or filter them out before importing.
The record on line 1 spans 2 lines; JSON Lines needs one record per line, so it was joinedA record was pretty-printed over several lines.Nothing to do here, but configure the producer to write compact records.

Frequently asked questions

Is NDJSON the same as JSON Lines?

For practical purposes, yes. Both mean one JSON value per line separated by newlines; the names come from two separate specifications that describe the same format.

Are empty lines allowed?

They are skipped. Most readers do the same, though a strict producer should not write them.

Can I validate an OpenAI fine-tuning file here?

You can check that every line is valid JSON, which is the most common reason uploads fail. The validator does not check the messages schema itself.

How large a file can I check?

Large exports are fine because each line is parsed independently. On very big files, use Ctrl/Cmd+Enter to validate on demand instead of while typing.

Related tools