web-dev-qa-db-fra.com

Comment renvoyer une réponse JSON complexe avec Node.js?

En utilisant nodejs et express, je voudrais renvoyer un ou plusieurs objets (tableau) en utilisant JSON. Dans le code ci-dessous, je produis un objet JSON à la fois. Cela fonctionne mais ce n'est pas exactement ce que je veux. La réponse produite n'est pas une réponse JSON valide, car j'ai plusieurs objets.

Je sais bien que je pourrais simplement ajouter tous les objets à un tableau et renvoyer ce tableau spécifique dans res.end. Cependant, je crains que cela ne devienne difficile à traiter et demande beaucoup de mémoire.

Quelle est la bonne façon de réaliser cela avec nodejs? Query.each est-il la bonne méthode à appeler?

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

Sur Express 3, vous pouvez utiliser directement res.json ({foo: bar})

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

Voir le documentation

182
zobi8225

Je ne sais pas si c'est vraiment différent, mais plutôt que d'itérer sur le curseur de la requête, vous pourriez faire quelque chose comme ça:

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

[Edit] Après avoir examiné la documentation de Mongoose, il semble que vous puissiez envoyer chaque résultat de requête sous forme de bloc séparé. le serveur Web utilise codage de transfert en blocpar défaut , vous n'avez donc qu'à enrouler un tableau autour des éléments pour en faire un objet JSON valide.

Grosso modo (non testé):

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

Alternativement, comme vous le mentionnez, vous pouvez simplement envoyer le contenu du tableau tel quel. Dans ce cas, le corps de la réponse sera mis en mémoire tampon et envoyé immédiatement, ce qui peut consommer une grande quantité de mémoire supplémentaire (supérieure à celle requise pour stocker les résultats eux-mêmes) pour des ensembles de résultats volumineux. Par exemple:

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