Правильний спосіб повернути 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"
}
$

Чи є спосіб створити точно такий самий орган у відповіді з сервера за допомогою вузла або express? Зрозуміло, що можна встановити заголовки і вказати, що тип відповіді відповіді буде "application / json", але тоді існують різні способи запису / відправлення об'єкта. Те, що я бачив, як часто використовується, - це використання команди команди:

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

Однак у цьому є два моменти, де можна міркувати, ніби це "проблеми":

  • Ми надсилаємо рядок.
  • Більше того, в кінцевому підсумку немає нового символу рядка.

Інша ідея полягає у використанні команди:

response.send(anObject);

Здається, це відправлення об'єкта JSON на основі виводу curl, подібного до першого прикладу вище. Однак у кінці тіла немає нового символу рядка, коли curl знову використовується на терміналі. Отже, як можна насправді записати щось подібне з новим символом рядка, доданим в кінці кінців, використовуючи вузол або вузол / експрес?

Відповіді:


620

Цей відповідь також є рядком, якщо ви хочете надіслати відповідь попередньо, з якоїсь незручної причини, ви можете використовувати щось на зразок 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'щоб цього досягти.

Експрес

Висловлюючи це, ви можете зробити це, змінивши параметри замість цього .

'json replacer' Зворотний виклик замінника JSON, за замовчуванням нуль

'json spaces' Простіри відповідей JSON для форматування, за замовчуванням 2 у розробці, 0 у виробництві

Насправді не рекомендується встановлювати 40

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

Тоді ви могли просто відповісти якимось json.

res.json({ a: 1 });

Він буде використовувати 'json spacesконфігурацію, щоб покращити її.


3
Спасибі за ваш час. Якщо чесно з тобою, у мене немає проблеми з мого боку. Просто хтось (в різних часових поясах) скаржився на формат, який я використовував, тому що він хотів зробити дію, і чомусь вони не змогли прочитати мій об’єкт належним чином. Дякуємо, що відмітили приємну версію stringify. :)
— MightyMouse

2
Цей хтось справді повинен розбирати рядок JSON на об’єкти або використовувати розширення браузера , а не намагатися робити будь-яке читання вручну.
— bevacqua

2
@akshay Ще краще, res.sendавтоматично встановить значення content-typeJSON, якщо надісланий елемент є об'єктом або масивом.
— royhowie

3
Я думаю, ти мав намір використати res.end()у своєму http(
— неекспрес

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, що таке pipe, що читається? Ваша відповідь - більше загадка
— Аакаш Дейв

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 u, ви можете використовувати це:

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

або просто це

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

5

Ви можете просто задекорувати його за допомогою труби та одного з багатьох процесорів. Ваш додаток завжди повинен відповідати якомога меншим навантаженням.

$ 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-заголовок Content-Type на тип MIME, як визначено mime.lookup () для вказаного типу. Якщо тип містить символ "/", він встановлює тип "Тип вмісту".


1

Старіша версія експрес-використання 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тобто об'єкт, що надсилається як тіло запиту.
— Маттіас Гринішак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.