81 votes

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

En utilisant nodejs et express, j'aimerais retourner un ou plusieurs objets (array) en utilisant JSON. Dans le code ci-dessous, je retourne 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 puisque j'ai plusieurs objets.

Je suis bien conscient 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 lourd à traiter et gourmand en mémoire.

Quelle est la bonne façon d'y parvenir avec nodejs ? Est-ce que query.each est 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();
        }
    });
});

182voto

zobi8225 Points 1490

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

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

Voir le la documentation

20voto

danmactough Points 1992

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

12voto

maerics Points 47743

[Editer] Après avoir consulté la documentation de Mongoose, il semble que vous puissiez envoyer chaque résultat de requête sous la forme d'un morceau séparé ; le serveur web utilise la fonction encodage de transfert par morceaux par défaut il suffit donc d'entourer les éléments d'un tableau pour en faire un objet JSON valide.

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

Sinon, 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és immédiatement, ce qui peut consommer une grande quantité de mémoire supplémentaire (en plus de ce qui est nécessaire pour stocker les résultats eux-mêmes) pour les grands ensembles de résultats. A titre d'exemple :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X