如何使用 Node.js 返回复杂的 JSON 响应?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8905613/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:02:32  来源:igfitidea点击:

How to return a complex JSON response with Node.js?

jsonnode.jsexpressmongoose

提问by Martin

Using nodejs and express, I'd like to return one or multiple objects (array) using JSON. In the code below I output one JSON object at a time. It works but this isn't exactly what I want. The response produced isn't a valid JSON response since I have many objects.

使用 nodejs 和 express,我想使用 JSON 返回一个或多个对象(数组)。在下面的代码中,我一次输出一个 JSON 对象。它有效,但这不是我想要的。生成的响应不是有效的 JSON 响应,因为我有很多对象。

I am well aware that I could simply add all objects to an array and return that specific array in res.end. However I am afraid this could become heavy to process and memory intensive.

我很清楚我可以简单地将所有对象添加到一个数组中并在 res.end 中返回该特定数组。但是,我担心这可能会变得繁重处理和内存密集型。

What is the proper way to acheive this with nodejs? Is query.each the right method to call?

使用 nodejs 实现这一目标的正确方法是什么?query.each 是正确的调用方法吗?

app.get('/users/:email/messages/unread', function(req, res, next) {
    var query = MessageInfo
        .find({ $and: [ { 'email': req.params.email }, { 'hasBeenRead': false } ] });

    res.writeHead(200, { 'Content-Type': 'application/json' });   
    query.each(function(err, msg) {
        if (msg) { 
            res.write(JSON.stringify({ msgId: msg.fileName }));
        } else {
            res.end();
        }
    });
});

回答by zobi8225

On express 3 you can use directly res.json({foo:bar})

在 express 3 上你可以直接使用 res.json({foo:bar})

res.json({ msgId: msg.fileName })

See the documentation

查看文档

回答by danmactough

I don't know if this is really any different, but rather than iterate over the query cursor, you could do something like this:

我不知道这是否真的有什么不同,但与其遍历查询游标,您还可以执行以下操作:

query.exec(function (err, results){
  if (err) res.writeHead(500, err.message)
  else if (!results.length) res.writeHead(404);
  else {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.write(JSON.stringify(results.map(function (msg){ return {msgId: msg.fileName}; })));
  }
  res.end();
});

回答by maerics

[Edit]After reviewing the Mongoose documentation, it looks like you can send each query result as a separate chunk; the web server uses chunked transfer encodingby defaultso all you have to do is wrap an array around the items to make it a valid JSON object.

[编辑]查看 Mongoose 文档后,您似乎可以将每个查询结果作为单独的块发送;默认情况下,Web 服务器使用分块传输编码因此您要做的就是在项目周围包装一个数组,使其成为有效的 JSON 对象。

Roughly (untested):

粗略(未经测试):

app.get('/users/:email/messages/unread', function(req, res, next) {
  var firstItem=true, query=MessageInfo.find(/*...*/);
  res.writeHead(200, {'Content-Type': 'application/json'});
  query.each(function(docs) {
    // Start the JSON array or separate the next element.
    res.write(firstItem ? (firstItem=false,'[') : ',');
    res.write(JSON.stringify({ msgId: msg.fileName }));
  });
  res.end(']'); // End the JSON array and response.
});

Alternatively, as you mention, you can simply send the array contents as-is. In this case the response body will be bufferedand sent immediately, which may consume a large amount of additional memory (above what is required to store the results themselves) for large result sets. For example:

或者,正如您所提到的,您可以简单地按原样发送数组内容。在这种情况下,响应正文将被缓冲并立即发送,对于大型结果集,这可能会消耗大量额外内存(高于存储结果本身所需的内存)。例如:

// ...
var query = MessageInfo.find(/*...*/);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(query.map(function(x){ return x.fileName })));