【问题标题】:How to read stream of JSON objects per object如何读取每个对象的 JSON 对象流
【发布时间】:2016-08-17 06:06:58
【问题描述】:

我有一个二进制应用程序,它生成一个连续的 json 对象流(不是一个 json 对象数组)。 Json 对象有时可以跨越多行(仍然是有效的 json 对象,但经过美化)。

我可以连接到这个流并阅读它而不会出现以下问题:

var child = require('child_process').spawn('binary', ['arg','arg']);

child.stdout.on('data', data => {
  console.log(data);
});

Streams 是缓冲区并在需要时发出数据事件,因此我使用 readline 模块将缓冲区解析为行,并且它适用于不支持的 Json 对象(我能够 JSON.parse() 行) '不要跨越多行。

最佳解决方案是监听返回单个 json 对象的事件,例如:

child.on('json', object => {

});

我注意到流节点文档中的 objectMode 选项,但是我得到了 Buffer 格式的流,所以我相信我无法使用它。

在 pixl-json-stream、json-stream 上查看了 npm,但在我看来,这些都不符合目的。有 clarinet-object-stream 但它需要根据事件从头开始构建 json 对象。

我无法控制 json 对象流,大多数情况下一个对象位于一行上,但是 10-20% 的时间 json 对象位于多行上(\n 作为 EOL),对象之间没有分隔符.每个新对象总是从新的一行开始。

示例流:

{ "a": "a", "b":"b" }
{ "a": "x",
  "b": "y", "c": "z"
}
{ "a": "a", "b":"b" }

必须有一个解决方案我只是错过了一些明显的东西。宁愿找到合适的模块,然后用正则表达式破解流解析器来处理这种情况。

【问题讨论】:

  • 多个 JSON 对象可以在一行中“重叠”吗?
  • 新对象总是按照上面的信息从新行开始。然而,对象的结尾可以在任何地方:只是一个由它自己或在最后一个值之后的右大括号。

标签: javascript node.js jsonstream


【解决方案1】:

有同样的要求,我不喜欢强制要求换行符来支持 readline,需要能够处理在流中间(可能是 JSON 文档的中间)开始读取,并且不喜欢不断解析和检查错误(似乎效率低下)。

因此,我更喜欢使用 clarinet sax 解析器,在我进行时收集文档并在解析整个 JSON 文档后发出 doc 事件。

我刚刚将这个类发布到 NPM

https://www.npmjs.com/package/json-doc-stream

【讨论】:

  • 这是否意味着您将整个文档保存在内存中?
【解决方案2】:

我建议尝试解析每一行:

const readline = require('readline');

const rl = readline.createInterface({
 input: child.stdout
});

var tmp = ''
rl.on('line', function(line) {
  tmp += line
  try {
    var obj = JSON.parse(tmp)
    child.emit('json', obj)
    tmp = ''
  } catch(_) {
    // JSON.parse may fail if JSON is not complete yet
  }
})

child.on('json', function(obj) {
  console.log(obj)
})

由于 child 是 EventEmitter,因此只需调用 child.emit('json', obj)。

【讨论】:

  • Funny :) 出现了两个相同的答案,但你之前的 :)
  • 创建readline接口时需要使用input而不是outptut。
  • 谢谢 :-) 没想到 try{}catch{}
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多