594

So, one can attempt to fetch the following JSON object:

$ 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"
}
$

Is there a way to produce exactly the same body in a response from a server using node or express? Clearly, one can set the headers and indicate that the content-type of the response is going to be "application/json", but then there are different ways to write/send the object. The one that I have seen commonly being used is by using a command of the form:

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

However, this has two points where one could argue as if they were "problems":

  • We are sending a string.
  • Moreover, there is no new line character in the end.

Another idea is to use the command:

response.send(anObject);

This appears to be sending a JSON object based on the output of curl similar to the first example above. However, there is no new line character in the end of the body when curl is again being used on a terminal. So, how can one actually write down something like this with a new line character appended in the end using node or node/express?

MightyMouse
  • 13,208
  • 8
  • 33
  • 43

11 Answers11

807

That response is a string too, if you want to send the response prettified, for some awkward reason, you could use something like JSON.stringify(anObject, null, 3)

It's important that you set the Content-Type header to application/json, too.

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}

Prettified:

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

I'm not exactly sure why you want to terminate it with a newline, but you could just do JSON.stringify(...) + '\n' to achieve that.

Express

In express you can do this by changing the options instead.

'json replacer' JSON replacer callback, null by default

'json spaces' JSON response spaces for formatting, defaults to 2 in development, 0 in production

Not actually recommended to set to 40

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

Then you could just respond with some json.

res.json({ a: 1 });

It'll use the 'json spaces' configuration to prettify it.

Community
  • 1
  • 1
