> ## Documentation Index
> Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JSONL

> 使用 Bun 内置的流式解析器解析换行分隔的 JSON（JSONL）

Bun 内置支持解析 [JSONL](https://jsonlines.org/)（换行分隔的 JSON），每一行都是一个独立的 JSON 值。该解析器使用 JavaScriptCore 优化的 JSON 解析器在 C++ 中实现，支持流式场景。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
const results = Bun.JSONL.parse('{"name":"Alice"}\n{"name":"Bob"}\n');
// [{ name: "Alice" }, { name: "Bob" }]
```

***

## `Bun.JSONL.parse()`

解析完整的 JSONL 输入并返回所有解析值的数组。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
import { JSONL } from "bun";

const input = '{"id":1,"name":"Alice"}\n{"id":2,"name":"Bob"}\n{"id":3,"name":"Charlie"}\n';
const records = JSONL.parse(input);
console.log(records);
// [
//   { id: 1, name: "Alice" },
//   { id: 2, name: "Bob" },
//   { id: 3, name: "Charlie" }
// ]
```

输入可以是字符串或 `Uint8Array`：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
const buffer = new TextEncoder().encode('{"a":1}\n{"b":2}\n');
const results = Bun.JSONL.parse(buffer);
// [{ a: 1 }, { b: 2 }]
```

当传入 `Uint8Array` 时，缓冲区开头的 UTF-8 BOM 会被自动跳过。

### 错误处理

如果输入包含无效 JSON，`Bun.JSONL.parse()` 会抛出 `SyntaxError`：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
try {
  Bun.JSONL.parse('{"valid":true}\n{invalid}\n');
} catch (error) {
  console.error(error); // SyntaxError: Failed to parse JSONL
}
```

***

## `Bun.JSONL.parseChunk()`

对于流式场景，`parseChunk` 尽可能从输入中解析完整值并报告解析进度。当数据逐步接收（例如网络流）时，知道从何处继续解析很有用。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
const chunk = '{"id":1}\n{"id":2}\n{"id":3';

const result = Bun.JSONL.parseChunk(chunk);
console.log(result.values); // [{ id: 1 }, { id: 2 }]
console.log(result.read); // 17 — 已消费字符数
console.log(result.done); // false — 仍有不完整的值
console.log(result.error); // null — 无解析错误
```

### 返回值

`parseChunk` 返回一个包含四个属性的对象：

| 属性       | 类型                    | 说明                            |
| -------- | --------------------- | ----------------------------- |
| `values` | `any[]`               | 成功解析的 JSON 值数组                |
| `read`   | `number`              | 消耗的字节数（`Uint8Array`）或字符数（字符串） |
| `done`   | `boolean`             | 如果整个输入被完全消费且无剩余数据，值为 `true`   |
| `error`  | `SyntaxError \| null` | 解析错误，若无错误则为 `null`            |

### 流式示例

使用 `read` 截取已消耗输入，剩余部分继续传递：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
let buffer = "";

async function processStream(stream: ReadableStream<string>) {
  for await (const chunk of stream) {
    buffer += chunk;
    const result = Bun.JSONL.parseChunk(buffer);

    for (const value of result.values) {
      handleRecord(value);
    }

    // 保留未消费部分
    buffer = buffer.slice(result.read);
  }

  // 处理剩余数据
  if (buffer.length > 0) {
    const final = Bun.JSONL.parseChunk(buffer);
    for (const value of final.values) {
      handleRecord(value);
    }
    if (final.error) {
      console.error("最终数据块解析错误:", final.error.message);
    }
  }
}
```

### 使用 `Uint8Array` 的字节偏移

当输入为 `Uint8Array` 时，可以传入可选的起始和结束字节偏移：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
const buf = new TextEncoder().encode('{"a":1}\n{"b":2}\n{"c":3}\n');

// 从字节 8 开始解析
const result = Bun.JSONL.parseChunk(buf, 8);
console.log(result.values); // [{ b: 2 }, { c: 3 }]
console.log(result.read); // 24

// 解析特定范围
const partial = Bun.JSONL.parseChunk(buf, 0, 8);
console.log(partial.values); // [{ a: 1 }]
```

The `read` value is always a byte offset into the original buffer. Use it with `TypedArray.subarray()` for zero-copy streaming:

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
let buf = new Uint8Array(0);

async function processBinaryStream(stream: ReadableStream<Uint8Array>) {
  for await (const chunk of stream) {
    // 追加 chunk 到缓冲区
    const newBuf = new Uint8Array(buf.length + chunk.length);
    newBuf.set(buf);
    newBuf.set(chunk, buf.length);
    buf = newBuf;

    const result = Bun.JSONL.parseChunk(buf);

    for (const value of result.values) {
      handleRecord(value);
    }

    // 保留未消费的字节
    buf = buf.slice(result.read);
  }
}
```

### 错误恢复

与 `parse()` 不同，`parseChunk()` 遇到无效 JSON 不抛出异常，而是通过返回的 `error` 属性提供错误信息，同时返回错误前成功解析的所有值：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
const input = '{"a":1}\n{invalid}\n{"b":2}\n';
const result = Bun.JSONL.parseChunk(input);

console.log(result.values); // [{ a: 1 }] — 错误前解析的值
console.log(result.error); // SyntaxError
console.log(result.read); // 7 — 最后成功解析的位置
```

***

## 支持的值类型

每一行可以是任意有效的 JSON 值，而不仅限于对象：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
const input = '42\n"hello"\ntrue\nnull\n[1,2,3]\n{"key":"value"}\n';
const values = Bun.JSONL.parse(input);
// [42, "hello", true, null, [1, 2, 3], { key: "value" }]
```

***

## 性能说明

* **ASCII 快速通道**：纯 ASCII 输入直接解析，无需复制，使用零分配的 `StringView`。
* **UTF-8 支持**：非 ASCII 的 `Uint8Array` 输入通过 SIMD 加速转换为 UTF-16。
* **BOM 处理**：`Uint8Array` 开头的 UTF-8 BOM（`0xEF 0xBB 0xBF`）自动跳过。
* **预构建对象形状**：`parseChunk` 返回的结果对象使用缓存结构，提高属性访问速度。
