Cara yang tepat untuk mengembalikan JSON menggunakan node atau Express

440

Jadi, seseorang dapat mencoba mengambil objek JSON berikut:

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

Apakah ada cara untuk menghasilkan tubuh yang persis sama dalam respons dari server menggunakan node atau express? Jelas, seseorang dapat mengatur header dan mengindikasikan bahwa tipe konten dari respon akan menjadi "application / json", tetapi kemudian ada berbagai cara untuk menulis / mengirim objek. Salah satu yang saya lihat umum digunakan adalah dengan menggunakan perintah dari form:

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

Namun, ini memiliki dua poin di mana orang dapat berdebat seolah-olah itu adalah "masalah":

  • Kami mengirim string.
  • Selain itu, pada akhirnya tidak ada karakter baris baru.

Gagasan lain adalah menggunakan perintah:

response.send(anObject);

Ini tampaknya mengirimkan objek JSON berdasarkan pada output dari curl mirip dengan contoh pertama di atas. Namun, tidak ada karakter garis baru di ujung tubuh ketika keriting lagi digunakan pada terminal. Jadi, bagaimana seseorang bisa menuliskan sesuatu seperti ini dengan karakter baris baru pada akhirnya menggunakan node atau node / express?

MightyMouse
sumber

Jawaban:

620

Respons itu juga berupa string, jika Anda ingin mengirim respons yang sudah dipersonifikasi, untuk beberapa alasan yang canggung, Anda dapat menggunakan sesuatu seperti JSON.stringify(anObject, null, 3)

Penting juga untuk mengatur Content-Typetajuk 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
// >  }

Saya tidak yakin mengapa Anda ingin menghentikannya dengan baris baru, tetapi Anda bisa lakukan JSON.stringify(...) + '\n'untuk mencapainya.

Mengekspresikan

Secara kilat Anda dapat melakukan ini dengan mengubah opsi .

'json replacer' JSON replacer callback, null secara default

'json spaces' Ruang respons JSON untuk pemformatan, default ke 2 dalam pengembangan, 0 dalam produksi

Sebenarnya tidak disarankan untuk mengatur ke 40

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

Maka Anda bisa merespons dengan beberapa json.

res.json({ a: 1 });

Ini akan menggunakan 'json spaceskonfigurasi 'untuk memproteksi itu.

bevacqua
sumber
3
Terima kasih atas waktu Anda. Jujur dengan Anda, saya tidak punya masalah di ujung saya. Hanya saja seseorang (dalam zona waktu yang berbeda) mengeluh tentang format yang saya gunakan karena dia ingin mendapatkan dan karena alasan tertentu mereka tidak dapat membaca objek saya dengan benar. Terima kasih telah mencatat versi bagus dari peregangan. :)
MightyMouse
2
Seseorang ini harus benar-benar mengurai string JSON menjadi objek, atau menggunakan ekstensi browser , daripada mencoba melakukan pembacaan dengan tangan.
bevacqua
2
@akshay Bahkan lebih baik, res.sendsecara otomatis akan mengatur content-typeke JSON, jika barang yang dikirim adalah objek atau array.
royhowie
3
Saya pikir Anda dimaksudkan untuk menggunakan res.end()di Anda http(non-express) contoh
Tobias Funke
2
@ TobiasFünke benar saya pikir. res.send()tidak bekerja. Harap perbaiki, jika itu kesalahan. res.end()berfungsi dengan benar. Terima kasih btw.
Kaushal28
410

Sejak Express.js 3x objek respons memiliki metode json () yang mengatur semua header dengan benar untuk Anda dan mengembalikan respons dalam format JSON.

Contoh:

res.json({"foo": "bar"});
JamieL
sumber
Terima kasih atas waktu Anda. Namun, pertanyaan saya sebenarnya bukan tentang tajuk. Itu lebih tentang hasil yang bisa dilihat seseorang melalui curl. Terima kasih lagi.
MightyMouse
53
OK, tetapi metode ini juga mengembalikan JSON yang diformat dengan benar juga. Itu adalah bagian dari respons. Jadi res.json () menetapkan tajuk yang benar dan kemudian JSON.stringify () adalah respons untuk Anda secara otomatis.
JamieL
19

Jika Anda mencoba mengirim file json, Anda dapat menggunakan stream

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

apiRouter.get('/users', function(req, res){
    var readable = fs.createReadStream(usersFilePath);
    readable.pipe(res);
});
Connor Leech
sumber
10
Apa fs, apa pipa, apa yang bisa dibaca? Jawaban Anda lebih merupakan sebuah misteri
Aakash Dave
11

The res.json()fungsi harus cukup untuk kebanyakan kasus.

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

The res.json()bertobat parameter fungsi yang Anda lolos ke JSON menggunakan JSON.stringify()dan menetapkan Content-Typesundulan untuk application/json; charset=utf-8jadi HTTP klien tahu untuk secara otomatis mengurai respon.

vkarpov15
sumber
6

jika Anda menggunakan Express, Anda dapat menggunakan ini:

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

atau hanya ini

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

Anda cukup memproduksinya menggunakan pipa dan satu dari banyak prosesor. Aplikasi Anda harus selalu merespons dengan muatan sekecil mungkin.

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

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

pawelzny
sumber
4

Anda dapat membuat helper untuk itu: Buat fungsi helper sehingga Anda dapat menggunakannya di mana saja di aplikasi Anda

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

Inilah rute topik saya di mana saya mencoba untuk mendapatkan semua topik

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

Respon yang kami dapatkan

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

Anda dapat menggunakan middleware untuk mengatur Tipe Konten default, dan mengatur Tipe Konten berbeda untuk API tertentu. Berikut ini sebuah contoh:

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

Untuk setengah dari tajuk pertanyaan, saya akan berteriak ke res.typesini:

res.type('json')

setara dengan

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

Sumber: dokumen tertulis :

Menetapkan header HTTP Tipe-Konten ke tipe MIME sebagaimana ditentukan oleh mime.lookup () untuk tipe yang ditentukan. Jika tipe mengandung karakter “/”, maka ia akan menentukan tipe konten untuk diketik.

MalcolmOcean
sumber
1

Versi Express yang lebih lama menggunakan app.use(express.json())atau bodyParser.json() membaca lebih lanjut tentang middleware bodyParser

Pada versi express terbaru, kita cukup menggunakan 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
sumber
Sayangku, tanggapanmu membingungkan dengan permintaan. Middleware BodyParser adalah untuk mem-parsing permintaan sehingga req.bodyobjek yang dikirim sebagai badan permintaan.
Matthias Hryniszak