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


82

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

我很清楚,我可以简单地将所有对象添加到数组中,然后在res.end中返回该特定数组。但是,恐怕这可能会使处理和内存密集化变得很重。

使用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();
        }
    });
});

Answers:


183

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

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

请参阅说明文件


9
没有快递怎么办?
Piotrek 2014年

@ Ludwik11 res.write(JSON.stringify(foo))。如果foo较大,则可能需要将其切碎(字符串化,然后一次写入块)。可能还想设置您的标题"Content-Type":"application/json"或类似的标题。
OJFord

21

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

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();
});

12

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

大致(未试用):

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.
});

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

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

这是一个好主意。但是,对我来说,它看起来有点不客气。我希望nodejs提供一些更优雅的东西。
马丁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.