Корректный способ вернуть JSON с использованием Node.js или Express
Я пытаюсь извлечь следующий 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.js или Express? Очевидно, что можно установить заголовки и указать, что content-type ответа будет "application/json", но существует несколько способов передачи объекта. Наиболее распространенный способ, который я видел, это использование команды:
response.write(JSON.stringify(anObject));
Однако здесь есть два момента, которые можно назвать "проблемами":
- Мы отправляем строку.
- Кроме того, в конце отсутствует символ новой строки.
Другой возможный подход — использовать команду:
response.send(anObject);
Кажется, что это отправляет JSON-объект, который по своему выходу аналогичен первому примеру. Однако при повторном выполнении curl в терминале также не появляется символа новой строки в конце тела ответа. Как можно добиться такого же результата с добавленным символом новой строки в конце, используя Node.js или Express?
5 ответ(ов)
Начиная с версии Express.js 3.x, объект ответа (response object) имеет метод json()
, который автоматически устанавливает все необходимые заголовки и возвращает ответ в формате JSON.
Пример использования:
res.json({"foo": "bar"});
Этот метод упрощает процесс отправки JSON-ответов и обеспечивает корректную настройку заголовков, таких как Content-Type: application/json
.
Если вы используете Express, вы можете сделать это следующим образом:
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({key: "value"}));
или просто так:
res.json({key: "value"});
Второй способ более предпочтителен, так как res.json
автоматически устанавливает заголовок Content-Type
и преобразует объект в JSON.
Если вы пытаетесь отправить JSON-файл, вы можете использовать потоки. Вот пример:
var fs = require('fs');
var path = require('path');
var usersFilePath = path.join(__dirname, 'users.min.json');
apiRouter.get('/users', function(req, res){
var readable = fs.createReadStream(usersFilePath);
readable.pipe(res);
});
В этом коде создается читаемый поток из файла users.min.json
, и затем этот поток передается напрямую в ответ (res
). Таким образом, данные JSON будут отправлены клиенту.
Вы можете создать вспомогательную функцию для этого, чтобы использовать её везде в приложении. Вот пример такой функции:
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
}
]
}
Таким образом, вы можете удобно обрабатывать стандартные ответы в вашем приложении, что обеспечивает стандартизацию и упрощает код.
Вы можете просто отформатировать вывод с помощью pipe
и одного из многих процессоров. Ваше приложение должно всегда возвращать ответ с минимальной нагрузкой.
Вот пример команды, которую можно использовать:
$ curl -i -X GET http://echo.jsontest.com/key/value/anotherKey/anotherValue | underscore print
Ссылка на инструмент: underscore-cli на GitHub.
Как разобрать JSON с помощью Node.js? [закрыто]
Как получить параметры GET после "?" в Express?
Включение HTTPS в express.js
Express 4: Middleware для обработки ошибок не вызывается
Как вернуть результаты Mongoose из метода find?