Node.js ile karmaşık bir JSON yanıtı nasıl döndürülür?


82

Nodejs ve express kullanarak, JSON kullanarak bir veya birden çok nesneyi (dizi) döndürmek istiyorum. Aşağıdaki kodda bir seferde bir JSON nesnesi çıkardım. Çalışıyor ama tam olarak istediğim bu değil. Çok sayıda nesnem olduğu için üretilen yanıt geçerli bir JSON yanıtı değil.

Tüm nesneleri bir diziye ekleyebileceğimi ve bu diziyi res.end'de döndürebileceğimi çok iyi biliyorum. Ancak korkarım ki bu işlem ağırlaşabilir ve bellek yoğun olabilir.

Bunu nodejs ile elde etmenin doğru yolu nedir? Query.each, aramak için doğru yöntem mi?

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

Yanıtlar:


183

Ekspres 3'te doğrudan res.json ({foo: bar}) kullanabilirsiniz

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

Belgelere bakın


9
bunu ifade olmadan nasıl yapabilirim?
Piotrek

@ Ludwik11 res.write(JSON.stringify(foo)). Eğer foobüyükse, kesmeniz gerekebilir (stringify, sonra bir seferde yığın yazın). Muhtemelen başlığınızı "Content-Type":"application/json"veya benzerini uygun şekilde görmek de isteyebilirsiniz .
OJFord

21

Bunun gerçekten farklı olup olmadığını bilmiyorum, ancak sorgu imlecini yinelemek yerine şöyle bir şey yapabilirsiniz:

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

[Düzenle] Mongoose belgelerini inceledikten sonra, her bir sorgu sonucunu ayrı bir yığın olarak gönderebileceğiniz görülüyor; web sunucusu varsayılan olarak yığınlanmış aktarım kodlaması kullanır, bu nedenle tek yapmanız gereken, bir diziyi geçerli bir JSON nesnesi yapmak için öğelerin etrafına sarmaktır.

Kabaca (test edilmemiş):

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

Alternatif olarak, belirttiğiniz gibi, dizi içeriklerini olduğu gibi gönderebilirsiniz. Bu durumda , yanıt gövdesi arabelleğe alınacak ve hemen gönderilecektir; bu, büyük sonuç kümeleri için büyük miktarda ek bellek (sonuçların kendilerini depolamak için gerekenden daha fazla) tüketebilir. Örneğin:

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

Bu iyi bir fikir. Ancak bana biraz huysuz görünüyor. Nodej'lerin biraz daha zarif bir şey sağlamasını umuyordum.
Martin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.