NDJSON 完整指南:换行分隔 JSON 详解

关于换行分隔 JSON (NDJSON) 的全面指南。学习规范、MIME 类型、如何在 Python、Node.js 和命令行中读写 NDJSON、在流式 HTTP API 中使用它,以及了解它与 JSONL 的关系。

最后更新:2026年2月

什么是 NDJSON?

NDJSON 全称 Newline Delimited JSON(换行分隔 JSON)。它是一种基于文本的数据格式,每一行包含一个有效的 JSON 值,由换行符 (\n) 分隔。该格式专为流式处理和处理大型数据集而设计,无需将整个文件加载到内存中。与将所有内容包装在单个数组或对象中的标准 JSON 文件不同,NDJSON 允许您逐条读取、写入和处理记录。

NDJSON 规范托管在 github.com/ndjson/ndjson-spec。它的创建是为了正式化在日志传输、数据管道和 HTTP 流式 API 中已经普遍使用的模式。每一行都是自包含的:如果一行包含无效的 JSON,其他行仍然可以被成功解析。这使得 NDJSON 具有容错性,非常适合应用日志、事件流和增量数据导出等仅追加工作流。

NDJSON 示例(3 条记录)
{"id":1,"event":"page_view","url":"/home"}
{"id":2,"event":"click","url":"/pricing"}
{"id":3,"event":"signup","url":"/register"}

NDJSON 规范

github.com/ndjson/ndjson-spec 上的官方 NDJSON 规范故意保持简洁。它定义了一种在单个文本流中序列化多个 JSON 值的简单约定。核心规则很直接:

规范明确避免向格式添加头信息、元数据或 Schema 信息。这使 NDJSON 尽可能简单,并与标准 Unix 文本处理工具兼容。每一行允许任何有效的 JSON 值,尽管在实践中大多数 NDJSON 文件包含具有一组一致键的 JSON 对象。

  • 每一行必须包含恰好一个有效的 JSON 值(对象、数组、字符串、数字、布尔值或 null)。
  • 行由换行符 '\n' (U+000A) 分隔。回车符 '\r' (U+000D) 可以出现在 '\n' 之前,但不是必需的。
  • 最后一个 JSON 值之后的尾随换行符是允许的但不是必需的。
  • 每个 JSON 值内部不得包含未转义的换行符。

由于规则最少,NDJSON 可以从任何具有 JSON 序列化器的编程语言轻松生成。只需序列化每条记录,追加一个换行符,然后写入输出。无需闭合括号、无需尾随逗号、无需包围数组结构。

NDJSON vs JSON vs JSONL

NDJSON、JSON 和 JSONL 各有不同的结构。标准 JSON 编码单个值(通常是数组或对象)。JSONL 和 NDJSON 都是每行存储一个 JSON 值,并且它们在功能上是完全相同的。下表突出了这三种格式之间的主要差异。

特性JSONJSONLNDJSON
全称JavaScript Object NotationJSON LinesNewline Delimited JSON
文件扩展名.json.jsonl.ndjson
MIME 类型application/jsonapplication/jsonl(非官方)application/x-ndjson
规范RFC 8259(IETF 标准)jsonlines.org(社区)github.com/ndjson/ndjson-spec(社区)
行分隔符不适用(单个值)\n(换行符)\n(换行符)
尾随换行符不适用推荐可选
适合流式处理否(必须解析整个文档)是(逐行处理)是(逐行处理)

NDJSON MIME 类型:application/x-ndjson

NDJSON 的注册 MIME 类型是 application/x-ndjson。此内容类型用于 HTTP 头中,表示响应体包含换行分隔的 JSON 数据。许多流式 API,包括 GitHub API、Docker Registry API 和 Elasticsearch 批量 API,都使用此 MIME 类型来传递 NDJSON 响应。

HTTP Content-Type 头
Content-Type: application/x-ndjson
# Example: curl a streaming API
curl -H "Accept: application/x-ndjson" https://api.example.com/events/stream
# Example: Express.js response
res.setHeader('Content-Type', 'application/x-ndjson');
res.write(JSON.stringify(record) + '\n');

一些 API 也接受 application/json-seq (RFC 7464) 或 text/plain 作为替代。然而,application/x-ndjson 是换行分隔 JSON 流最广泛采用的 MIME 类型。在构建流式传输 JSON 记录的新 API 时,请使用 application/x-ndjson 以获得最大兼容性。

读写 NDJSON

在任何支持 JSON 的语言中处理 NDJSON 都很简单。以下是 Python、Node.js 和命令行的实用示例。

Python 内置的 json 模块天然支持 NDJSON。从文件中读取行,使用 json.loads 解析每一行,使用 json.dumps 写入。对于大文件,这种逐行方式使用恒定的内存。

Python:读写 NDJSON
guide-ndjson-complete-guide.ndjsonGuide.readWrite.python.code

在 Node.js 中,使用 readline 模块配合 fs.createReadStream 高效解析 NDJSON 文件。流式处理一次一行,无论文件大小如何,内存使用量都保持较低。

Node.js:读写 NDJSON
import { createReadStream, writeFileSync } from 'node:fs';
import { createInterface } from 'node:readline';
// Read NDJSON
async function readNdjson(filePath) {
const records = [];
const rl = createInterface({
input: createReadStream(filePath, 'utf-8'),
crlfDelay: Infinity,
});
for await (const line of rl) {
const trimmed = line.trim();
if (trimmed) records.push(JSON.parse(trimmed));
}
return records;
}
// Write NDJSON
const data = [
{ id: 1, event: 'page_view' },
{ id: 2, event: 'click' },
];
const ndjson = data.map(r => JSON.stringify(r)).join('\n') + '\n';
writeFileSync('output.ndjson', ndjson, 'utf-8');

