json的node.js流数组以进行响应

ric*_*dtz 7 arrays rest json node.js node.js-stream

我有一个REST方法,应该返回一个JSON数组,其中包含从mongodb中读取的某些元素(使用mongoose)。

它应该非常简单(在实际情况下,find方法具有参数,但这不是问题):

OutDataModel.find().stream({transform: JSON.stringify}).pipe(res);
Run Code Online (Sandbox Code Playgroud)

这种方法的问题是我没有得到有效的JSON,结果是这样的:

{"id":"1","score":11}{"id":"2","score":12}{"id":"3","score":13}
Run Code Online (Sandbox Code Playgroud)

我期待着这样:

[{"id":"1","score":11},{"id":"2","score":12},{"id":"3","score":13}]
Run Code Online (Sandbox Code Playgroud)

我还没有找到解决方案,但是我很确定会有一个简单的解决方案。

我尝试过的

没有什么让我引以为傲的,但事情就这样了。

  1. 在流之前写入'['响应。
  2. 我提供了另一个方法,而不是JSON.stringify,它调用JSON.stringify并','在末尾添加一个
  3. 在流的“结束”事件中,我写']'了响应。

仍然无法使用此“解决方案”,因为我在末尾有这样一个逗号:

 [{"id":"1","score":11},{"id":"2","score":12},{"id":"3","score":13},]
Run Code Online (Sandbox Code Playgroud)

正如我所说,我很确定应该有一个干净的解决方案,因为这应该很普遍。

此方法将有很多并发调用,因此我不想将所有内容都读取到内存中,然后再将所有内容写入响应中。每次调用都不会返回很多记录,但是所有这些记录在一起可能会非常庞大​​。使用者是一个带有spring的Java应用程序,它使用jackson解析JSON。

请让我知道该怎么做。

回答

通过按照接受的答案中的建议创建一个Transform流,使它起作用。

我的信息流看起来像这样:

var arraystream = new stream.Transform({objectMode: true});
arraystream._hasWritten = false;


arraystream._transform = function (chunk, encoding, callback) {
    console.log('_transform:' + chunk);
    if (!this._hasWritten) {
        this._hasWritten = true;
        this.push('[' + JSON.stringify(chunk));

    } else {
        this.push(',' + JSON.stringify(chunk));
    }
    callback();
};

arraystream._flush = function (callback) {
    console.log('_flush:');
    this.push(']');
    callback();

};
Run Code Online (Sandbox Code Playgroud)

以及使用它的代码:

OutDataModel.find().stream().pipe(arraystream).pipe(res);
Run Code Online (Sandbox Code Playgroud)

谢谢。

lis*_*K01 3

通过实现自己的逻辑,您就走在正确的轨道上。您还可以利用ArrayFormatter此处执行类似的操作:https ://gist.github.com/aeckmann/1403797

每个文档都会单独调用转换函数——Mongoose QueryStream 为每个“数据”事件发出一个文档,但 QueryStream 不会在语义上将它们视为任何更大数组数据结构的一部分;要获得数组格式的 JSON,您确实必须自己完成(正如您所猜测的)。