使用节点或Express返回JSON的正确方法


437

因此,可以尝试获取以下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"
}
$

有没有一种方法可以使用node或express在服务器的响应中生成完全相同的主体?显然,可以设置标头并指示响应的内容类型将为“ application / json”,但是存在多种写入/发送对象的方法。我经常看到的一种是通过使用以下形式的命令:

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

但是,这有两点可以使人争辩为“问题”:

  • 我们正在发送一个字符串。
  • 此外,最后没有换行符。

另一个想法是使用命令:

response.send(anObject);

这似乎是基于curl的输出发送JSON对象,类似于上面的第一个示例。但是,当在终端上再次使用curl时,在主体的末端没有换行符。那么,如何使用node或node / express实际写下这样的内容并在末尾添加换行符呢?

Answers:


617

该响应也是一个字符串,如果您要发送经过修饰的响应,出于某种尴尬的原因,您可以使用类似 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}

美化:

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'

表达

在Express中,您可以通过更改选项来实现

'json replacer' JSON替换器回调,默认为null

'json spaces' 用于格式化的JSON响应空间,开发中默认为2,生产中默认为0

实际不建议设置为40

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

然后,您可以使用一些json进行响应。

res.json({ a: 1 });

它将使用'json spaces'配置进行美化。


3
感谢您的时间。老实说,我没有任何问题。只是有人(在不同时区)抱怨我使用的格式是因为他想获取,并且由于某种原因他们无法正确读取我的对象。感谢您注意到stringify的漂亮版本。:)
MightyMouse

2
这个人确实应该将JSON字符串解析为对象,或使用浏览器扩展,而不是尝试手动进行任何读取。
bevacqua 2013年

2
@akshay 如果发送的项目是对象或数组,甚至会更好,res.send它将自动设置content-type为JSON。
royhowie 2015年

3
我认为您打算res.end()在您的http(非表达)示例中使用
TobiasFünke,2016年

2
@TobiasFünke我认为是正确的。res.send()不管用。如果有误,请更正它。res.end()工作正常。谢谢顺便说一句。
Kaushal28年

409

从Express.js 3x开始,响应对象具有json()方法,该方法可以为您正确设置所有标头,并以JSON格式返回响应。

例:

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

感谢您的时间。但是,我当时的问题不是关于标头的。人们可以通过卷曲看到的结果更多是关于结果。无论如何再次感谢。
MightyMouse 2014年

53
可以,但是此方法还可以返回格式正确的JSON。这是响应的一部分。因此res.json()设置正确的标头,然后JSON.stringify()自动为您响应。
JamieL 2014年

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


6

如果您使用的是Express,则可以使用以下方法:

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

或者只是这个

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


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

您可以使用中间件来设置默认的Content-Type,并为特定的API设置不同的Content-Type。这是一个例子:

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')

资料来源:express docs

将Content-Type HTTP标头设置为mime.lookup()为指定类型确定的MIME类型。如果type包含“ /”字符,则它将Content-Type设置为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,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.