วิธีที่เหมาะสมในการส่งคืน JSON โดยใช้โหนดหรือ Express


440

ดังนั้นหนึ่งสามารถพยายามดึงวัตถุ 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"
}
$

มีวิธีการสร้างเนื้อเดียวกันในการตอบสนองจากเซิร์ฟเวอร์โดยใช้โหนดหรือด่วน? เห็นได้ชัดว่าใครสามารถตั้งค่าส่วนหัวและระบุว่าเนื้อหาประเภทของการตอบสนองจะเป็น "application / json" แต่แล้วมีวิธีที่แตกต่างกันในการเขียน / ส่งวัตถุ สิ่งที่ฉันได้เห็นการใช้งานทั่วไปคือการใช้คำสั่งของแบบฟอร์ม:

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

อย่างไรก็ตามมีสองจุดที่สามารถโต้เถียงราวกับว่าพวกเขาเป็น "ปัญหา":

  • เรากำลังส่งสตริง
  • ยิ่งกว่านั้นไม่มีอักขระบรรทัดใหม่ในตอนท้าย

แนวคิดอื่นคือการใช้คำสั่ง:

response.send(anObject);

สิ่งนี้ดูเหมือนว่าจะส่งวัตถุ JSON ตามผลลัพธ์ของ curl คล้ายกับตัวอย่างแรกข้างต้น อย่างไรก็ตามไม่มีอักขระขึ้นบรรทัดใหม่ในตอนท้ายของเนื้อความเมื่อมีการใช้ขดในเทอร์มินัลอีกครั้ง ดังนั้นเราจะเขียนบางสิ่งเช่นนี้ด้วยอักขระบรรทัดใหม่ต่อท้ายด้วยการใช้ node หรือ node / express ได้อย่างไร?

คำตอบ:


620

การตอบสนองนั้นเป็นสตริงเช่นกันหากคุณต้องการส่งการตอบกลับที่ prettified ด้วยเหตุผลบางอย่างที่น่าอึดอัดใจคุณสามารถใช้สิ่งที่ชอบ JSON.stringify(anObject, null, 3)

เป็นสิ่งสำคัญที่คุณต้องตั้งค่าContent-Typeส่วนหัว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
// >  }

ฉันไม่แน่ใจว่าทำไมคุณต้องการยุติด้วยการขึ้นบรรทัดใหม่ แต่คุณสามารถทำได้JSON.stringify(...) + '\n'เพื่อให้บรรลุ

ด่วน

ด่วนคุณสามารถทำเช่นนี้โดยการเปลี่ยนแปลงตัวเลือกแทน

'json replacer' JSON โทรกลับ replacer เป็นโมฆะโดยค่าเริ่มต้น

'json spaces' พื้นที่ตอบสนอง JSON สำหรับการจัดรูปแบบเริ่มต้นที่ 2 ในการพัฒนา 0 ในการผลิต

ไม่แนะนำให้ตั้งเป็น 40

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

จากนั้นคุณสามารถตอบสนองด้วย json บางอย่าง

res.json({ a: 1 });

มันจะใช้การ'json spacesกำหนดค่า 'เพื่อ prettify


3
ขอขอบคุณสำหรับเวลาของคุณ. เพื่อที่จะซื่อสัตย์กับคุณฉันไม่ได้มีปัญหาในตอนท้ายของฉัน เป็นเพียงแค่บางคน (ในเขตเวลาที่แตกต่างกัน) บ่นเกี่ยวกับรูปแบบที่ฉันใช้เพราะเขาต้องการทำเพื่อรับและด้วยเหตุผลบางอย่างที่พวกเขาไม่สามารถอ่านวัตถุของฉันอย่างถูกต้อง ขอบคุณที่สังเกต stringify รุ่นที่ดี :)
MightyMouse

2
บางคนนี้ควรแยกสตริง JSON เป็นวัตถุหรือใช้ส่วนขยายของเบราว์เซอร์แทนที่จะพยายามอ่านด้วยมือ
bevacqua

2
@akshay ยิ่งดีกว่าres.sendจะตั้งเป็นcontent-typeJSON โดยอัตโนมัติหากรายการที่ส่งเป็นวัตถุหรืออาร์เรย์
royhowie

3
ฉันคิดว่าคุณตั้งใจจะใช้res.end()ในตัวอย่างhttp(ไม่ใช่ด่วน) ของคุณ
Tobias Fünke

