В чем разница между Mongoose toObject и JSON?

Документация Mongoose для toObject перечисляет функции, параметры и дает примеры функций toObject.

В документации Mongoose для toJSON указано, что параметры такие же, как и для объекта, но не объясняют, что делает toJSON. В других документах говорится

toJSON точно такая же, как опция toObject, но применяется только когда вызывается метод toJSON документа.

Является ли toJSON псевдоним toObject? Если нет, каковы различия?

Ответ 1

Посмотрите на исходный код , который показывает, что оба метода вызывают внутренний метод $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 для своих значений по умолчанию. Поэтому, если эти параметры схемы не настроены по-разному, эти два метода идентичны.

Ответ 2

Как JohnnyHK anwser, нет разницы между toJSON и toObject. Я предполагаю, что toJSON был создан для поддержки метода JSON.stringify.

Из MDN document, если объект имеет свойство toJSON как функцию, JSON.stringify будет использовать toJSON чтобы сериализовать объект вместо самого объекта.

Ответ 3

При разработке плагина для методов toObject и toJSON я обнаружил, что toObject также вызывается во время операций сохранения. Это может быть вредным. Например, если плагин, который устанавливает toObject (как мой), изменяет поля, результат этого изменения будет сохранен.

Ответ 4

Для моего случая использования это то, что я получил:

  • Преимущество .toJSON заключается в том, что оно автоматически используется JSON.stringify. Если вы установите параметр схемы toJSON для параметров изменения формы, то объект с правильной формой будет создан, когда вы структурируете документ с этой схемой

  • Преимущество .toObject состоит в том, что иногда JSON.stringify запускается после разрыва связи между документом и схемой, поэтому повторное формирование невозможно. В таком случае вы просто вызываете метод документа toObject с этими параметрами, чтобы получить объект правильной формы.

Пример

  • Наличие:
const reshapingOptions = {

    // include .id (it 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' });
}
  • утверждение

    JSON.stringify(john);
    

    вернулся:

{
    "id": "...",
    "givenName": "John",
    "familyName": "Doe"
}
  • но это столь же невинное утверждение

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

    неожиданно вернулся:

{
    "_id": "...",
    "givenName": "John",
    "familyName": "Doe",
    "__v": 0,
    "role": "dummy friend"
}
  • Так что я использовал

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

    чтобы получить:

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