snack4 - Json 流式读取与结构修复
2026年3月18日 上午10:41:14
在处理 LLM(大语言模型) 实时输出或 NDJSON(服务端推送流) 时,开发者经常面临两个挑战:一是数据以“流”的形式分批到达;二是数据流可能由于中断或截断导致 JSON 结构不完整。
snack4 的 JsonReader 针对这些场景深度优化,提供了高效的流式读取与智能结构修复能力。
1、流式读取
核心场景:
- LLM 分块输出:大语言模型分块输出 JSON 数据
- NDJSON 数据:换行分隔的 JSON 格式(或没有换行),如
{"a":"a"}{"a":"a","b":"b"} - 大型 JSON 文件:避免一次性加载到内存
接口:
JsonReader reader = new JsonReader(inputStream); // or json
// 读取下一个 JSON 块
ONode node = reader.readNext();
// 使用迭代器遍历(推荐)
for (ONode item : reader.iterableNext()) {
// 处理每个 JSON
}
// 读取最后一个 JSON 块
ONode last = reader.readLast();
应用示例:
String ndjson = "{\"name\":\"Alice\"}\n{\"name\":\"Bob\"}\n{\"name\":\"Charlie\"}";
// 迭代器方式(推荐)
for (ONode item : new JsonReader(ndjson).iterableNext()) {
System.out.println(item.get("name").val());
}
// 输出: Alice, Bob, Charlie
// 逐个读取
JsonReader reader = new JsonReader(ndjson);
ONode node;
while ((node = reader.readNext()) != null) {
System.out.println(node.val());
}
2、结构修复
启用方式
Options opts = Options.of(Feature.Read_AutoRepair);
JsonReader reader = new JsonReader(json, opts);
修复示例
| 输入 | 修复结果 |
|---|---|
{"flag": tru | {"flag": true} |
{"a":{"b":{"c":1 | {"a":{"b":{"c":1}}} |
[1,2,3, | [1,2,3] |
{"a": | {"a":null} |
代码示例
// LLM 输出不完整的 JSON
String incomplete = "{\"flag\": tru"; // true 没写完
Options opts = Options.of(Feature.Read_AutoRepair);
JsonReader reader = new JsonReader(incomplete, opts);
ONode node = reader.readLast();
System.out.println(node.toJson());
// 输出: {"flag":null}
// 深层嵌套未闭合
String broken = "{\"data\":{\"items\":[";
Options opts2 = Options.of(Feature.Read_AutoRepair);
JsonReader reader2 = new JsonReader(broken, opts2);
ONode node2 = reader2.readLast();
System.out.println(node2.toJson());
// 输出: {"data":{"items":[]}}
3、组合使用
流式解析 + 自动修复,处理复杂的 LLM 混合输出:
String mixed = "{\"name\":\"test\"}{\"name\":\"test\",\"broken\": tru";
Options opts = Options.of(Feature.Read_AutoRepair);
JsonReader reader = new JsonReader(mixed, opts);
for (ONode node : reader.iterableNext()) {
System.out.println(node.toJson());
}
// 输出: {"name":"test"}
// {"broken":null,"ok":"yes"}