2
@ TobiasFünkeถูกต้องฉันคิดว่า res.send()ไม่ทำงาน. โปรดแก้ไขถ้ามันเป็นความผิดพลาด res.end()ทำงานอย่างถูกต้อง ขอบคุณ btw
Kaushal28

410

ตั้งแต่ Express.js 3x วัตถุตอบกลับมีวิธี json () ซึ่งตั้งค่าส่วนหัวทั้งหมดให้ถูกต้องสำหรับคุณและส่งกลับการตอบสนองในรูปแบบ JSON

ตัวอย่าง:

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

ขอขอบคุณสำหรับเวลาของคุณ. อย่างไรก็ตามคำถามของฉันไม่เกี่ยวกับส่วนหัวในตอนนั้น มันเป็นเรื่องเกี่ยวกับผลลัพธ์ที่คน ๆ หนึ่งสามารถมองเห็นพูดผ่านการม้วนงอ ขอบคุณอีกครั้ง
MightyMouse

53
ตกลง แต่เมธอดนี้จะส่งคืน JSON ในรูปแบบที่เหมาะสมเช่นกัน มันเป็นส่วนหนึ่งของการตอบสนอง ดังนั้น res.json () ตั้งค่าส่วนหัวที่ถูกต้องจากนั้น JSON.stringify () คือการตอบกลับของคุณโดยอัตโนมัติ
JamieL

19

หากคุณพยายามส่งไฟล์ json คุณสามารถใช้สตรีมได้

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

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

10
fs คืออะไรท่อคืออะไรสามารถอ่านได้? คำตอบของคุณเป็นเรื่องลึกลับมากกว่า
Aakash Dave

11

res.json()ฟังก์ชั่นควรจะเพียงพอสำหรับกรณีส่วนใหญ่

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

res.json()แปลงฟังก์ชั่นพารามิเตอร์ที่คุณส่งผ่านไปยัง JSON ใช้JSON.stringify()และกำหนดContent-Typeส่วนหัวไปapplication/json; charset=utf-8เพื่อให้ลูกค้า HTTP รู้ที่จะแยกการตอบสนองโดยอัตโนมัติ


6

ถ้าคุณใช้งาน Express คุณสามารถใช้สิ่งนี้:

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

หรือแค่นี้

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

5

คุณสามารถ prettify ได้โดยใช้ไพพ์และหนึ่งในโปรเซสเซอร์จำนวนมาก แอปของคุณควรตอบสนองเมื่อโหลดน้อยที่สุดเท่าที่จะทำได้

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

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


4

คุณสามารถสร้างผู้ช่วยได้: สร้างฟังก์ชันผู้ช่วยเพื่อให้คุณสามารถใช้งานได้ทุกที่ในแอปพลิเคชันของคุณ

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

นี่คือเส้นทางหัวข้อของฉันที่ฉันพยายามรับหัวข้อทั้งหมด

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

การตอบสนองที่เราได้รับ

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

คุณสามารถใช้มิดเดิลแวร์เพื่อตั้งค่าประเภทเนื้อหาเริ่มต้นและตั้งค่าประเภทเนื้อหาแตกต่างกันสำหรับ API เฉพาะ นี่คือตัวอย่าง:

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

สำหรับส่วนหัวครึ่งหนึ่งของคำถามฉันจะส่งเสียงไปres.typeที่นี่:

res.type('json')

เทียบเท่ากับ

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

ที่มา: เอกสารด่วน :

ตั้งค่าส่วนหัว HTTP ชนิดเนื้อหาเป็นชนิด MIME ตามที่กำหนดโดย mime.lookup () สำหรับประเภทที่ระบุ หาก type มีอักขระ“ /” ดังนั้นจะกำหนดให้ประเภทเนื้อหาเป็นประเภท


1

Express เวอร์ชันเก่าใช้app.use(express.json())หรือbodyParser.json() อ่านเพิ่มเติมเกี่ยวกับมิดเดิลแวร์ bodyParser

ใน Express เวอร์ชั่นล่าสุดเราสามารถใช้ 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}`))

ที่รักคุณสับสนกับคำตอบ มิดเดิลแวร์ BodyParser ใช้สำหรับการแยกวิเคราะห์คำขอเพื่อให้req.bodyเป็นวัตถุที่ส่งเป็นเนื้อความของคำขอ
Matthias Hryniszak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.