Richtige Möglichkeit, JSON mit Node oder Express zurückzugeben

437

Man kann also versuchen, das folgende JSON-Objekt abzurufen:

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

Gibt es eine Möglichkeit, in einer Antwort von einem Server mit Node oder Express genau denselben Text zu erzeugen? Natürlich kann man die Header setzen und angeben, dass der Inhaltstyp der Antwort "application / json" sein wird, aber dann gibt es verschiedene Möglichkeiten, das Objekt zu schreiben / zu senden. Das, was ich häufig gesehen habe, ist die Verwendung eines Befehls des Formulars:

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

Dies hat jedoch zwei Punkte, an denen man argumentieren könnte, als wären sie "Probleme":

  • Wir senden eine Zeichenfolge.
  • Außerdem gibt es am Ende kein neues Zeilenzeichen.

Eine andere Idee ist, den Befehl zu verwenden:

response.send(anObject);

Dies scheint ein JSON-Objekt zu senden, das auf der Ausgabe von Curl basiert, ähnlich dem ersten Beispiel oben. Es gibt jedoch kein neues Linienzeichen am Ende des Körpers, wenn Curl wieder an einem Terminal verwendet wird. Wie kann man so etwas tatsächlich mit einem neuen Zeilenzeichen aufschreiben, das am Ende mit node oder node / express angehängt wird?

MightyMouse
quelle

Antworten:

617

Diese Antwort ist auch eine Zeichenfolge. Wenn Sie die Antwort aus einem unangenehmen Grund hübsch senden möchten, können Sie so etwas wie verwenden JSON.stringify(anObject, null, 3)

Es ist wichtig, dass Sie auch den Content-TypeHeader auf setzen 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
// >  }

Ich bin mir nicht ganz sicher, warum Sie es mit einem Zeilenumbruch beenden möchten, aber Sie könnten einfach tun JSON.stringify(...) + '\n', um dies zu erreichen.

ausdrücken

In Express können Sie dies tun, indem Sie stattdessen die Optionen ändern .

'json replacer' JSON-Ersetzer-Rückruf, standardmäßig null

'json spaces' JSON-Antwortbereiche für die Formatierung, standardmäßig 2 in der Entwicklung, 0 in der Produktion

Nicht wirklich empfohlen, auf 40 zu setzen

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

Dann könnten Sie einfach mit etwas json antworten.

res.json({ a: 1 });

Es wird die 'json spaces'Konfiguration verwenden, um es zu verschönern.

bevacqua
quelle
3
Vielen Dank für Ihre Zeit. Um ehrlich zu sein, habe ich kein Problem. Es ist nur so, dass sich jemand (in einer anderen Zeitzone) über das von mir verwendete Format beschwert hat, weil er ein Get machen wollte und aus irgendeinem Grund mein Objekt nicht richtig lesen konnte. Vielen Dank für die nette Version von stringify. :)
MightyMouse
2
Diese Person sollte die JSON-Zeichenfolge wirklich in Objekte analysieren oder eine Browser-Erweiterung verwenden , anstatt zu versuchen, sie von Hand zu lesen.
Bevacqua
2
@akshay Noch besser, res.sendwird automatisch content-typeauf JSON gesetzt, wenn das gesendete Element ein Objekt oder Array ist.
Royhowie
3
Ich denke, Sie wollten res.end()in Ihrem http(nicht ausdrücklichen) Beispiel verwenden
Tobias Fünke
2
@ TobiasFünke hat recht, denke ich. res.send()funktioniert nicht. Bitte korrigieren Sie es, wenn es ein Fehler ist. res.end()funktioniert richtig. Danke übrigens.
Kaushal28
409

Seit Express.js 3x verfügt das Antwortobjekt über eine json () -Methode, die alle Header korrekt für Sie festlegt und die Antwort im JSON-Format zurückgibt.

Beispiel:

res.json({"foo": "bar"});
JamieL
quelle
Vielen Dank für Ihre Zeit. Bei meiner Frage ging es damals jedoch nicht wirklich um Header. Es ging mehr um das Ergebnis, das man durch Locken sagen konnte. Trotzdem nochmals vielen Dank.
MightyMouse
53
OK, aber diese Methode gibt auch korrekt formatiertes JSON zurück. Es ist Teil der Antwort. Also setzt res.json () die richtigen Header und dann ist JSON.stringify () automatisch die Antwort für Sie.
JamieL
19

Wenn Sie versuchen, eine JSON-Datei zu senden, können Sie Streams verwenden

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

apiRouter.get('/users', function(req, res){
    var readable = fs.createReadStream(usersFilePath);
    readable.pipe(res);
});
Connor Leech
quelle
10
Was ist fs, was ist Pipe, was ist lesbar? Ihre Antwort ist eher ein Rätsel
Aakash Dave
11

Die res.json()Funktion sollte in den meisten Fällen ausreichend sein.

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

Die res.json()Funktion konvertiert den Parameter, den Sie mit JSON übergeben, JSON.stringify()und setzt den Content-TypeHeader auf, application/json; charset=utf-8damit HTTP-Clients die Antwort automatisch analysieren können.

vkarpov15
quelle
6

Wenn Sie Express verwenden, können Sie Folgendes verwenden:

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

oder einfach das

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

Sie können es einfach mit Pipe und einem von vielen Prozessoren verschönern. Ihre App sollte immer mit möglichst geringer Last reagieren.

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

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

pawelzny
quelle
4

Sie können dafür einen Helfer erstellen: Erstellen Sie eine Hilfsfunktion, damit Sie sie überall in Ihrer Anwendung verwenden können

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

Hier ist meine Themenroute, auf der ich versuche, alle Themen abzurufen

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

Antwort bekommen wir

{
"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
quelle
3

Sie können eine Middleware verwenden, um den Standardinhaltstyp festzulegen und den Inhaltstyp für bestimmte APIs unterschiedlich festzulegen. Hier ist ein Beispiel:

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
quelle
2

Für die Kopfzeithälfte der Frage werde ich hier einen Gruß aussprechen res.type:

res.type('json')

ist äquivalent zu

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

Quelle: Expressdokumente :

Legt den HTTP-Header für den Inhaltstyp auf den MIME-Typ fest, der von mime.lookup () für den angegebenen Typ festgelegt wird. Wenn type das Zeichen "/" enthält, wird der Inhaltstyp auf type gesetzt.

MalcolmOcean
quelle
1

Ältere Express-Versionen verwenden app.use(express.json())oder bodyParser.json() lesen Sie mehr über bodyParser Middleware

Auf der neuesten Version von Express könnten wir einfach verwenden 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
quelle
Mein Lieber, Sie verwechseln Antwort mit Anfrage. Die BodyParser-Middleware dient zum Parsen der Anforderung, sodass req.bodydas Objekt als Hauptteil der Anforderung gesendet wird.
Matthias Hryniszak