JSON Lines(JSONL)⇔ JSON 数组 互相转换

在每行一个 JSON 对象的 JSON Lines 格式与普通 JSON 数组之间互相转换,方便查看机器学习数据集和日志输出。

使用提示

  • JSON Lines(JSONL)是每行排列一个独立 JSON 对象的格式,广泛用于 OpenAI 微调数据集以及 Elasticsearch/Logstash 的日志输出等场景。
  • 在"JSONL → JSON 数组"模式下,每一行都必须是可单独解析的 JSON 对象,空行会被自动跳过。
  • 在"JSON 数组 → JSONL"模式下,整个输入必须是一个 JSON 数组(`[ ... ]`),数组中的每个元素会作为一行 JSONL 输出。
  • 将大型日志文件从 JSONL 转换为 JSON 数组后,用 `jq` 命令或各编程语言的标准 JSON 数组解析器处理起来会更加方便。

常见问题

JSON 数组会用 `[ {...}, {...} ]` 这样的形式把整体包裹成一个数组,如果不解析整体就无法访问单个元素。而 JSON Lines 是每行排列一个独立的 JSON 对象,可以逐行进行流式处理,因此更适合对超大日志文件或机器学习数据集进行逐条处理。

常见于 OpenAI 及其他机器学习平台的微调数据集、Elasticsearch、Logstash 等日志采集工具的输出格式,以及需要逐条独立读写的大规模数据流式处理场景。

在"JSONL → JSON 数组"模式下,每一行都必须是独立有效的 JSON,哪怕只有一行存在语法错误,也会显示包含该行号的错误信息。在"JSON 数组 → JSONL"模式下,整个输入必须是数组格式(以 `[` 开头、以 `]` 结尾)。

转换为 JSON 数组的结果可以直接用 `jq` 命令或各编程语言的标准 JSON 解析器处理。反之,转换为 JSONL 的结果与 `jq -c`、`grep`、`awk` 等按行处理的工具契合度很高,便于纳入日志分析流水线。
ツールくん

闲话 ― 为什么会诞生"一行一条记录"这种格式

JSON Lines(也称 JSONL)这种格式诞生的背景,是因为普通的 JSON 数组存在一个限制:在把整体读入内存并解析完毕之前,无法取出哪怕一条中间数据。如果试图用 JSON 数组处理多达数百万行的日志数据或机器学习训练数据集,就必须把整个文件展开到内存中,对于超大文件来说,这会带来内存不足和解析耗时激增的问题。

JSON Lines 用"一行 = 一个完整的 JSON 对象"这样简单的约束解决了这个问题。由于可以一边逐行读取文件一边随即解析,无需把整个文件读入内存,因此与流式处理、并行处理非常契合。这种设计理念也与 Unix 系统传统的"一行一条记录"文本处理文化(`grep`、`awk`、`sed` 等命令都按行工作)高度亲和,可以直接嵌入现有的命令行工具链,这在实用层面也是很大的优势。

如今它已被广泛采用为 AI、机器学习领域的数据集分发格式,大语言模型的训练数据以及用于微调的提示/回复对,以 JSON Lines 格式分发的情况已相当普遍。