@cacheplane/ 部分杰森( 部分)
流出 JSON 解析器以获取不完整的输入 .
当一个AI模型,网络流,工人,或工具 调出JSON a时使用它
块一次. JSON.parse() 需要一个完整的文档。 此解析器给出
当文档仍然到达时,您要输入树,并保留节点对象
身份稳定,随着后面的块更新树.
安装
npm install @cacheplane/partial-json
运行时间和包装 :
- 节点
>=20 - 包含类型脚本声明
- 无害环境管理和CJS捆绑在一起
- 用途
@cacheplane/json-stream作为运行时间解析器内核 - 标出无副作用
30- 第二实例
import { createPartialJsonParser } from '@cacheplane/partial-json';
const parser = createPartialJsonParser();
parser.push('{"items":[{"name":"alpha","done":');
parser.push('true},{"name":"beta');
const first = parser.getByPath('/items/0/name');
const second = parser.getByPath('/items/1/name');
console.log(first);
// { type: 'string', value: 'alpha', status: 'complete', ... }
console.log(second);
// { type: 'string', value: 'beta', status: 'streaming', ... }
解析器不只因为输入结束于中键而抛出. 每个公众
节点携带 status: 'pending' | 'streaming' | 'complete',所以UI可以渲染
让节点解决.
何时使用
使用 @cacheplane/partial-json 当您需要时:
- 在模型完成前进行结构化的LLM输出.
- 在串流工具调用参数对象中监视一个字段 .
- 保存反应器、角质、固态或自定义成像器记忆器.
- 将活的剖析树转换成简单的 JS快照而不替换 没有改变的子树.
- 逐步解析严格的JSON,不使用regex修剪或修复回路.
这不是JSON修复图书馆。 无效的 JSON 仍然是错误; 已切换 JSON作为普通在建输入处理.
心理模式
剖析器会建立节点树. 节点随着更多输入的到来而变异于原地. 每个节点有:
id: 解析器一生的稳定数字身份.typeJSON节点类型.status数字 :pending, (中文(简体) ),streaming,或complete。 。 。 .parent: 父节点或null。 。 。 .key:对象属性键、数组索引,或null为根.
集装箱节点暴露儿童:
- 对象节点使用
children: Map<string, JsonNode>。 。 。 . - 使用矩阵节点
children: JsonNode[]。 。 。 .
Scalar 节点显示值 :
- 字符串节点显示部分
value在流出时. - 显示节点数
raw在流线和解析时value完成后. - 布尔和无效节点仍然存在
pending直到字面上决定.
Push-Style API (英语)
使用push-style API来进行流式UI和长生节点引用.
import {
createPartialJsonParser,
materialize,
} from '@cacheplane/partial-json';
const parser = createPartialJsonParser();
for await (const chunk of llmStream) {
const events = parser.push(chunk);
for (const event of events) {
if (event.type === 'value-updated') {
// event.node is the same object reference across future pushes.
}
}
if (parser.root) {
const snapshot = materialize(parser.root);
render(snapshot);
}
}
parser.finish();
push(chunk) 财务报告和审定财务报表 finish() 返回时 ParseEvent[]数字 :
interface ParseEvent {
type: 'node-created' | 'value-updated' | 'node-completed';
node: JsonNode;
delta?: string;
}
JSON 指针查询
getByPath() 接受JSON协议 指针路径 :
parser.getByPath(''); // root
parser.getByPath('/items/0/name'); // array index + object key
parser.getByPath('/a~1b/~0key'); // RFC 6901 escaping
缺少路径返回 null。 。 。 .
拉- 平面 API
使用拉动风格的 API , 当您想要不可移动的 parser 状态时, 如 减速器 , 撤销/重做堆栈,确定性测试,或国家机器集成.
import { create, push, finish, resolve } from '@cacheplane/partial-json';
let state = create();
state = push(state, '{"a":1');
state = push(state, ',"b":2}');
state = finish(state);
const value = resolve(state);
// { a: 1, b: 2 }
每个呼叫返回一个新的 StreamState。 。 。 .
牵引式出口还包括: StreamError 财务报告和审定财务报表 StreamErrorCode 从
@cacheplane/json-stream包括经济、社会、文化权利委员会 INVALID_SYNTAX, (中文(简体) ),
UNEXPECTED_END,以及 TRAILING_CONTENT 类别。 分会 code,不准确
错误消息文本 . UNEXPECTED_END 包括递增有效的数字前缀
例如 -, (中文(简体) ), 1.,以及 1e+; 已完成的错构语法是
INVALID_SYNTAX。 。 。 .
结构共享快照
实体化对象值保留 JSON 密钥为可自控、可写,
普通对象上可配置的数据属性,包括诸如
__proto__, (中文(简体) ), constructor,以及 toString。复制密钥时保留最后一个值,
匹配 JSON.parse。定义 JSON 密钥不会改变结果对象的
原型车 json- stream ^0.1.1 依赖性在解析时也会保留空密钥 .
materialize(node) 将解析器节点树转换为平版JavaScript值.
用一个 WeakMap 以节点身份键入缓存, 因此未更改子树返回
同一对象的参考.
const before = materialize(parser.root!);
parser.push(',"next":true');
const after = materialize(parser.root!);
这在渲染出每个动画框或每个流块时都是有用的. 比较参考文献的消费者只重新提供实际变化的子树.
保证
@cacheplane/partial-json 保证:
- 截断的有效前缀 JSON 可解析为在建输入 .
- 公共推式节点对象身份跨推相稳定.
- 节点状态使用相同的
pending | streaming | complete寿命周期为@cacheplane/partial-markdown。 。 。 . materialize()为未改变的子树保留引用.- 复制对象密钥遵循正常的 JavaScript 物质化语义 : 后相值取胜.
finish()关闭在输入端可以完成的有效后导结构, 譬如一个等待终结者的号码.- 语法错误以 parser 状态记录, 而不是由最佳效果隐藏 修理.
限制
此软件包不 :
- 修复无效的 JSON .
- 接受 JSON5 注释、 单引用字符串、 后缀等特性
逗号,未引用的对象键,
.5,或+1。 。 。 . - 在已实现输出中保留重复的对象键历史 .
- 验证应用程序级别计划.
- 通过一个解析器实例将多个顶级 JSON 文档流出 .
为每个顶级文档创建新解析器.
节点形状
interface JsonNodeBase {
readonly id: number;
readonly type: 'object' | 'array' | 'string' | 'number' | 'boolean' | 'null';
status: 'pending' | 'streaming' | 'complete';
parent: JsonNode | null;
key: string | number | null;
}
对象节点 :
interface JsonObjectNode extends JsonNodeBase {
readonly type: 'object';
children: Map<string, JsonNode>;
pendingKey: string | null;
}
阵列节点 :
interface JsonArrayNode extends JsonNodeBase {
readonly type: 'array';
children: JsonNode[];
}
斯卡尔节点 :
interface JsonStringNode extends JsonNodeBase {
readonly type: 'string';
value: string;
}
interface JsonNumberNode extends JsonNodeBase {
readonly type: 'number';
raw: string;
value: number | null;
}
interface JsonBooleanNode extends JsonNodeBase {
readonly type: 'boolean';
value: boolean;
}
interface JsonNullNode extends JsonNodeBase {
readonly type: 'null';
}
类型警卫
import {
isObjectNode,
isArrayNode,
isStringNode,
isNumberNode,
isBoolNode,
isNullNode,
isComplete,
} from '@cacheplane/partial-json';
const node = parser.getByPath('/title');
if (node && isStringNode(node) && isComplete(node)) {
console.log(node.value);
}
常见模式
流化反应
const parser = createPartialJsonParser();
for await (const chunk of llmStream) {
parser.push(chunk);
render(parser.root);
}
parser.finish();
监视一个特定字段
parser.push(chunk);
const status = parser.getByPath('/result/status');
if (status?.status === 'complete' && status.type === 'string') {
console.log('final status:', status.value);
}
读取部分字符串内容
const title = parser.getByPath('/title');
if (title?.type === 'string') {
renderTitle(title.value, { final: title.status === 'complete' });
}
检测文档结束
parser.finish();
if (parser.root?.status === 'complete') {
const value = materialize(parser.root);
}
解决问题
parser.root 实值 null。 。 。 .
尚未创建根节点 。 先按一个非白空间块.
一个数字 value: null。 。 。 .
号码还在流 使用 raw 用于显示,或等待到
status === 'complete'。 。 。 .
布尔或无效节点是 pending。 。 。 .
文字尚未解决。 譬如说, tr 可能会变成 true。 。 。 .
resolve(state) 返回时 undefined。 。 。 .
牵引式状态目前不包含完全可解的值.
打电话 finish() 当流结束并检查 state.error。 。 。 .
无效的 JSON 产生错误 . 这是预期的。 剖析器可以容忍截取,而不是不正确的语法.
API 参考
// Push-style
createPartialJsonParser(): PartialJsonParser
interface PartialJsonParser {
push(chunk: string): ParseEvent[];
finish(): ParseEvent[];
readonly root: JsonNode | null;
getByPath(path: string): JsonNode | null;
}
materialize(node: JsonNode): unknown;
// Pull-style
create(): StreamState;
push(state: StreamState, chunk: string): StreamState;
finish(state: StreamState): StreamState;
resolve(state: StreamState): JsonValue | undefined;
// Type guards
isObjectNode(node): node is JsonObjectNode;
isArrayNode(node): node is JsonArrayNode;
isStringNode(node): node is JsonStringNode;
isNumberNode(node): node is JsonNumberNode;
isBoolNode(node): node is JsonBooleanNode;
isNullNode(node): node is JsonNullNode;
isComplete(node): boolean;
导出类型 :
JsonNode, JsonValue, StreamStatus, StreamState, StreamError, StreamErrorCode, ParseEvent,
JsonObjectNode, JsonArrayNode, JsonStringNode, JsonNumberNode,
JsonBooleanNode, JsonNullNode, JsonNodeType,
AstNode, ObjectNode, ArrayNode, StringNode, NumberNode, BoolNode, NullNode
更改日志
见 CHANGELOG.md。 。 。 .
许可证
麻省理工学院