bevacqua
  • 47,502
  • 56
  • 171
  • 285
  • 3
    Thank you for your time. To be honest with you, I do not have a problem on my end. It is just that someone (in different timezone) complained about the format that I was using because he wanted to do a get and for some reason they could not read my object properly. Thanks for noting the nice version of stringify. :) – MightyMouse Oct 31 '13 at 00:36
  • 2
    This someone should really be parsing the JSON string into objects, or [using a browser extension](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?hl=en), rather than trying to do any reading by hand. – bevacqua Oct 31 '13 at 00:47
  • 1
    When I use `curl` from the command line, it is nice to have the newline at the end of the output so that my command prompt does not get jammed onto the end of the output. – amacleod Jan 25 '15 at 20:10
  • 3
    @akshay Even better, [`res.send`](http://expressjs.com/api.html#res.send) will automatically set the `content-type` to JSON, if the sent item is an object or array. – royhowie Apr 12 '15 at 00:58
  • Nope, res.json() does not stand deprecated?http://expressjs.com/api.html#res.json – Sharjeel Ahmed Aug 18 '15 at 11:12
  • @akshay That looks quite silly. Could you provide the source please? – Alexander Gonchiy Aug 29 '15 at 14:24
  • stupidity on my part. I meant to say you cannot specify the status if you ever wanted to do that. My bad. you can use `res.json([body])` or `res.status(statusCode).json([body])` – akshay Aug 30 '15 at 15:05
  • @bevacqua Having human unreadable responses defies the purpose of REST and JSON. So most popular REST APIs like github, stackoverflow always return prettified JSON. Over gzip encoding that you should anyway use the difference is only few bytes. – Max Dec 03 '15 at 10:01
  • thanks for res.json({}), it's work perfect on my app – yussan Apr 13 '16 at 07:31
  • 3
    I think you meant to use `res.end()` in your `http` (non-express) example – Tobias Fünke Aug 05 '16 at 11:00
  • 2
    @TobiasFünke is right i think. `res.send()` is not working. Please correct it, if it is a mistake. `res.end()` is working correctly. Thank you btw. – Kaushal28 Jun 07 '17 at 19:49
  • According to the docs: https://nodejs.org/api/http.html#http_request_write_chunk_encoding_callback `setHeader` isn't a Node method. It's an Express method. – Joseph Cho Sep 17 '19 at 15:37
  • @JosephCho You're confused. It's from Node. See: https://nodejs.org/api/http.html#http_request_setheader_name_value – bevacqua Sep 25 '19 at 02:03
  • @bevacqua You are right I am wrong. I'm not sure why it didn't work for me. – Joseph Cho Sep 25 '19 at 02:08
489

Since Express.js 3x the response object has a json() method which sets all the headers correctly for you and returns the response in JSON format.

Example:

res.json({"foo": "bar"});
JamieL
  • 5,573
  • 1
  • 18
  • 9
  • Thank you for your time. However, my question was not really about headers back then. It was more about the outcome that one could see say through curl. Thanks again anyway. – MightyMouse Apr 22 '14 at 09:13
  • 59
    OK, but this method also returns properly formatted JSON as well. It is part of the response. So res.json() sets correct headers and then JSON.stringify()'s the response for you automatically. – JamieL May 09 '14 at 16:11
49

If you're using Express, you can use this:

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

or just this

res.json({key:"value"});
Jonathin
  • 127
  • 1
  • 12
IXOVER
  • 531
  • 4
  • 4
27

The res.json() function should be sufficient for most cases.

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

The res.json() function converts the parameter you pass to JSON using JSON.stringify() and sets the Content-Type header to application/json; charset=utf-8 so HTTP clients know to automatically parse the response.

vkarpov15
  • 3,614
  • 24
  • 21
21

If you are trying to send a json file you can use streams

var fs = require('fs');

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

apiRouter.get('/users', function(req, res){
    var readable = fs.createReadStream(usersFilePath);
    readable.pipe(res);
});
user2878850
  • 2,446
  • 1
  • 18
  • 22
Connor Leech
  • 18,052
  • 30
  • 105
  • 150
  • 14
    What is fs, what is pipe, what is readable? Your answer is more of a mystery – Aakash Dave Dec 30 '18 at 22:42
  • `readable` is something that implements the node.js stdlinbs stream interface, see https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options – mb21 Jul 09 '20 at 14:53
11

You can make a helper for that: Make a helper function so that you can use it everywhere in your application

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

Here is my topic route where I am trying to get all topics

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

Response we get

{
"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
  • 301
  • 3
  • 7
  • Why do you have a status in the body? That's the entire point of HTTP status codes. Also why do you have a blank message? If status is an error, then just have the message. Only thing in response should be the array of objects. I see this everywhere, people using "data": and it's a nightmare because you have to write custom json parsing for it. You usually can't just use json libraries. There is no benefit to this anti pattern. – Yoker Jul 10 '20 at 14:11
  • @Yoker it's up to you brother what you want as a response my frontend requirement was that so I send this in that format if you want in other you are free to goo. The code I shared is just to explain how we can send JSON response in node using helpers. – Nishant Aug 19 '20 at 11:57
  • Plus one, I need some code after `res.json()`, so I used `return res.json(foo)` to avoid `Cannot set headers after they are sent to the client` – Timo Jul 22 '22 at 17:23
9

For the header half of the question, I'm gonna give a shout out to res.type here:

res.type('json')

is equivalent to

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

Source: express docs:

Sets the Content-Type HTTP header to the MIME type as determined by mime.lookup() for the specified type. If type contains the “/” character, then it sets the Content-Type to type.

MalcolmOcean
  • 2,807
  • 2
  • 29
  • 38
5

You can just prettify it using pipe and one of many processor. Your app should always response with as small load as possible.

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

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

pawelzny
  • 51
  • 1
  • 1
5

You can use a middleware to set the default Content-Type, and set Content-Type differently for particular APIs. Here is an example:

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
  • 27,235
  • 10
  • 114
  • 113
2

Older version of Express use app.use(express.json()) or bodyParser.json() read more about bodyParser middleware

On latest version of express we could simply use 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
  • 392
  • 2
  • 8
  • 1
    My dear, you are confusing response with request. BodyParser middleware is for parsing the request so that `req.body` is the object sent as body of the request. – Matthias Hryniszak Feb 04 '19 at 15:30
-1

Here is the Solution:

//Here, JSON object is doc  
const M={"First Name":doc.First_Name,
          "Last Name":doc.Last_Name,
          "Doctor's Email":doc.Email,
          "Doctors Picture Link":doc.Image};
   res.write(JSON.stringify(M,null,10)+"\n");
   res.end();

other ways to just to render the Object

console.log(doc);
res.json(doc);
//Here,M is referred from the above code it is contains doc Object
res.send(M);

How I am getting the Object using Mongoose:

//Here, Handles contains my MongoDB Schema.
const NN=Handles.findOne().lean().exec(function(err, doc) {
console.log(doc);
});

ABHI SHEK
  • 85
  • 6