Bonne façon de renvoyer JSON en utilisant node ou Express

440

Ainsi, on peut tenter de récupérer l'objet JSON suivant:

$ curl -i -X GET http://echo.jsontest.com/key/value/anotherKey/anotherValue
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=ISO-8859-1
Date: Wed, 30 Oct 2013 22:19:10 GMT
Server: Google Frontend
Cache-Control: private
Alternate-Protocol: 80:quic,80:quic
Transfer-Encoding: chunked

{
   "anotherKey": "anotherValue",
   "key": "value"
}
$

Existe-t-il un moyen de produire exactement le même corps dans une réponse d'un serveur utilisant node ou express? De toute évidence, on peut définir les en-têtes et indiquer que le type de contenu de la réponse sera "application / json", mais il existe alors différentes façons d'écrire / d'envoyer l'objet. Celui que j'ai vu couramment utilisé est en utilisant une commande de la forme:

response.write(JSON.stringify(anObject));

Cependant, cela comporte deux points sur lesquels on pourrait argumenter comme s'il s'agissait de «problèmes»:

  • Nous envoyons une chaîne.
  • De plus, il n'y a pas de nouveau caractère de ligne à la fin.

Une autre idée est d'utiliser la commande:

response.send(anObject);

Cela semble envoyer un objet JSON basé sur la sortie de curl similaire au premier exemple ci-dessus. Cependant, il n'y a pas de nouveau caractère de ligne à la fin du corps lorsque curl est à nouveau utilisé sur un terminal. Alors, comment peut-on réellement écrire quelque chose comme ça avec un nouveau caractère de ligne ajouté à la fin en utilisant node ou node / express?

MightyMouse
la source

Réponses:

620

Cette réponse est également une chaîne de caractères, si vous souhaitez envoyer la réponse prettified, pour une raison gênante, vous pouvez utiliser quelque chose comme JSON.stringify(anObject, null, 3)

Il est important que vous définissiez également l'en- Content-Typetête application/json.

var http = require('http');

var app = http.createServer(function(req,res){
    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify({ a: 1 }));
});
app.listen(3000);

// > {"a":1}

Prettifié:

var http = require('http');

var app = http.createServer(function(req,res){
    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify({ a: 1 }, null, 3));
});
app.listen(3000);

// >  {
// >     "a": 1
// >  }

Je ne sais pas exactement pourquoi vous souhaitez y mettre fin avec une nouvelle ligne, mais vous pouvez simplement le faire JSON.stringify(...) + '\n'pour y parvenir.

Express

En express, vous pouvez le faire en modifiant les options à la place .

'json replacer' Rappel du remplaçant JSON, null par défaut

'json spaces' Espaces de réponse JSON pour le formatage, par défaut 2 en développement, 0 en production

Pas vraiment recommandé de définir à 40

app.set('json spaces', 40);

Ensuite, vous pourriez simplement répondre avec du json.

res.json({ a: 1 });

Il utilisera la 'json spaces'configuration pour l'affiner.

bevacqua
la source
3
Merci pour votre temps. Pour être honnête avec vous, je n'ai pas de problème de ma part. C'est juste que quelqu'un (dans un fuseau horaire différent) s'est plaint du format que j'utilisais parce qu'il voulait faire un get et pour une raison quelconque, il ne pouvait pas lire correctement mon objet. Merci d'avoir noté la belle version de stringify. :)
MightyMouse
2
Cette personne devrait vraiment analyser la chaîne JSON en objets, ou utiliser une extension de navigateur , plutôt que d'essayer de lire à la main.
bevacqua
2
@akshay Encore mieux, res.senddéfinira automatiquement le content-typesur JSON, si l'élément envoyé est un objet ou un tableau.
royhowie
3
Je pense que vous vouliez utiliser res.end()dans votre exemple http(non express)
Tobias Fünke
2
@ TobiasFünke a raison, je pense. res.send()ne fonctionne pas. Veuillez le corriger, s'il s'agit d'une erreur. res.end()fonctionne correctement. Merci btw.
Kaushal28
410

Depuis Express.js 3x, l'objet de réponse a une méthode json () qui définit correctement tous les en-têtes pour vous et renvoie la réponse au format JSON.

Exemple:

res.json({"foo": "bar"});
JamieL
la source
Merci pour votre temps. Cependant, ma question ne portait pas vraiment sur les en-têtes à l'époque. C'était plus sur le résultat que l'on pouvait voir dire à travers la boucle. Merci encore quand même.
MightyMouse
53
OK, mais cette méthode renvoie également le format JSON correctement formaté. Cela fait partie de la réponse. Donc res.json () définit les en-têtes corrects, puis la réponse JSON.stringify () est automatiquement pour vous.
JamieL
19

Si vous essayez d'envoyer un fichier json, vous pouvez utiliser des flux

var usersFilePath = path.join(__dirname, 'users.min.json');

apiRouter.get('/users', function(req, res){
    var readable = fs.createReadStream(usersFilePath);
    readable.pipe(res);
});
Connor Leech
la source
10
Qu'est-ce que fs, qu'est-ce que pipe, qu'est-ce qui est lisible? Votre réponse est plus un mystère
Aakash Dave
11

La res.json()fonction devrait être suffisante dans la plupart des cas.

app.get('/', (req, res) => res.json({ answer: 42 }));

La res.json()fonction convertit le paramètre que vous transmettez à JSON à l'aide de JSON.stringify()et définit l'en- Content-Typetête pour application/json; charset=utf-8que les clients HTTP sachent analyser automatiquement la réponse.

