大家都很熟悉 JSON 和 CSV,但你有没有遇到过处理几 GB 的大型 JSON 文件时导致内存直接爆炸?或是用 CSV 记录多层次嵌套数据时觉得转义符号超级痛苦?
在现代 AI 训练与海量数据处理领域,有一个数据格式正在默默成为主流标准,那就是 JSONL(JSON Lines)。
JSONL 的核心价值:解决传统 JSON 无法流式读取与 CSV 无法支持嵌套结构的两大痛点!
什么是 JSONL?一分钟搞懂“一行一个 JSON”的核心定义
JSONL 的全名是 JSON Lines (有时也被称为 NDJSON,即 Newline Delimited JSON)。它的核心概念非常直白:每一行都是一个独立且完整的 JSON 对象。
在传统的 JSON 文件中,最外层通常会有一个巨大的方括号 [] 将所有数据包起来,且各对象之间必须用逗号 , 隔开。而 JSONL 彻底摒弃了最外层的方括号与逗号,改用换行符 \n 来分隔每条数据。

三大常见数据格式对照
为了让大家更直观理解,我们将 JSONL、JSON 与 CSV 放在一起比较:
| 数据格式 | 排版结构 | 嵌套数据支持 | 流式读写(Streaming) | 适合场景 |
|---|---|---|---|---|
| JSON | 整份文件为单一阶层树状结构,需一次加载 | 原生支持 | 困难(需加载整份文件) | Web API 传输、配置文件 |
| CSV | 2D 平面表格,以逗号分隔字段 | 困难(需转义或编码) | 原生支持 | Excel 报表、平面数据 |
| JSONL | 一行一个独立 JSON,以换行分隔 | 原生支持 | 极佳(逐行读取与追加) | AI 训练集、海量 Log 记录 |
为什么 AI 模型训练与大数据 ETL 都偏爱 JSONL?
近年随着 OpenAI、Anthropic 等大语言模型(LLM)的崛起,JSONL 跃升为微调(Fine-tuning)与数据集准备的首选格式。这背后主要有两大关键优势:
1. 内存占用极低(支持 Streaming 流式处理)
当你的训练数据库高达 50 GB 时,如果是传统 JSON 文件,程序必须把整份 50 GB 的文件完整读入内存解析语法树,这会瞬间触发内存溢出(OOM)。
而 JSONL 支持 逐行读取(Line-by-line Streaming)。程序只需要一次读取一行(可能只有几 KB),处理完毕后释放内存再读下一行。
flowchart TD
subgraph TraditionalJSON["传统 JSON 读取方式"]
A1["读取 50 GB JSON 文件"] --> A2["解析全文件语法树"]
A2 --> A3["内存一次性加载 50 GB"]
A3 -->|高风险| A4["内存溢出崩溃 (OOM)"]
end
subgraph JSONLStreaming["JSONL 流式读取方式"]
B1["开启 50 GB JSONL 文件"] --> B2["读取第 1 行 (5 KB)"]
B2 --> B3["解析并处理单条数据"]
B3 --> B4["释放内存并读取下一行"]
B4 --> B5["稳定高效完成海量数据处理"]
end
对于海量数据而言,JSONL 让内存消耗从 O(N) 降为 O(1)!
2. 支持无锁追加(Append-Only Logging)
在分布式系统或日志收集场景中,如果要在文件末尾新增数据:
- 传统
JSON:必须读取全档、移除结尾的]、补上逗号,、写入新数据再补回]。 - JSONL:直接在文件尾端直接 append 一个字符串与换行符
\n即可完成写入。
3. 大数据并行处理(Parallel Processing)
因为 JSONL 的每一行都是独立的 JSON,大型文件可以从任意换行符切割成若干小区块,发送给多个 CPU Core 或计算节点进行并行运算,彼此完全互不干扰。
开发者必知的 5 大 JSONL 严格格式铁律
虽然 JSONL 极具弹性,但为了确保解析器能顺利读取,官方规格(jsonlines.org)订立了 5 大格式限制:
规范详细说明
| 规范编号 | 铁律项目 | 说明与正确示范 |
|---|---|---|
| 规范 1 | 每一行必须是合法 JSON | 每一行独立拿出来都必须能被标准的 JSON.parse() 解析。 |
| 规范 2 | 绝不能有未转义的换行 | 字符串内若含有换行,必须转义写成 \n,禁用多行排版。 |
| 规范 3 | 禁用最外层符号 | 绝不可有最外层方括号 [] ,行与行之间 不可加逗号 , 。 |
| 规范 4 | UTF-8 无 BOM 编码 | 必须严格使用 UTF-8 编码,且 不应包含 BOM 头。 |
| 规范 5 | 文件默认不含空行 | 每一行皆为有效数据,唯有文件最后一行允许空换行。 |
实战解析:如何写出防御性高的 JSONL 读取代码?
在实际开发中,由于 JSONL 具有 无固定 Schema(Schema-less) 的特性,不同行的 Key 可能完全不同。写代码解析时,建议遵守以下防御性原则:
防御性代码示例(Python)
import json
def process_jsonl_file(file_path):
with open(file_path, "r", encoding="utf-8") as f:
for line_num, line in enumerate(f, 1):
# 1. 自动跳过空白行(防止空白行导致解析失败)
line = line.strip()
if not line:
continue
try:
data = json.loads(line)
# 2. 防御性取值:使用 .get() 避免 KeyError
user_id = data.get("id")
user_name = data.get("name", "Unknown")
# 3. 字段类型识别(多态数据处理)
doc_type = data.get("type", "default")
print(f"Line {line_num}: [{doc_type}] {user_id} - {user_name}")
except json.JSONDecodeError as e:
print(f"Error parsing line {line_num}: {e}")
# 执行读取
process_jsonl_file("dataset.jsonl")
关键防御技巧:使用
strip()清除首尾空白,并以.get()代替直取键值,可避免 90% 以上的运行时崩溃!
JSONL、JSON 与 CSV 的场景选择指南
看完 JSONL 的强大功能后,是不是该把所有数据都换成 JSONL 呢?答案是:看使用场景!
| 场景需求 | 推荐使用格式 | 原因说明 |
|---|---|---|
| Web 前后端 API 传输 | JSON | 浏览器原生支持度高,单次传输数据量适中。 |
| 导出数据给非技术人员/营销 | CSV | 可直接用 Excel 打开查看。 |
| AI 模型微调 (Fine-tuning) | JSONL | OpenAI / Anthropic API 官方指定训练格式。 |
| 系统海量 Log 记录 | JSONL | 写入成本低、支持无限 append 与超低内存监控。 |
| 大数据 ETL 管线 | JSONL | 方便分布式切割与并行处理。 |
只要掌握各格式的特性,在正确的场景选择正确工具,就能让你的数据处理性能大幅提升!