Modo corretto per restituire JSON utilizzando il nodo o Express


440

Quindi, si può tentare di recuperare il seguente oggetto JSON:

$ 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"
}
$

C'è un modo per produrre esattamente lo stesso corpo in una risposta da un server usando il nodo o express? Chiaramente, si possono impostare le intestazioni e indicare che il tipo di contenuto della risposta sarà "application / json", ma poi ci sono diversi modi per scrivere / inviare l'oggetto. Quello che ho visto comunemente usato è usando un comando del modulo:

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

Tuttavia, questo ha due punti in cui si potrebbe discutere come se fossero "problemi":

  • Stiamo inviando una stringa.
  • Inoltre, non esiste un nuovo carattere di linea alla fine.

Un'altra idea è quella di utilizzare il comando:

response.send(anObject);

Questo sembra inviare un oggetto JSON basato sull'output di arricciatura simile al primo esempio sopra. Tuttavia, non esiste un nuovo carattere di linea alla fine del corpo quando il ricciolo viene nuovamente utilizzato su un terminale. Quindi, come si può effettivamente scrivere qualcosa di simile con un nuovo carattere di linea aggiunto alla fine usando node o node / express?

Risposte:


620

Anche quella risposta è una stringa, se vuoi inviare la risposta in modo predefinito, per qualche motivo imbarazzante, potresti usare qualcosa come JSON.stringify(anObject, null, 3)

È importante impostare anche l' Content-Typeintestazione 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}

prettified:

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
// >  }

Non sono esattamente sicuro del motivo per cui vuoi terminarlo con una nuova riga, ma potresti semplicemente farlo JSON.stringify(...) + '\n'per raggiungerlo.

Esprimere

In express puoi farlo modificando invece le opzioni .

'json replacer' Callback sostitutivo JSON, null per impostazione predefinita

'json spaces' Spazi di risposta JSON per la formattazione, il valore predefinito è 2 in sviluppo, 0 in produzione

In realtà non è consigliabile impostare su 40

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

Quindi potresti semplicemente rispondere con un po 'di json.

res.json({ a: 1 });

'json spacesUserà la 'configurazione per preimpostarla.


3
Grazie per il tuo tempo. Ad essere sincero con te, non ho alcun problema da parte mia. È solo che qualcuno (in diversi fusi orari) si è lamentato del formato che stavo usando perché voleva fare un get e per qualche motivo non potevano leggere correttamente il mio oggetto. Grazie per aver notato la bella versione di stringify. :)
MightyMouse,

2
Questo qualcuno dovrebbe davvero analizzare la stringa JSON in oggetti o utilizzare un'estensione del browser , piuttosto che provare a fare qualsiasi lettura a mano.
Bevacqua,

2
@akshay Ancora meglio, res.sendimposterà automaticamente content-typesu JSON, se l'elemento inviato è un oggetto o un array.
Royhowie,

3
Penso che tu intendessi usare res.end()nel tuo esempio http(non espresso)
Tobias Fünke il

2
@ TobiasFünke ha ragione, credo. res.send()non funziona. Per favore correggilo, se è un errore. res.end()funziona correttamente. Grazie a proposito.
Kaushal28,

410

Dal momento che Express.js 3x l'oggetto response ha un metodo json () che imposta correttamente tutte le intestazioni e restituisce la risposta in formato JSON.

Esempio:

res.json({"foo": "bar"});

Grazie per il tuo tempo. Tuttavia, la mia domanda non riguardava davvero le intestazioni di allora. Si trattava più del risultato che si poteva vedere dire attraverso il ricciolo. Grazie ancora comunque.
MightyMouse,

53
OK, ma questo metodo restituisce anche JSON formattato correttamente. Fa parte della risposta. Quindi res.json () imposta le intestazioni corrette e quindi JSON.stringify () è la risposta per te automaticamente.
JamieL

19

Se stai provando a inviare un file json puoi usare gli stream

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

apiRouter.get('/users', function(req, res){
    var readable = fs.createReadStream(usersFilePath);
    readable.pipe(res);
});

10
Cos'è fs, cos'è pipe, cosa è leggibile? La tua risposta è più di un mistero
Aakash Dave, il


6

se stai usando Express puoi usare questo:

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

o solo questo

res.json({key:"value"});

5

Puoi semplicemente prettificarlo usando pipe e uno dei tanti processori. L'app dovrebbe sempre rispondere con il minor carico possibile.

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

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


4

Puoi creare un aiuto per questo: crea una funzione di aiuto in modo da poterlo usare ovunque nella tua applicazione

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

Ecco il mio percorso tematico in cui sto cercando di ottenere tutti gli argomenti

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

Risposta che otteniamo

{
"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
    }
      ]
}

3

È possibile utilizzare un middleware per impostare il tipo di contenuto predefinito e impostare il tipo di contenuto in modo diverso per determinate API. Ecco un esempio:

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

2

Per la metà dell'intestazione della domanda, darò un messaggio res.typequi:

res.type('json')

è equivalente a

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

Fonte: express docs :

Imposta l'intestazione HTTP Content-Type sul tipo MIME come determinato da mime.lookup () per il tipo specificato. Se type contiene il carattere “/”, imposta Type-Type su type.


1

La versione precedente di Express usa app.use(express.json())o bodyParser.json() leggi di più sul middleware bodyParser

Sull'ultima versione di Express potremmo semplicemente usare 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}`))

Mia cara, stai confondendo la risposta con la richiesta. Il middleware BodyParser serve per analizzare la richiesta in modo che req.bodysia l'oggetto inviato come corpo della richiesta.
Matthias Hryniszak,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.