是否有用于异步 JSON 解析器的 Node 模块,它不会将整个 JSON 字符串加载到内存中?
Posted
技术标签:
【中文标题】是否有用于异步 JSON 解析器的 Node 模块,它不会将整个 JSON 字符串加载到内存中?【英文标题】:Is there a Node module for an async JSON parser that does not load the entire JSON string into memory? 【发布时间】:2014-12-12 16:54:01 【问题描述】:我意识到there are a ton of Node modules that provide an async API for parsing JSON,但他们中的许多人似乎读取整个文件或流到内存中,构造一个巨大的字符串,然后将其传递给JSON.parse()
。这就是the second answer to "How to parse JSON using NodeJS?" suggests 所做的,也正是jsonfile module 所做的。
构造一个巨大的字符串正是我想要避免的。我想要这样的 API:
parseJsonFile(pathToJsonFile): Promise
返回的Promise
解析为解析后的 JSON 对象。此实现应使用恒定数量的内存。我对在解析各种片段时广播事件的任何类似 SAX 的东西不感兴趣:只是最终结果。
我认为jsonparse 可以做我想做的事(它显然包含了不使用JSON.parse()
解析JSON 的逻辑),但是README.md
中没有简单的例子,one file in the examples directory 似乎过于复杂。
【问题讨论】:
【参考方案1】:我编写了一个模块来执行此操作:BFJ(Big-Friendly JSON)。它导出了一堆在不同抽象级别上运行的函数,但它们的核心都是异步和流式传输。
***别是两个用于读取和写入文件系统的函数,bfj.read
和 bfj.write
。他们每个人都返回一个承诺,所以你这样称呼他们:
var bfj = require('bfj');
// Asynchronously read from a JSON file on disk
bfj.read(path)
.then(data =>
// :)
)
.catch(error =>
// :(
);
// Asynchronously write to a JSON file on disk
bfj.write(path, data)
.then(data =>
// :)
)
.catch(error =>
// :(
);
在这一层还有一个用于将数据序列化为 JSON 字符串的函数,称为 bfj.stringify
:
// Asynchronously serialize data to a JSON string
bfj.stringify(data)
.then(json =>
// :)
)
.catch(error =>
// :(
);
下面是两个更通用的读取和写入流的函数,bfj.parse
和 bfj.streamify
。这些作为更高级别函数的基础,但您也可以直接调用它们:
// Asynchronously parse JSON from a readable stream
bfj.parse(readableStream).
.then(data =>
// :)
)
.catch(error =>
// :(
);
// Asynchronously serialize data to a writable stream of JSON
bfj.streamify(data).
.pipe(writableStream);
在最低级别,有两个函数类似于 SAX 解析器/序列化器,bfj.walk
和 bfj.eventify
。您不太可能想直接调用它们,它们只是更高级别实现的核心。
它是开源的并获得 MIT 许可。欲了解更多信息,请查看the readme。
【讨论】:
Phil Booth:BFJ 的 API 看起来很棒!我质疑的一件看似微不足道的事情是check-types
的价值。 BFJ 只对模块进行了 13 次调用,其中一半似乎可以用typeof
检查替换。我不确定这是否值得额外的 20K。此外,check-types
的发布版本似乎附带了src/check-types.min.js
,这将节省一些加载时间,但package.json
中的"main"
仍然指向src/check-types.js
,因此您最终会加载更大的版本,无论如何。【参考方案2】:
jsonparse 是一个流式 json 解析器,示例代码已经展示了使用 Node 流的最低限度。
-
将
client.request()
更改为fs.createReadStream()
。
在文件读取流上设置on('data')
侦听器,类似于示例中on('response')
中的内容。
【讨论】:
jsonparse 缺乏文档让我感到不安。examples
中只有一个文件,而且它甚至看起来都不起作用,因为有 require('./colors')
之类的东西,但没有 colors.js
文件。以上是关于是否有用于异步 JSON 解析器的 Node 模块,它不会将整个 JSON 字符串加载到内存中?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 json 解析器的 boost property_tree 创建空数组节点