jq 命令行工具原生支持 NDJSON 输入。使用 --slurp 标志将所有记录收集到数组中,或不加任何标志单独处理每条记录。

命令行:使用 jq 处理 NDJSON
# Print each record (jq reads NDJSON by default)
jq '.' data.ndjson
# Filter records where event is "click"
jq 'select(.event == "click")' data.ndjson
# Extract specific fields
jq {id, url} data.ndjson
# Count total records
jq -s 'length' data.ndjson
# Convert NDJSON to a JSON array
jq -s '.' data.ndjson > data.json
# Convert a JSON array back to NDJSON
jq -c '.[]' data.json > data.ndjson

NDJSON 在 HTTP 流式 API 中的应用

NDJSON 是传递实时数据的 HTTP 流式 API 的事实标准。当服务器发送 NDJSON 响应时,客户端可以在第一条记录到达时立即开始处理,无需等待整个响应完成。这比返回大型 JSON 数组更快、更节省内存。

使用 NDJSON 流式传输的热门服务包括 Docker Registry(镜像层事件)、Elasticsearch(批量操作)、Apache CouchDB(变更订阅)以及许多现代事件驱动 API。这种模式在 Server-Sent Events 替代方案、实时日志跟踪和 Web 应用程序中的渐进式数据加载中效果很好。

Express.js NDJSON 流式服务器
import express from 'express';
const app = express();
app.get('/api/events/stream', (req, res) => {
res.setHeader('Content-Type', 'application/x-ndjson');
res.setHeader('Transfer-Encoding', 'chunked');
// Simulate streaming events
let id = 0;
const interval = setInterval(() => {
id++;
const event = {
id,
type: 'heartbeat',
timestamp: new Date().toISOString(),
};
res.write(JSON.stringify(event) + '\n');
if (id >= 100) {
clearInterval(interval);
res.end();
}
}, 100);
req.on('close', () => clearInterval(interval));
});
app.listen(3000);
浏览器:使用 Fetch 消费 NDJSON 流
async function* readNdjsonStream(url) {
const response = await fetch(url, {
headers: { 'Accept': 'application/x-ndjson' },
});
const reader = response.body
.pipeThrough(new TextDecoderStream())
.getReader();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += value;
const lines = buffer.split('\n');
buffer = lines.pop();
for (const line of lines) {
if (line.trim()) yield JSON.parse(line);
}
}
if (buffer.trim()) yield JSON.parse(buffer);
}
// Usage
for await (const event of readNdjsonStream('/api/events/stream')) {
console.log('Received:', event);
}

NDJSON 生态系统工具

越来越多的命令行工具和库原生支持 NDJSON。这些工具让您无需编写自定义代码即可过滤、转换和分析 NDJSON 数据。

jq

必备

jq 是最流行的命令行 JSON 处理器。它默认读取 NDJSON(每行一个 JSON 值),支持过滤、映射、分组和重新格式化。使用 jq -c 输出紧凑格式,使用 jq -s 将所有记录收集到数组中。

ndjson-cli

CLI

ndjson-cli 是一组 Unix 风格的 NDJSON 流操作命令:ndjson-filter、ndjson-map、ndjson-reduce、ndjson-sort 和 ndjson-join。每个命令从 stdin 读取并写入 stdout,使它们可以通过管道组合使用。

ndjson (npm)

Node.js

ndjson npm 包为 Node.js 提供流式 NDJSON 解析器和序列化器。它暴露 ndjson.parse() 和 ndjson.stringify() 转换流,可直接集成到 Node.js 流式管道中进行高吞吐量数据处理。

NDJSON 与 JSONL:互操作性

NDJSON 和 JSONL (JSON Lines) 是功能上完全相同的格式。两者都是每行存储一个 JSON 值,由换行符分隔。一个有效的 NDJSON 文件同时也是有效的 JSONL,反之亦然。您可以将 .ndjson 文件重命名为 .jsonl(或反过来),无需更改任何一个字节的内容,读取一种格式的每个工具都会读取另一种。

唯一的差异是表面的:NDJSON 来自 github.com/ndjson/ndjson-spec,使用 .ndjson 扩展名和 application/x-ndjson MIME 类型,而 JSONL 来自 jsonlines.org,使用 .jsonl 扩展名。在实践中,大多数开发者将这两个名称视为同义词。如果您的项目已经使用 JSONL,则无需迁移到 NDJSON;如果一个库说它支持 NDJSON,它也会无需任何更改地处理您的 .jsonl 文件。

JSONL vs NDJSON:详细对比

要深入了解 JSONL 和 NDJSON 的历史、规范差异和社区采用情况,请阅读我们的专门对比指南。

试试我们的免费 NDJSON/JSONL 工具

直接在浏览器中处理 NDJSON 和 JSONL 文件。所有处理均在本地完成,您的数据始终保持私密。

在线处理 NDJSON 文件

在浏览器中查看、验证和转换最大 1 GB 的 NDJSON 和 JSONL 文件。无需上传,100% 私密。

常见问题

NDJSON 格式指南 — 换行分隔 JSON 与 JSONL 详解 | jsonl.co