vkarpov15
la source
6

si vous utilisez Express, vous pouvez utiliser ceci:

res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({key:"value"}));

ou juste ça

res.json({key:"value"});
IXOVER
la source
5

Vous pouvez simplement le raffiner en utilisant pipe et l'un des nombreux processeurs. Votre application doit toujours répondre avec une charge aussi faible que possible.

$ curl -i -X GET http://echo.jsontest.com/key/value/anotherKey/anotherValue | underscore print

https://github.com/ddopson/underscore-cli

pawelzny
la source
4

Vous pouvez créer un assistant pour cela: créez une fonction d'assistance pour pouvoir l'utiliser partout dans votre application

function getStandardResponse(status,message,data){
    return {
        status: status,
        message : message,
        data : data
     }
}

Voici mon itinéraire de sujet où j'essaie d'obtenir tous les sujets

router.get('/', async (req, res) => {
    const topics = await Topic.find().sort('name');
    return res.json(getStandardResponse(true, "", topics));
});

Réponse que nous obtenons

{
"status": true,
"message": "",
"data": [
    {
        "description": "sqswqswqs",
        "timestamp": "2019-11-29T12:46:21.633Z",
        "_id": "5de1131d8f7be5395080f7b9",
        "name": "topics test xqxq",
        "thumbnail": "waterfall-or-agile-inforgraphics-thumbnail-1575031579309.jpg",
        "category_id": "5de0fe0b4f76c22ebce2b70a",
        "__v": 0
    },
    {
        "description": "sqswqswqs",
        "timestamp": "2019-11-29T12:50:35.627Z",
        "_id": "5de1141bc902041b58377218",
        "name": "topics test xqxq",
        "thumbnail": "waterfall-or-agile-inforgraphics-thumbnail-1575031835605.jpg",
        "category_id": "5de0fe0b4f76c22ebce2b70a",
        "__v": 0
    },
    {
        "description": " ",
        "timestamp": "2019-11-30T06:51:18.936Z",
        "_id": "5de211665c3f2c26c00fe64f",
        "name": "topics test xqxq",
        "thumbnail": "waterfall-or-agile-inforgraphics-thumbnail-1575096678917.jpg",
        "category_id": "5de0fe0b4f76c22ebce2b70a",
        "__v": 0
    },
    {
        "description": "null",
        "timestamp": "2019-11-30T06:51:41.060Z",
        "_id": "5de2117d5c3f2c26c00fe650",
        "name": "topics test xqxq",
        "thumbnail": "waterfall-or-agile-inforgraphics-thumbnail-1575096701051.jpg",
        "category_id": "5de0fe0b4f76c22ebce2b70a",
        "__v": 0
    },
    {
        "description": "swqdwqd wwwwdwq",
        "timestamp": "2019-11-30T07:05:22.398Z",
        "_id": "5de214b2964be62d78358f87",
        "name": "topics test xqxq",
        "thumbnail": "waterfall-or-agile-inforgraphics-thumbnail-1575097522372.jpg",
        "category_id": "5de0fe0b4f76c22ebce2b70a",
        "__v": 0
    },
    {
        "description": "swqdwqd wwwwdwq",
        "timestamp": "2019-11-30T07:36:48.894Z",
        "_id": "5de21c1006f2b81790276f6a",
        "name": "topics test xqxq",
        "thumbnail": "waterfall-or-agile-inforgraphics-thumbnail-1575099408870.jpg",
        "category_id": "5de0fe0b4f76c22ebce2b70a",
        "__v": 0
    }
      ]
}
Nishant
la source
3

Vous pouvez utiliser un middleware pour définir le type de contenu par défaut et définir le type de contenu différemment pour des API particulières. Voici un exemple:

const express = require('express');
const app = express();

const port = process.env.PORT || 3000;

const server = app.listen(port);

server.timeout = 1000 * 60 * 10; // 10 minutes

// Use middleware to set the default Content-Type
app.use(function (req, res, next) {
    res.header('Content-Type', 'application/json');
    next();
});

app.get('/api/endpoint1', (req, res) => {
    res.send(JSON.stringify({value: 1}));
})

app.get('/api/endpoint2', (req, res) => {
    // Set Content-Type differently for this particular API
    res.set({'Content-Type': 'application/xml'});
    res.send(`<note>
        <to>Tove</to>
        <from>Jani</from>
        <heading>Reminder</heading>
        <body>Don't forget me this weekend!</body>
        </note>`);
})
Yuci
la source
2

Pour la moitié de la tête de la question, je vais crier res.typeici:

res.type('json')

est équivalent à

res.setHeader('Content-Type', 'application/json')

Source: documents express :

Définit l'en-tête HTTP Content-Type sur le type MIME tel que déterminé par mime.lookup () pour le type spécifié. Si type contient le caractère «/», il définit le Content-Type sur type.

MalcolmOcean
la source
1

Version plus ancienne d'Express app.use(express.json())ou en bodyParser.json() savoir plus sur le middleware bodyParser

Sur la dernière version d'express, nous pourrions simplement utiliser res.json()

const express = require('express'),
    port = process.env.port || 3000,
    app = express()

app.get('/', (req, res) => res.json({key: "value"}))

app.listen(port, () => console.log(`Server start at ${port}`))
Aung Zan Baw
la source
Mon cher, vous confondez réponse et demande. Le middleware BodyParser sert à analyser la demande afin que req.bodyl'objet soit envoyé en tant que corps de la demande.
Matthias Hryniszak