JSONL 教程:创建、读取和转换 JSONL 文件
逐步教程,涵盖使用 JSONL (JSON Lines) 文件所需的一切知识。包含 Python、JavaScript 和 CLI 工具的代码示例。
最后更新:2026年2月
什么是 JSONL?
JSONL (JSON Lines) 是一种轻量级文本格式,每行是一个单独的、有效的 JSON 值。与将所有数据包装在单个数组或对象中的标准 JSON 不同,JSONL 每行存储一条记录,用换行符 (\n) 分隔。
这种逐行结构使 JSONL 非常适合流式传输大型数据集、追加记录而无需重写文件,以及并行处理数据。它被 OpenAI 用于微调数据集,被 ELK stack 等日志系统使用,以及 BigQuery 和 Apache Spark 等大数据工具广泛采用。
{"id":1,"name":"Alice","role":"engineer"}{"id":2,"name":"Bob","role":"designer"}{"id":3,"name":"Charlie","role":"manager"}
如何创建 JSONL 文件
创建 JSONL 文件很简单:将每条记录序列化为单行 JSON 字符串,并在其后写入换行符。以下是最流行语言的示例。
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`);
手动 / 文本编辑器
您也可以在任何文本编辑器中创建 JSONL 文件。只需每行输入一个有效的 JSON 对象,行之间不加逗号,并以 .jsonl 扩展名保存文件。确保每行都是完整且有效的 JSON。
如何读取 JSONL 文件
因为每行都是一个独立的 JSON 值,读取 JSONL 文件就像迭代行一样简单。以下是最常见的方法。
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
如何将 JSON 转换为 JSONL
如果您有一个标准的 JSON 数组,转换为 JSONL 意味着将每个元素作为单独的行写入。这是最常见的 JSONL 操作之一。
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`);
如何将 CSV 转换为 JSONL
将 CSV 转换为 JSONL 会将每行映射到一个 JSON 对象,使用 CSV 标题作为字段名。这在将表格数据迁移到适合流式或机器学习的格式时非常有用。
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 最佳实践
对所有 JSONL 文件使用 UTF-8 编码。这确保了跨平台兼容性,并支持国际字符。
每行只写一个 JSON 对象。永远不要将 JSON 对象拆分到多行,或在同一行上放置多个对象。
不要在行之间添加逗号。与 JSON 数组不同,JSONL 使用换行符作为唯一的分隔符。
独立验证每行。每行必须是完整、有效的 JSON 值。使用 JSONL 验证器及早发现语法错误。
对大文件使用流式读取。不要将整个文件加载到内存中,而是使用 readline (Node.js) 或文件迭代 (Python) 逐行处理。
保持记录结构一致。虽然 JSONL 允许每行使用不同的模式,但保持统一的结构使数据处理更容易。
避免尾随空白。确保行末没有可能导致解析问题的额外空格或制表符。
文件以换行符结尾。在最后一条记录后添加尾随换行符有助于 wc 和 cat 等工具正确处理文件。
常见 JSONL 错误
[
{"name":"Alice"},
{"name":"Bob"}
]{"name":"Alice"}
{"name":"Bob"}JSONL 不是 JSON 数组。不要在方括号中包装行或在它们之间添加逗号。每行独立存在。
{"name":"Alice"},
{"name":"Bob"},{"name":"Alice"}
{"name":"Bob"}每行后的尾随逗号或行之间的逗号在 JSONL 中是无效的。换行符是唯一的分隔符。
{
"name": "Alice",
"age": 30
}{"name":"Alice","age":30}每个 JSON 对象必须适合单行。带有缩进和换行符的美化打印 JSON 不是有效的 JSONL。
{"text":"She said "hello""}{"text":"She said \"hello\""}JSON 字符串中的引号和特殊字符必须用反斜杠正确转义。未转义的引号会破坏 JSON 解析器。