On this page
@std/json
Overview Jump to heading
Utilities for parsing streaming JSON data.
import { JsonStringifyStream } from "@std/json";
import { assertEquals } from "@std/assert";
const stream = ReadableStream.from([{ foo: "bar" }, { baz: 100 }])
.pipeThrough(new JsonStringifyStream());
assertEquals(await Array.fromAsync(stream), [
`{"foo":"bar"}\n`,
`{"baz":100}\n`
]);
Add to your project Jump to heading
deno add jsr:@std/json
See all symbols in @std/json on
什么是 JSON 流? Jump to heading
JSON 流是一种处理 JSON 数据的连续流技术,而非一次性将整个数据集加载到内存中。这对于处理大型 JSON 文件或实时数据流尤其有用。
为什么使用 @std/json? Jump to heading
用于流式读写 JSON,处理大型数据集时无需将所有数据加载到内存中。
示例 Jump to heading
解析连续拼接的 JSON(多个 JSON 值紧密连接)
import {
ConcatenatedJsonParseStream,
} from "@std/json/concatenated-json-parse-stream";
// 流中包含两个不带分隔符的连续 JSON 文档。
const input = ReadableStream.from([
'{"a":1}{',
'"b":2}',
]);
const parsed = input.pipeThrough(new ConcatenatedJsonParseStream());
console.log(await Array.fromAsync(parsed)); // [{ a: 1 }, { b: 2 }]
从对象生成 NDJSON(JSON 行格式)
import { JsonStringifyStream } from "@std/json/stringify-stream";
const data = [{ id: 1 }, { id: 2 }, { id: 3 }];
// 在每个 JSON 值后添加换行符,形成 NDJSON
const ndjson = ReadableStream
.from(data)
.pipeThrough(new JsonStringifyStream({ suffix: "\n" }));
// 发送到接受 application/x-ndjson 的服务器
await fetch("/ingest", {
method: "POST",
headers: { "content-type": "application/x-ndjson" },
body: ndjson,
});
安全地消费 NDJSON(处理跨块边界的换行)
import { JsonParseStream } from "@std/json/parse-stream";
// 按换行符拆分,即使一行跨越多个块
function lineSplitter() {
let buffer = "";
return new TransformStream<string, string>({
transform(chunk, controller) {
buffer += chunk;
const lines = buffer.split(/\r?\n/);
buffer = lines.pop() ?? ""; // 保留最后不完整的行
for (const line of lines) if (line) controller.enqueue(line);
},
flush(controller) {
if (buffer) controller.enqueue(buffer);
},
});
}
const res = await fetch("/stream.ndjson");
const values = res.body!
.pipeThrough(new TextDecoderStream())
.pipeThrough(lineSplitter())
.pipeThrough(new JsonParseStream());
for await (const obj of values) {
// 按到达顺序处理每个 JSON 对象
console.log(obj);
}
动态转换 JSON 流
import { JsonParseStream } from "@std/json/parse-stream";
import { JsonStringifyStream } from "@std/json/stringify-stream";
// 输入对象 -> 映射 -> 输出 NDJSON
function mapStream<T, U>(map: (t: T) => U) {
return new TransformStream<T, U>({ transform: (t, c) => c.enqueue(map(t)) });
}
const response = await fetch("/objects.jsonl");
const uppercased = response.body!
.pipeThrough(new TextDecoderStream())
.pipeThrough(lineSplitter()) // 来自前面示例
.pipeThrough(new JsonParseStream<{ name: string }>())
.pipeThrough(mapStream((o) => ({ name: o.name.toUpperCase() })))
.pipeThrough(new JsonStringifyStream({ suffix: "\n" }));
// 管道输出到另一个请求、文件或进一步处理
await fetch("/store", { method: "POST", body: uppercased });
提示 Jump to heading
- 使用
JsonStringifyStream/JsonParseStream可与fetch()和文件流高效组合。 - 明确编码边界 —— 使用 UTF-8 和
TextEncoder/TextDecoder作为桥接。 - 生成 NDJSON 时使用
JsonStringifyStream({ suffix: "\n" }),消费时先拆分行再用JsonParseStream。 - 输入为紧凑连续的 JSON 值流时,使用
ConcatenatedJsonParseStream。