什么是 jsonriver
jsonriver 是一个基于标准的轻量级流式 JSON 解析库。它以增量方式解析传入的 JSON 数据流,例如来自网络请求或语言模型的数据,并返回一系列逐渐完整的值。这种流式解析方式在处理大型或实时数据时尤其高效。
试想以下 JSON 数据:
{"name": "Alex", "keys": [1, 20, 300]}
如果将此数据逐字节地传递给 jsonriver,它将产生以下值序列:
{}
{"name": ""}
{"name": "A"}
{"name": "Al"}
{"name": "Ale"}
{"name": "Alex"}
{"name": "Alex", "keys": []}
{"name": "Alex", "keys": [1]}
{"name": "Alex", "keys": [1, 20]}
{"name": "Alex", "keys": [1, 20, 300]}
jsonriver 的 parse 函数返回的最终值与对整个字符串调用 JSON.parse 的结果相同。该函数已通过 JSONTestSuite 测试,在正确、错误和歧义情况下均与 JSON.parse 的行为保持一致。
在处理无效输入时,jsonriver 也与 JSON.parse 的行为一致。如果输入流无法解析为有效 JSON 文档的开头,解析过程会停止并抛出错误。更准确地说,AsyncIterable 对象上 next 方法返回的 Promise 会被 reject 并抛出错误。如果输入流过早关闭,也会出现同样的情况。
jsonriver 体积小、速度快、无依赖项,并且仅使用 JavaScript 的标准特性,因此可在任何 JS 环境中运行。作为一款开源项目,目前在 Github 上通过 MIT 协议开源,已经获得超过 1k 的 star,是一个值得尝试的前端工具。
如何使用 jsonriver
下面是 jsonriver 的基本使用示例:
// 更丰富的示例在 examples/fetch.js,在线演示见 https://rictic.github.io/jsonriver/
import {parse} from 'jsonriver';
const response = await fetch(`https://jsonplaceholder.typicode.com/posts`);
const postsStream = parse(response.body.pipeThrough(new TextDecoderStream()));
for await (const posts of postsStream) {
console.log(posts);
}
parse 函数还可以接收一个 options 参数作为其第二个参数。如果 options 对象包含 completeCallback 函数,则每次解析器处理完一个值后,都会调用该函数,例如: completeCallback(value, path)。
严格来说,当 jsonriver 不再修改某个值,也不会将其替换为其他值时,该值即被视为已完成,除非对象中存在重复键。jsonriver 对 completeCallback 的调用是确定性的,与传入的 JSON 流的格式无关。
例如,解析以下 JSON 时:
{"name": "Alex", "keys": [1, 20, 300]}
completeCallback 将被调用六次,每次调用的值如下:
'Alex'
1
20
300
[1, 20, 300]
{"name": "Alex", "keys": [1, 20, 300]}
下面示例使用 WeakMap 以一种简单且开销低的方式来处理补全信息:
const completed = new WeakMap();
function markCompleted(value) {
if (value && typeof value === 'object') {
completed.set(value, true);
}
}
function isComplete(value) {
if (value && typeof value === 'object') {
return completed.has(value);
}
}
const values = parse(stream, {completeCallback: markCompleted});
for await (const value of values) {
// render 函数可以使用 isComplete 函数来检查对象或数组是否已完成
render(value, isComplete);
}
参考资料
更多前端技术和开源工具讨论,欢迎访问云栈社区。