Cách thích hợp để trả về JSON bằng nút hoặc Express


437

Vì vậy, người ta có thể cố gắng tìm nạp đối tượng JSON sau đây:

$ 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ó cách nào để tạo ra chính xác cùng một cơ thể trong phản hồi từ máy chủ bằng nút hoặc express không? Rõ ràng, người ta có thể đặt các tiêu đề và chỉ ra rằng loại nội dung của phản hồi sẽ là "application / json", nhưng sau đó có nhiều cách khác nhau để viết / gửi đối tượng. Một cái mà tôi đã thấy thường được sử dụng là bằng cách sử dụng một lệnh có dạng:

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

Tuy nhiên, điều này có hai điểm mà người ta có thể tranh luận như thể họ là "vấn đề":

  • Chúng tôi đang gửi một chuỗi.
  • Hơn nữa, cuối cùng không có nhân vật dòng mới.

Một ý tưởng khác là sử dụng lệnh:

response.send(anObject);

Điều này dường như đang gửi một đối tượng JSON dựa trên đầu ra của curl tương tự như ví dụ đầu tiên ở trên. Tuy nhiên, không có ký tự dòng mới ở cuối cơ thể khi curl lại được sử dụng trên thiết bị đầu cuối. Vì vậy, làm thế nào người ta thực sự có thể viết ra một cái gì đó như thế này với một ký tự dòng mới được nối vào cuối bằng cách sử dụng nút hoặc nút / express?

Câu trả lời:


617

Phản hồi đó cũng là một chuỗi, nếu bạn muốn gửi phản hồi được chỉnh sửa, vì một số lý do khó xử, bạn có thể sử dụng một cái gì đó như JSON.stringify(anObject, null, 3)

Điều quan trọng là bạn cũng đặt Content-Typetiêu đề 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}

Chuẩn bị:

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

Tôi không chắc chắn chính xác lý do tại sao bạn muốn chấm dứt nó với một dòng mới, nhưng bạn chỉ có thể làm JSON.stringify(...) + '\n'để đạt được điều đó.

bày tỏ

Thay vào đó, bạn có thể làm điều này bằng cách thay đổi các tùy chọn thay thế .

'json replacer' JSON thay thế gọi lại, null theo mặc định

'json spaces' Không gian phản hồi JSON để định dạng, mặc định là 2 trong phát triển, 0 trong sản xuất

Không thực sự được đề xuất để đặt thành 40

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

Sau đó, bạn chỉ có thể trả lời với một số json.

res.json({ a: 1 });

Nó sẽ sử dụng 'json spacescấu hình 'để tô điểm cho nó.


3
Cảm ơn bạn đã dành thời gian. Thành thật với bạn, tôi không có vấn đề gì với tôi cả. Chỉ là ai đó (ở các múi giờ khác nhau) phàn nàn về định dạng mà tôi đang sử dụng vì anh ta muốn nhận và vì một lý do nào đó họ không thể đọc được đối tượng của tôi đúng cách. Cảm ơn bạn đã lưu ý phiên bản đẹp của chuỗi. :)
MightyMouse

2
Điều này ai đó thực sự nên phân tích chuỗi JSON thành các đối tượng hoặc sử dụng tiện ích mở rộng trình duyệt , thay vì cố gắng thực hiện bất kỳ việc đọc nào bằng tay.
bevacqua

2
@akshay Thậm chí tốt hơn, res.sendsẽ tự động đặt thành content-typeJSON, nếu mục được gửi là một đối tượng hoặc mảng.
royhowie

3
Tôi nghĩ bạn có ý định sử dụng res.end()trong httpví dụ (không thể hiện) của bạn
Tobias Fünke

2
@ TobiasFünke là đúng tôi nghĩ. res.send()không hoạt động. Hãy sửa nó, nếu đó là một sai lầm. res.end()đang hoạt động chính xác. Cảm ơn bạn btw.
Kaushal28

409

Vì Express.js 3x, đối tượng phản hồi có phương thức json () đặt tất cả các tiêu đề chính xác cho bạn và trả về phản hồi ở định dạng JSON.

Thí dụ:

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

Cảm ơn bạn đã dành thời gian. Tuy nhiên, câu hỏi của tôi không thực sự về tiêu đề hồi đó. Đó là nhiều hơn về kết quả mà người ta có thể thấy nói qua curl. Dù sao cũng cảm ơn.
MightyMouse

53
OK, nhưng phương thức này cũng trả về JSON được định dạng đúng. Nó là một phần của phản ứng. Vì vậy, res.json () thiết lập các tiêu đề chính xác và sau đó trả lời tự động cho JSON.opesify () cho bạn.
JamieL

19

Nếu bạn đang cố gắng gửi một tệp json, bạn có thể sử dụng các luồng

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

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

10
Fs là gì, ống là gì, những gì có thể đọc được? Câu trả lời của bạn có nhiều bí ẩn
Aakash Dave


6

nếu bạn đang sử dụng Express bạn có thể sử dụng điều này:

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

hoặc chỉ cái này

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

5

Bạn chỉ có thể làm đẹp nó bằng cách sử dụng đường ống và một trong nhiều bộ xử lý. Ứng dụng của bạn phải luôn đáp ứng với tải càng nhỏ càng tốt.

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

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


4

Bạn có thể tạo một trình trợ giúp cho điều đó: Tạo một hàm trợ giúp để bạn có thể sử dụng nó ở mọi nơi trong ứng dụng của bạn

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

Đây là lộ trình chủ đề của tôi, nơi tôi đang cố gắng để có được tất cả các chủ đề

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

Phản hồi chúng tôi nhận được

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

Bạn có thể sử dụng phần mềm trung gian để đặt Loại nội dung mặc định và đặt Loại nội dung khác nhau cho các API cụ thể. Đây là một ví dụ:

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

Đối với một nửa tiêu đề của câu hỏi, tôi sẽ hét lên res.typeở đây:

res.type('json')

tương đương với

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

Nguồn: tài liệu thể hiện :

Đặt tiêu đề HTTP Loại nội dung thành loại MIME được xác định bởi mime.lookup () cho loại được chỉ định. Nếu loại có chứa ký tự / loại, thì nó đặt Kiểu nội dung thành loại.


1

Phiên bản cũ hơn của Express sử dụng app.use(express.json())hoặc bodyParser.json() đọc thêm về phần mềm trung gian bodyParser

Trên phiên bản mới nhất của express chúng ta chỉ cần sử dụng 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}`))

Bạn ơi, bạn đang bối rối đáp ứng với yêu cầu. Phần mềm trung gian BodyParser là để phân tích yêu cầu để đó req.bodylà đối tượng được gửi dưới dạng phần thân của yêu cầu.
Matthias Hryniszak
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.