10

What is the difference between

res.status(STATUS_CODE).send({"message" : "this is the message" });

and

res.status(STATUS_CODE).json({"message" : "this is the message" });

although checked the similar question but that is in context of express 3 and I am looking for express 4

Community
  • 1
  • 1
xkeshav
  • 53,360
  • 44
  • 177
  • 245
  • Possible duplicate of [Difference between res.send and res.json in Express.js](https://stackoverflow.com/questions/19041837/difference-between-res-send-and-res-json-in-express-js) – Roko C. Buljan Mar 28 '18 at 21:02

2 Answers2

16

Ultimately, both will achieve the same thing. If you call res.send with an object, it will hit this switch in res.send:

switch (typeof chunk) {
// string defaulting to html
case 'string':
  if (!this.get('Content-Type')) {
    this.type('html');
  }
  break;
case 'boolean':
case 'number':
case 'object':
  if (chunk === null) {
    chunk = '';
  } else if (Buffer.isBuffer(chunk)) {
    if (!this.get('Content-Type')) {
      this.type('bin');
    }
  } else {
    return this.json(chunk);
  }
  break;
}

If the object you're sending it is not a Buffer - it will call res.json.

res.json simply sets the Content-Type header to application/json and runs the object through JSON.stringify - with specified replacer function and spacer value. Eventually it calls res.send.

This call of res.send is sent a string and the case statement will break resulting in the rest of the function being run. The remainder of the send function sets things like etag, content size etc. You can find out more by looking at the express code.

They start to differ when you send them non-object responses, such as strings, numbers etc. As in that case res.json will run it through JSON.stringify but res.send wont: resulting in different Content-Type headers and content.

edit: to answer your comment on the other answer, sending different status codes will still behave the same.

MrWillihog
  • 2,586
  • 19
  • 17
  • I havn't specified replacer function and spacer value on any page and running `res.json`, does this break some way? – xkeshav Jun 08 '16 at 10:13
  • No, in that case it just uses the default (which is undefined). Effectively resulting in a vanilla call to JSON.stringify(). – MrWillihog Jun 08 '16 at 10:16
  • do not understand :( do I need to write `.send(JSON.stringify({"message" :"message here"}))`? – xkeshav Jun 08 '16 at 10:28
  • 1
    Ah, no. Sorry. You don't need to do that. You can ignore the replacer and spacer settings. They are for controlling how the json is formatted, default is fine for most cases. – MrWillihog Jun 08 '16 at 10:30
4

.json calls .toJSON() method on the object (if it exists) and also sets the content-type header to application/json

But basically you can simulate .json with .send, if you do the above manually.


For example this middleware

(req, res, next) => {
    let x = {};
    x.toJSON = () => {
        console.log('oh yeah');
        return 15;
    };

    return res.json(x);
}

Prints

oh yeah

And returns 15 to the request with these headers (at least in my simple express app):

Connection →keep-alive
Content-Length →2
Content-Type →application/json; charset=utf-8
Date →Wed, 08 Jun 2016 10:16:09 GMT
ETag →W/"2-m/Mcf/Bik2qW08i9H48v8w"
Vary →Accept-Encoding
X-Powered-By →Express
libik
  • 22,239
  • 9
  • 44
  • 87