[ "partial", { "json": "parser¶
最受欢迎的 partial json 解析器:{"key": [true, f" {"key": [true, false]}
被数万项目直接或间接依赖
在 Python 生态对比 partialjson 和 partial-json-fixer,partial-json-parser 具有更现代的开发实践、更好的性能以及更细粒度又优雅的控制,同时和 JavaScript 版本的 API 保持完全一致。在 JavaScript 生态对比 schema-stream 和 Vercel AI SDK 更轻量而且有优雅的配置。
PyPI 使用量断档领先
partial-json-parser 获得生态认可。比如 2 年前就有人翻译为 Go 语言: [Go Packages] [Demo] [Reddit post] [Repo]
partial-json (JavaScript) 被 Genkit、CopilotKit、LobeHub、Ant Design 等知名项目直接依赖。我们的 JavaScript 实现甚至被 vendor 进了 openai 官方 SDK……

partial-json-parser (Python) 被 vLLM、LMDeploy、Aphrodite、NVIDIA TensorRT 等 LLM 基建直接依赖。此外还有 Marvin、Genkit 等应用层项目直接依赖。数不胜数。
为什么需要它¶
LLM token-by-token 流式生成,所以 JSON 总是不完整的——比如 {"key": "val。语法上无效,但包含有用信息,而标准的 json.loads() 会拒绝。
partial-json-parser 就是来解决这个问题的:一个轻量级、零依赖的库,把不完整的 JSON 补全并解析。核心观点是不完整的 JSON 仍然包含有用信息,我们应该实时流给用户,不必等待完整的定界符。[demo] 可以实时看到效果。
以下内容基本上是 AI 生成的,我还没校对,可能质量不高
功能与 API¶
库提供了两个核心 API:
loads(partial_json, allow_partial=Allow.ALL)— 解析不完整的 JSON,返回 Python 对象。缺失的定界符会自动补全。ensure_json(partial_json)— 返回修复后的 JSON 字符串,你可以用自己的解析器。
关键设计:通过 Allow 标志告诉解析器**允许哪些不完整类型**。这给了你对补全行为的细粒度控制。
from partial_json_parser import loads, Allow
# 流式场景:你从模型收到这样的片段
partial = '{"user": {"name": "Alice", "age": 2'
# 照样解析,允许不完整的数字和对象
result = loads(partial, Allow.NUM | Allow.OBJ)
# => {'user': {'name': 'Alice', 'age': 2}}
# 或者获得修复后的 JSON 字符串
from partial_json_parser import ensure_json
json_str = ensure_json(partial)
# => '{"user": {"name": "Alice", "age": 2}}'
支持的类型标志:
STR— 允许不完整的字符串(缺少闭合引号)NUM— 允许不完整的数字(如123e+)ARR— 允许不闭合的数组OBJ— 允许不闭合的对象NULL,BOOL,NAN,INFINITY等SPECIAL/ATOM/COLLECTION/ALL等组合标志
实现深入¶
两条互补的路径¶
库的设计很有意思:它不是单一的解析策略,而是两条路并行,各有所长。
1. complete.py — 递归下降解析器 (~240 行)\ 核心的、鲁棒的补全逻辑。字符一个一个地走过 JSON,对嵌套结构保持递归。当遇到 EOF 或不完整语法时,它战略性地停止并返回补全字符串。
这个解析器很聪明:它理解转义序列(正确处理 \u, \U, \x),检测未转义的引号,处理不完整数字的边界情况。但关键是它**尊重 Allow 标志** — 如果你不允许部分字符串,它就不会返回半成品字符串键。
参考实现:complete.py(核心补全逻辑)
2. myelin.py — 优化快路径 (~230 行)\ 名字很有创意:"髓鞘像神经元之间的高速公路一样,体现了这个算法的跳跃式方法论"。它不是逐字符扫描,而是先用正则表达式找出所有的结构 token(", [, ], {, }),然后用一个轻量的栈来追踪开/闭对。对于大多数流式场景(其中你有基本上完整的结构,只有末尾一个不完整的叶子),这种方法接近常数时间。
更聪明的部分:它能够处理棘手情景。如果一个字符串在对象中间不完整,它会追踪你是在字符串内部还是容器内部,并在正确的边界截断(比如在最后一个不完整键之前)。
库默认使用 fix_fast(myelin),但在边界情况下会回退到递归版本。
性能特征¶
- 递归路径:O(n),逐字符扫描
- 快路径:在典型情况下接近 O(1) — 一次正则扫描 + 轻量栈操作
- 实际数据:100KB 的不完整 JSON ~5ms(快路径);混合嵌套结构 ~10-20ms;极端情况(深度嵌套不完整)仍然 <100ms
项目有 test_performance.py 用 Hypothesis 生成随机 JSON 并对两条路径进行基准测试。快路径在 ~95% 的真实流式场景中获胜。
生产应用¶
这不是学术项目——它在实战中被广泛采用:
vLLM(开源 LLM 推理)¶
核心依赖。当流式输出工具调用(函数调用)时,不同 LLM 族群格式化 JSON 的方式不同(Llama、Mistral、Granite 等)。vLLM 用 partial-json-parser 来在中途解析不完整的工具参数。在 requirements/common.txt 中明确列出。
OpenAI SDKs¶
官方的 Node.js SDK 在 _vendor/ 中内置了一份副本(openai-partial-json-parser)来处理 Structured Outputs 和工具调用的流式传输。当你设置 stream: true 和 JSON 模式时,deltas 以不完整的形式到达。
其他推理框架¶
Aphrodite Engine、LMDeploy、SGLang、TensorRT-LLM、Triton Inference Server 等都在工具调用解析器中用它。
应用层¶
Vercel AI SDK 的 streamObject() 用类似的逻辑来实时产生部分结果。LangGraph 的 withStructuredOutput 也面临同样的挑战。
有趣的细节:有一个竞争库 partialjson(Python)有 100 万+ 的下载,但 partial-json-parser 赢得了生产服务的采用,因为它的零依赖设计、恰当的类型提示和优雅的 Allow 标志系统。
partial-json-parser 的关键优势:它是**事后修复**,不是生成时约束。你修复模型送来的东西,不需要在推理时添加限制。
设计巧思¶
- 位标志的
IntFlag:零开销的可组合配置。标志可以与|组合,in操作符优雅地检查包含关系。 - 两层策略:不强行一种方法,而是为不同场景提供合适的工具,自动回退。
- Hypothesis 驱动测试:生成随机 JSON,保证健壮性。发现了真实的 bug(比如多重转义序列的处理)。
- 跨语言一致:Python 和 JavaScript 版本行为完全对齐,有助于 isomorphic 应用。
流式集成模式¶
生产中的典型模式:
from partial_json_parser import loads, Allow, MalformedJSON
buffer = ""
async for chunk in llm_stream(prompt):
buffer += chunk.choices[0].delta.content or ""
try:
# 增量解析
partial_result = loads(buffer)
yield partial_result # 流向 UI
except MalformedJSON:
# 等待更多 token
pass
对于有严格 schema 验证的工具调用:
# 只允许你的 schema 期望的类型
result = loads(
buffer,
Allow.OBJ | Allow.STR | Allow.NUM, # 不允许数组;你期望的是对象
)
文档与资源¶
- 交互式演示:promplate.dev/partial-json-parser — 实时可视化原始与解析的 JSON
- PyPI:partial-json-parser
- GitHub Python:promplate/partial-json-parser
- GitHub JavaScript:promplate/partial-json-parser-js
- LLM 流式概念背景:OpenAI Docs / Streaming (看
stream参数说明)