Как вернуть сложный JSON-ответ с Node.js? - PullRequest
79 голосов
/ 18 января 2012

Используя 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();
        }
    });
});

Ответы [ 3 ]

182 голосов
/ 22 ноября 2012

В экспрессе 3 можно напрямую использовать res.json ({foo: bar})

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

См. Документацию

19 голосов
/ 18 января 2012

Я не знаю, действительно ли это отличается, но вместо того, чтобы перебирать курсор запроса, вы можете сделать что-то вроде этого:

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 голосов
/ 18 января 2012

[Редактировать] После просмотра документации Mongoose вы можете отправить каждый результат запроса в виде отдельного чанка; веб-сервер использует кодировку chunked Transfer по умолчанию , поэтому все, что вам нужно сделать, это обернуть массив вокруг элементов, чтобы сделать его действительным объектом 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 })));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...