Mongoose 的 toObject 文档 列出了 toObject 的特性、选项,并提供了 toObject 功能的示例。
toJSON
的 Mongoose 文档表示该选项与 toObject 相同,但并未解释 toJSON
的作用。在文档的其他地方,有这样的说明:
当调用文档的 toJSON 方法时,toJSON 与 toObject 选项完全相同。
toJSON
是 toObject
的别名吗?如果不是,它们有什么区别?
Mongoose 的 toObject 文档 列出了 toObject 的特性、选项,并提供了 toObject 功能的示例。
toJSON
的 Mongoose 文档表示该选项与 toObject 相同,但并未解释 toJSON
的作用。在文档的其他地方,有这样的说明:
当调用文档的 toJSON 方法时,toJSON 与 toObject 选项完全相同。
toJSON
是 toObject
的别名吗?如果不是,它们有什么区别?
查看源代码可知,这两种方法都调用了内部的$toObject
方法,但是toJSON
传递了第二个参数true
:
Document.prototype.toObject = function (options) {
return this.$toObject(options);
};
...
Document.prototype.toJSON = function (options) {
return this.$toObject(options, true);
};
第二个参数决定$toObject
是否使用toJSON
或toObject
模式选项作为默认值。因此,除非这些模式选项已经配置不同,否则这两种方法是相同的。
就像JohnnyHK的回答所说,toJSON
和toObject
之间没有区别。我猜测,toJSON
是为了支持JSON.stringify
方法而创建的。
根据MDN文档,如果一个对象有toJSON
属性作为函数,JSON.stringify
会使用toJSON
函数来序列化对象,而不是使用对象本身。
根据我的使用情况,我得到了以下结果:
.toJSON
的优点是它会被JSON.stringify
自动使用。如果你将模式选项toJSON
设置为重新塑造选项,则当您对具有该模式的文档进行字符串化时,将构建一个具有正确形状的对象。
.toObject
的优点在于有时候JSON.stringify
在打破文档和模式之间的链接后运行,这样就不会发生重新塑造。在这种情况下,您只需使用那些选项调用文档方法toObject
,即可获得具有正确形状的对象。
示例
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"
}
在开发一个插件的过程中,我发现在保存操作期间也会调用toObject
方法。这可能会有害。例如,如果一个设置了toObject
的插件(就像我的插件)改变了字段,那么该更改的结果将被持久化。