Làm thế nào để trả về một phản hồi JSON phức tạp với Node.js?


82

Sử dụng nodejs và express, tôi muốn trả về một hoặc nhiều đối tượng (mảng) bằng JSON. Trong đoạn mã bên dưới, tôi xuất một đối tượng JSON tại một thời điểm. Nó hoạt động nhưng đây không phải là chính xác những gì tôi muốn. Phản hồi được tạo không phải là phản hồi JSON hợp lệ vì tôi có nhiều đối tượng.

Tôi biết rõ rằng tôi có thể chỉ cần thêm tất cả các đối tượng vào một mảng và trả về mảng cụ thể đó trong res.end. Tuy nhiên, tôi sợ điều này có thể trở nên nặng nề để xử lý và tốn nhiều bộ nhớ.

Cách thích hợp để đạt được điều này với nodejs là gì? Query.each có phải là phương thức phù hợp để gọi không?

app.get('/users/:email/messages/unread', function(req, res, next) {
    var query = MessageInfo
        .find({ $and: [ { 'email': req.params.email }, { 'hasBeenRead': false } ] });

    res.writeHead(200, { 'Content-Type': 'application/json' });   
    query.each(function(err, msg) {
        if (msg) { 
            res.write(JSON.stringify({ msgId: msg.fileName }));
        } else {
            res.end();
        }
    });
});

Câu trả lời:


183

Trên express 3, bạn có thể sử dụng trực tiếp res.json ({foo: bar})

res.json({ msgId: msg.fileName })

Xem tài liệu


9
Làm thế nào để làm điều đó mà không cần thể hiện?
Piotrek

@ Ludwik11 res.write(JSON.stringify(foo)). Nếu foolớn, bạn có thể cần phải cắt nhỏ nó (xâu chuỗi, sau đó viết từng đoạn một). Có lẽ cũng muốn đặt tiêu đề của bạn "Content-Type":"application/json"hoặc tương tự nếu thích hợp.
OJFord

21

Tôi không biết liệu điều này có thực sự khác biệt hay không, nhưng thay vì lặp lại con trỏ truy vấn, bạn có thể làm điều gì đó như sau:

query.exec(function (err, results){
  if (err) res.writeHead(500, err.message)
  else if (!results.length) res.writeHead(404);
  else {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.write(JSON.stringify(results.map(function (msg){ return {msgId: msg.fileName}; })));
  }
  res.end();
});

12

[Chỉnh sửa] Sau khi xem xét tài liệu Mongoose, có vẻ như bạn có thể gửi từng kết quả truy vấn dưới dạng một đoạn riêng biệt; máy chủ web sử dụng mã hóa chuyển theo từng đoạn theo mặc định, vì vậy tất cả những gì bạn phải làm là quấn một mảng xung quanh các mục để biến nó thành đối tượng JSON hợp lệ.

Đại khái (chưa được kiểm tra):

app.get('/users/:email/messages/unread', function(req, res, next) {
  var firstItem=true, query=MessageInfo.find(/*...*/);
  res.writeHead(200, {'Content-Type': 'application/json'});
  query.each(function(docs) {
    // Start the JSON array or separate the next element.
    res.write(firstItem ? (firstItem=false,'[') : ',');
    res.write(JSON.stringify({ msgId: msg.fileName }));
  });
  res.end(']'); // End the JSON array and response.
});

Ngoài ra, như bạn đã đề cập, bạn có thể chỉ cần gửi nội dung mảng như hiện tại. Trong trường hợp này, phần thân phản hồi sẽ được lưu vào bộ đệm và được gửi ngay lập tức, điều này có thể tiêu tốn một lượng lớn bộ nhớ bổ sung (cao hơn những gì cần thiết để lưu trữ kết quả) cho các tập kết quả lớn. Ví dụ:

// ...
var query = MessageInfo.find(/*...*/);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(query.map(function(x){ return x.fileName })));

Đây là một ý tưởng tốt. Tuy nhiên nó trông hơi khó hiểu với tôi. Tôi đã hy vọng nodejs cung cấp một cái gì đó thanh lịch hơn một chút.
Martin
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.