Data Formats2026-09-29

JSON vs JSONL: Format, Examples, and When to Use Each

Compare JSON arrays and JSON Lines with valid examples, streaming code, common parsing errors, and a quick way to validate each format.

jsonjsonldata-formatspythonjavascript

JSON vs JSONL: the difference in one example

JSON is one serialized value. A file containing multiple records often wraps them in an array. JSONL (JSON Lines, usually .jsonl) writes one complete JSON value on each line. Both use JSON syntax inside each value, but the whole JSONL file is generally not one valid JSON document.

For two events, a JSON array looks like this:

[
  {"event":"login","userId":1},
  {"event":"logout","userId":1}
]

The same records in JSONL look like this:

{"event":"login","userId":1}
{"event":"logout","userId":1}

The braces and commas within each line follow ordinary JSON rules. There is no comma between JSONL lines and no array wrapper. The JSON Lines specification requires UTF-8 and one valid JSON value per line; a trailing newline after the last value is recommended. Blank lines are not valid JSONL records. The JSON standard, RFC 8259, defines the JSON value syntax used by each line.

Which should you choose?

Need Better fit Why
A conventional API response with one structured object or array JSON The entire response is one value that standard parsers accept.
Append new log or event records JSONL Add a line without rewriting an enclosing array.
Read a large dataset record by record JSONL Process one line at a time without loading the entire file.
Share configuration with nested relationships JSON One document preserves the full structure.
Import or export independent training/data records JSONL Each line can be handled separately.

JSONL can still contain nested objects or arrays inside a line. It is useful when the top-level items are independent records. It does not make the data smaller by itself; line breaks and repeated property names still consume bytes. Compression may matter more for transfer size.

Read JSONL in Python

Parse each nonempty line independently and include the line number in errors:

import json

with open("events.jsonl", encoding="utf-8") as source:
    for line_number, line in enumerate(source, start=1):
        if not line.strip():
            raise ValueError(f"Blank line at {line_number}")
        try:
            event = json.loads(line)
        except json.JSONDecodeError as exc:
            raise ValueError(f"Invalid JSON on line {line_number}: {exc}") from exc
        print(event["event"])

To write independent records:

import json

records = [{"event": "login", "userId": 1}, {"event": "logout", "userId": 1}]
with open("events.jsonl", "w", encoding="utf-8") as output:
    for record in records:
        output.write(json.dumps(record, ensure_ascii=False) + "\n")

Read JSONL in Node.js

readline lets you process a file line by line:

import fs from "node:fs";
import readline from "node:readline";

const lines = readline.createInterface({
  input: fs.createReadStream("events.jsonl", { encoding: "utf8" }),
  crlfDelay: Infinity,
});

let lineNumber = 0;
for await (const line of lines) {
  lineNumber++;
  if (!line.trim()) throw new Error(`Blank line at ${lineNumber}`);
  try {
    const event = JSON.parse(line);
    console.log(event.event);
  } catch (error) {
    throw new Error(`Invalid JSON on line ${lineNumber}: ${error.message}`);
  }
}

Common mistakes

Putting commas between lines. A trailing comma makes a line invalid JSON. Write each record as a complete value followed only by a newline.

Pasting the entire JSONL file into a JSON validator. A normal validator expects one JSON value. Validate each line separately with the JSON Validator. If you have a JSON array, validate the whole document there.

Using a literal newline inside a string. Encode it as \n inside the JSON string. The actual line break marks the end of the JSONL record.

Assuming every line is an object. The format permits any valid JSON value, including arrays, strings, numbers, booleans, and null. Your application can impose a stricter record schema.

For readable individual records, use the JSON Formatter. For compact JSON output, use the JSON Minifier; it accepts one JSON value at a time, not an entire JSONL stream.