Glossary

JSON Lines

JSON Lines holds one JSON record per line, so large exports can be streamed and appended to. This entry gives the rules, a worked example and the traps.

Updated 5 October 20262 min read

JSON Lines is a text format in which each line is one complete JSON value, usually an object, and lines are separated by a newline character. A record never spans lines, so a file can be read, split, streamed and appended to one record at a time.

The rules

The format is short enough to state in full:

  • The file is UTF-8, and a byte order mark must not be included.
  • Every line is a valid JSON value, and a blank line is not one.
  • Lines end with \n, and \r\n is accepted. A line ending after the last value is recommended.
  • The suggested extension is .jsonl, or .jsonl.gz for a compressed file.

The rules are kept at jsonlines.org. Two lines of an illustrative file for Acme Robotics, trimmed to four fields:

{"company": "Acme Robotics", "day": "2026-10-01", "open_postings": 42, "new_postings": 3}
{"company": "Acme Robotics", "day": "2026-10-02", "open_postings": 44, "new_postings": 2}

To read it, parse one line at a time:

import json

with open("export.jsonl", encoding="utf-8") as f:
    for line in f:
        row = json.loads(line)
        print(row["day"], row["open_postings"])

Against CSV and a single JSON file

A single JSON file holds one value, usually a large array, and a reader has to parse all of it before it can use any of it. A JSON Lines file can be processed a record at a time, split by lines for parallel loading and extended by appending. Against CSV, it keeps nested values and numbers as they are, and a newline inside a text value is escaped rather than needing quotes. The cost is size, because every line repeats the field names, so compress the file.

Mistakes that break a load

  • Pretty-printed JSON is not JSON Lines, because each record spans several lines.
  • A file holding one JSON array is JSON, and a line reader will fail on it.
  • Lines do not all carry every key, so test for a missing key rather than assuming one.
  • A transfer cut in the middle of a record fails on its last line. One cut between records does not, so compare the line count with the rows you expect for the period.

In Fokals data

Bulk exports come as JSON, JSON Lines or CSV, page by page through the export endpoints or as a package of files with a manifest. In the CSV files, lists and objects are JSON in a single cell, as with the postings by job function in Hiring Activity; the conventions are in the data dictionary. The comparison of CSV, JSON Lines and Parquet sets out when each format fits, and the delivery page covers the exports themselves.

Frequently asked questions

What is the difference between JSON and JSON Lines?

A JSON file holds one value, often a large array or object, and must be parsed as a whole. A JSON Lines file holds one JSON value per line, so you can stream it, split it by lines and append to it. Each line is valid JSON on its own, but the file as a whole is not a single valid JSON document.

How do I open a JSON Lines file?

Read it line by line and parse each line as JSON. In Python that is a loop over the file with json.loads, and jq reads the format without extra flags. Many analytical engines and warehouses can also load it directly. Do not call a whole-file JSON parser on it, because the file as a whole is not one JSON value.

Is JSON Lines the same as NDJSON?

They describe the same idea, one JSON value per line, and differ in small points. JSON Lines suggests .jsonl and treats a blank line as invalid, while NDJSON suggests .ndjson and lets a parser ignore empty lines. A reader built for one will normally read the other, but check how it treats blank lines.

The queries and code on this page are examples to adapt. Test them in your own environment before you rely on them.