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