29

The Mongoose documentation for toObject lists features, options, and gives examples of functionality of toObject.

The Mongoose documentation for toJSON says the options are the same as toObject, but doesn't explain what toJSON does. Elsewhere the documentation says

toJSON is exactly the same as the toObject option but only applies when the document's toJSON method is called.

Is toJSON an alias of toObject? If not, what are the differences?

4 Answers 4

31

A look at the source code reveals that both methods call an internal $toObject method, but with toJSON passing a second, true parameter:

Document.prototype.toObject = function (options) {
  return this.$toObject(options);
};
...
Document.prototype.toJSON = function (options) {
  return this.$toObject(options, true);
};

That second parameter determines whether $toObject uses the toJSON or toObject schema options for its defaults. So unless those schema options are configured differently, the two methods are identical.

1
  • 2
    As a side note it actually makes sense to use a different configuration of toJSON - you can do some transformations before returning an object from controller (in express res.json(object) calls JSON.stringify that is object.toJSON) - for instance depopulate some entries to avoid stack overflow...
    – kboom
    Commented Apr 12, 2017 at 11:21
9

Like JohnnyHK's anwser said, there is no difference between toJSON and toObject. My guess is that, toJSON was created to support the JSON.stringify method.

From the MDN document, if an object has the toJSON property as a function, JSON.stringify will use the toJSON function to serialize the object instead of the object itself.

5

For my use case, this is what I got:

  • .toJSON's advantage is that it's used automatically by JSON.stringify. If you set the schema option toJSON to your re-shaping options, then an object with the proper shape will be built when you stringify a document with that schema

  • .toObject's advantage is that some times JSON.stringify runs after breaking the link between the document and the schema, so that no re-shaping can happen. In such a case, you just call the document method toObject with those options to get an object with the proper shape.

Example

  • Having:
const reshapingOptions = {

    // include .id (it's a virtual)
    virtuals: true,

    // exclude .__v
    versionKey: false,

    // exclude ._id
    transform: function (doc, ret) {
        delete ret._id;
        return ret;
    },

};

const friendSchema = mongoose.Schema({ 
    givenName: String,
    familyName: String,
}, { toJSON: reshapingOptions });

const friendModel = mongoose.model('Friend', friendSchema);

const john = friendModel.findOne({ givenName: 'John' });
if (!john) {
    res.status(404).json({ error: 'No John Found' });
}
  • the statement

    JSON.stringify(john);
    

    returned:

{
    "id": "...",
    "givenName": "John",
    "familyName": "Doe"
}
  • but this equally innocent statement

    JSON.stringify({ 
        ...john, // the spread breaks the link
        role: 'dummy friend' 
    })
    

    suddenly returned:

{
    "_id": "...",
    "givenName": "John",
    "familyName": "Doe",
    "__v": 0,
    "role": "dummy friend"
}
  • So that I used

    res.json({ 
        ...john.toObject(reshapingOptions), 
        role: 'dummy friend' 
    })
    

    to get:

{
    "id": "...",
    "givenName": "John",
    "familyName": "Doe",
    "role": "dummy friend"
}
2

While developing a plugin for the toObject and toJSON methods, I discovered that toObject is also called during save operations. This can be detrimental. For example, if a plugin that sets toObject (like mine) alters fields, the result of that alteration will be persisted.

2
  • This might be an issue to bring up on Github: github.com/Automattic/mongoose/issues Commented Aug 19, 2016 at 22:03
  • @steampowered Fred I am using .toObject() and on the object whose value I am assiging from docs.toObject(), I am changing the values, but when I am calling docs.save then the value changed by new object is not there in MongoDB. Which i want to happen so everything is working perfectly for me, Can you please tell me how was it detrimental for your case? I don't get you? Commented Nov 19, 2018 at 23:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.