JSONL Tutorial: Create, Read & Convert JSONL Files
A step-by-step tutorial covering everything you need to know about working with JSONL (JSON Lines) files. Includes code examples in Python, JavaScript, and CLI tools.
Last updated: February 2026
What is JSONL?
JSONL (JSON Lines) is a lightweight text format where each line is a separate, valid JSON value. Unlike standard JSON, which wraps all data in a single array or object, JSONL stores one record per line, separated by newline characters (\n).
This line-by-line structure makes JSONL ideal for streaming large datasets, appending records without rewriting the file, and processing data in parallel. It is widely used by OpenAI for fine-tuning datasets, by logging systems like the ELK stack, and by big data tools such as BigQuery and Apache Spark.
{"id":1,"name":"Alice","role":"engineer"}{"id":2,"name":"Bob","role":"designer"}{"id":3,"name":"Charlie","role":"manager"}
How to Create JSONL Files
Creating a JSONL file is straightforward: serialize each record as a single-line JSON string and write it followed by a newline. Here are examples in the most popular languages.
import jsonrecords = [{"id": 1, "name": "Alice", "role": "engineer"},{"id": 2, "name": "Bob", "role": "designer"},{"id": 3, "name": "Charlie", "role": "manager"},]with open("output.jsonl", "w", encoding="utf-8") as f:for record in records:f.write(json.dumps(record, ensure_ascii=False) + "\n")print("Created output.jsonl with", len(records), "records")
import { writeFileSync } from 'fs';const records = [{ id: 1, name: 'Alice', role: 'engineer' },{ id: 2, name: 'Bob', role: 'designer' },{ id: 3, name: 'Charlie', role: 'manager' },];const jsonl = records.map(record => JSON.stringify(record)).join('\n');writeFileSync('output.jsonl', jsonl + '\n', 'utf-8');console.log(`Created output.jsonl with ${records.length} records`);
Manual / Text Editor
You can also create JSONL files in any text editor. Simply type one valid JSON object per line with no commas between lines, and save the file with a .jsonl extension. Make sure each line is complete and valid JSON.
How to Read JSONL Files
Because each line is an independent JSON value, reading JSONL files is as simple as iterating over lines. Here are the most common approaches.
import jsonwith open("data.jsonl", "r", encoding="utf-8") as f:for line_number, line in enumerate(f, 1):line = line.strip()if not line:continue # skip empty linesrecord = json.loads(line)print(f"Line {line_number}: {record['name']} - {record['role']}")
import { createReadStream } from 'fs';import { createInterface } from 'readline';const rl = createInterface({input: createReadStream('data.jsonl', 'utf-8'),});let lineNumber = 0;for await (const line of rl) {if (!line.trim()) continue; // skip empty lineslineNumber++;const record = JSON.parse(line);console.log(`Line ${lineNumber}: ${record.name} - ${record.role}`);}
# View first 10 lineshead -n 10 data.jsonl# Count total recordswc -l data.jsonl# Pretty-print each line with jqcat data.jsonl | jq .# Filter records where role is "engineer"cat data.jsonl | jq 'select(.role == "engineer")'# Extract only the name fieldcat data.jsonl | jq -r '.name'# Search for lines containing a keywordgrep '"Alice"' data.jsonl
How to Convert JSON to JSONL
If you have a standard JSON array, converting to JSONL means writing each element as a separate line. This is one of the most common JSONL operations.
import json# Read JSON arraywith open("data.json", "r", encoding="utf-8") as f:data = json.load(f) # expects a JSON array# Write as JSONLwith open("data.jsonl", "w", encoding="utf-8") as f:for record in data:f.write(json.dumps(record, ensure_ascii=False) + "\n")print(f"Converted {len(data)} records from JSON to JSONL")
import { readFileSync, writeFileSync } from 'fs';// Read JSON arrayconst data = JSON.parse(readFileSync('data.json', 'utf-8'));// Write as JSONLconst jsonl = data.map(record => JSON.stringify(record)).join('\n');writeFileSync('data.jsonl', jsonl + '\n', 'utf-8');console.log(`Converted ${data.length} records from JSON to JSONL`);
How to Convert CSV to JSONL
Converting CSV to JSONL maps each row to a JSON object, using the CSV header as field names. This is useful when migrating tabular data into a format suitable for streaming or machine learning.
import csvimport jsonwith open("data.csv", "r", encoding="utf-8") as csv_file:reader = csv.DictReader(csv_file)with open("data.jsonl", "w", encoding="utf-8") as jsonl_file:for row in reader:jsonl_file.write(json.dumps(row, ensure_ascii=False) + "\n")print("Converted CSV to JSONL successfully")
import { readFileSync, writeFileSync } from 'fs';const csv = readFileSync('data.csv', 'utf-8');const lines = csv.trim().split('\n');const headers = lines[0].split(',');const jsonl = lines.slice(1).map(line => {const values = line.split(',');const obj = {'};headers.forEach((h, i) => obj[h.trim()] = values[i]?.trim());return JSON.stringify(obj);}).join('\n');writeFileSync('data.jsonl', jsonl + '\n', 'utf-8');console.log('Converted CSV to JSONL successfully');
JSONL Best Practices
Use UTF-8 encoding for all JSONL files. This ensures compatibility across platforms and supports international characters.
Write exactly one JSON object per line. Never split a JSON object across multiple lines or put multiple objects on the same line.
Do not add commas between lines. Unlike JSON arrays, JSONL uses newline characters as the sole delimiter.
Validate each line independently. Every line must be a complete, valid JSON value. Use a JSONL validator to catch syntax errors early.
Use streaming reads for large files. Instead of loading the entire file into memory, process it line by line using readline (Node.js) or file iteration (Python).
Keep records consistent in structure. While JSONL allows different schemas per line, keeping a uniform structure makes data processing much easier.
Avoid trailing whitespace. Ensure lines do not have extra spaces or tabs that could cause parsing issues.
End the file with a newline. A trailing newline after the last record helps tools like wc and cat handle the file correctly.
Common JSONL Errors
[
{"name":"Alice"},
{"name":"Bob"}
]{"name":"Alice"}
{"name":"Bob"}JSONL is not a JSON array. Do not wrap lines in square brackets or add commas between them. Each line stands alone.
{"name":"Alice"},
{"name":"Bob"},{"name":"Alice"}
{"name":"Bob"}Trailing commas after each line or commas between lines are invalid in JSONL. The newline character is the only separator.
{
"name": "Alice",
"age": 30
}{"name":"Alice","age":30}Each JSON object must fit on a single line. Pretty-printed JSON with indentation and line breaks is not valid JSONL.
{"text":"She said "hello""}{"text":"She said \"hello\""}Quotes and special characters inside JSON strings must be properly escaped with backslashes. Unescaped quotes will break the JSON parser.