Skip to main content
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

你找到了你需要的东西吗?

编辑此页面
隐私政策