Maneira correta de retornar JSON usando o nó ou Express

438

Portanto, pode-se tentar buscar o seguinte objeto 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"
}
$

Existe uma maneira de produzir exatamente o mesmo corpo em uma resposta de um servidor usando o node ou express? Claramente, pode-se definir os cabeçalhos e indicar que o tipo de conteúdo da resposta será "application / json", mas existem diferentes maneiras de escrever / enviar o objeto. O que eu vi sendo comumente usado é usando um comando do formulário:

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

No entanto, isso tem dois pontos em que se pode argumentar como se fossem "problemas":

  • Estamos enviando uma string.
  • Além disso, não há um novo caractere de linha no final.

Outra idéia é usar o comando:

response.send(anObject);

Parece estar enviando um objeto JSON com base na saída de curvatura semelhante ao primeiro exemplo acima. No entanto, não há um novo caractere de linha no final do corpo quando o enrolamento está sendo usado novamente em um terminal. Então, como alguém pode escrever algo assim com um novo caractere de linha acrescentado no final usando node ou node / express?

Rato poderoso
fonte

Respostas:

619

Essa resposta também é uma string. Se você quiser enviar a resposta prettificada, por algum motivo estranho, poderá usar algo como JSON.stringify(anObject, null, 3)

É importante que você defina o Content-Typecabeçalho application/jsontambém.

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}

Pré-especificado:

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
// >  }

Não sei exatamente por que você deseja encerrá-lo com uma nova linha, mas você pode simplesmente fazer isso JSON.stringify(...) + '\n'para isso.

Expressar

No express, você pode fazer isso alterando as opções .

'json replacer' Retorno de chamada do substituto JSON, nulo por padrão

'json spaces' Espaços de resposta JSON para formatação, o padrão é 2 em desenvolvimento, 0 em produção

Não é realmente recomendado definir 40

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

Então você poderia apenas responder com algum json.

res.json({ a: 1 });

Ele usará a 'json spacesconfiguração 'para prettificá-la.

bevacqua
fonte
3
Obrigado pelo seu tempo. Para ser sincero com você, não tenho um problema do meu lado. É que alguém (em outro fuso horário) reclamou do formato que eu estava usando, porque ele queria fazer um get e, por algum motivo, não conseguiu ler meu objeto corretamente. Obrigado por observar a boa versão do stringify. :)
mightymouse
2
Esse alguém realmente deve estar analisando a string JSON em objetos ou usando uma extensão do navegador , em vez de tentar fazer qualquer leitura manualmente.
Bevacqua
2
@akshay Ainda melhor, res.sendconfigurará automaticamente o content-typeJSON, se o item enviado for um objeto ou matriz.
Royhowie 12/04/2015
3
Eu acho que você quis usar res.end()em sua http(não expresso) exemplo
Tobias Funke
2
@ TobiasFünke está certo, eu acho. res.send()não está funcionando. Corrija, se for um erro. res.end()está funcionando corretamente. Obrigado btw.
precisa saber é o seguinte
409

Desde o Express.js 3x, o objeto de resposta tem um método json () que define todos os cabeçalhos corretamente para você e retorna a resposta no formato JSON.

Exemplo:

res.json({"foo": "bar"});
JamieL
fonte
Obrigado pelo seu tempo. No entanto, minha pergunta não era realmente sobre cabeçalhos na época. Era mais sobre o resultado que se podia dizer através do curl. Mais uma vez obrigado.
MightyMouse
53
OK, mas esse método também retorna JSON formatado corretamente também. Faz parte da resposta. Então res.json () define os cabeçalhos corretos e, em seguida, JSON.stringify () é a resposta automaticamente.
JamieL
19

Se você estiver tentando enviar um arquivo json, poderá usar fluxos

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

apiRouter.get('/users', function(req, res){
    var readable = fs.createReadStream(usersFilePath);
    readable.pipe(res);
});
Connor Leech
fonte
10
O que é fs, o que é pipe, o que é legível? Sua resposta é mais um mistério
Aakash Dave
11

A res.json()função deve ser suficiente para a maioria dos casos.

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

A res.json()função converte o parâmetro que você passa para JSON usando JSON.stringify()e define o Content-Typecabeçalho para application/json; charset=utf-8que os clientes HTTP saibam analisar automaticamente a resposta.

vkarpov15
fonte
6

Se você estiver usando o Express, poderá usar o seguinte:

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

ou apenas isso

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

Você pode simplesmente prettificá-lo usando pipe e um dos muitos processadores. Seu aplicativo deve sempre responder com a menor carga possível.

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

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

pawelzny
fonte
4

Você pode ajudar: Faça uma função auxiliar para poder usá-la em qualquer lugar do aplicativo.

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

Aqui está minha rota de tópicos em que estou tentando obter todos os tópicos

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

Resposta que obtemos

{
"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
    }
      ]
}
Nishant
fonte
3

Você pode usar um middleware para definir o Tipo de Conteúdo padrão e definir o Tipo de Conteúdo de maneira diferente para APIs específicas. Aqui está um exemplo:

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>`);
})
Yuci
fonte
2

Para o cabeçalho da metade da pergunta, vou gritar res.typeaqui:

res.type('json')

é equivalente a

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

Fonte: documentos expressos :

Define o cabeçalho HTTP do tipo de conteúdo como o tipo MIME, conforme determinado por mime.lookup () para o tipo especificado. Se o tipo contiver o caractere "/", ele definirá o Tipo de conteúdo para o tipo.

MalcolmOcean
fonte
1

Versão mais antiga do Express use app.use(express.json())ou bodyParser.json() leia mais sobre o middleware bodyParser

Na versão mais recente do express, poderíamos simplesmente usar 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}`))
Aung Zan Baw
fonte
Minha querida, você está confundindo a resposta com o pedido. O middleware BodyParser é para analisar a solicitação para que req.bodyseja o objeto enviado como corpo da solicitação.
Matthias Hryniszak