Перетворити документи Mongoose на json


77

Я повернув мангустські документи як json таким чином:

UserModel.find({}, function (err, users) {
    return res.end(JSON.stringify(users));
}

Однак користувач .__ proto__ також був повернутий. Як я можу повернутися без нього? Я спробував це, але не працював:

UserModel.find({}, function (err, users) {
    return res.end(users.toJSON());    // has no method 'toJSON'
}

Відповіді:


151

Ви також можете спробувати mongoosejs's lean () :

UserModel.find().lean().exec(function (err, users) {
    return res.end(JSON.stringify(users));
}

9
Чи не повинно бути так: JSON.stringify(users);оскільки документи, що повертаються, lean()є звичайними об'єктами JS?
— Еньо

Так, ти маєш рацію, дякую. Слід використовувати JSON.stringify (користувачі).
— ecdeveloper

Якщо ви все-таки хочете використовувати об'єкт екземпляра mongoose у функції зворотного виклику після запиту до бази даних, ви не повинні використовувати leanфункцію. Дивіться мою відповідь на рішення. :)
— eAbi

1
будьте обережні, lean()
— Еммануель НК

54

Пізня відповідь, але ви також можете спробувати це при визначенні вашої схеми.

/**
 * toJSON implementation
 */
schema.options.toJSON = {
    transform: function(doc, ret, options) {
        ret.id = ret._id;
        delete ret._id;
        delete ret.__v;
        return ret;
    }
};

Зверніть увагу, що retце об'єкт JSON, і це не екземпляр моделі мангуста. Ви будете працювати з ним прямо на хешах об'єктів, без геттерів / сетерів.

І потім:

Model
    .findById(modelId)
    .exec(function (dbErr, modelDoc){
         if(dbErr) return handleErr(dbErr);

         return res.send(modelDoc.toJSON(), 200);
     });

Редагувати: лютий 2015 р

Оскільки я не надав рішення відсутніх методів toJSON (або toObject), я пояснити різницю між моїм прикладом використання та прикладом використання OP.

ОП:

UserModel
    .find({}) // will get all users
    .exec(function(err, users) {
        // supposing that we don't have an error
        // and we had users in our collection,
        // the users variable here is an array
        // of mongoose instances;

        // wrong usage (from OP's example)
        // return res.end(users.toJSON()); // has no method toJSON

        // correct usage
        // to apply the toJSON transformation on instances, you have to
        // iterate through the users array

        var transformedUsers = users.map(function(user) {
            return user.toJSON();
        });

        // finish the request
        res.end(transformedUsers);
    });

Мій приклад:

UserModel
    .findById(someId) // will get a single user
    .exec(function(err, user) {
        // handle the error, if any
        if(err) return handleError(err);

        if(null !== user) {
            // user might be null if no user matched
            // the given id (someId)

            // the toJSON method is available here,
            // since the user variable here is a 
            // mongoose model instance
            return res.end(user.toJSON());
        }
    });

3
Це найкращий спосіб піти.
— Даніель Кмак

@eAbi і toJSON, і toObject не визначені
— OMGPOP

@OMGPOP і toJSON, і toObject - це методи, визначені в екземплярах моделі мангуста. Ви можете надати приклад використання або опублікувати інше запитання на stackoverflow. Як наскільки мені відомо, як toJSON, так і toObject методи не були застаріли / вилучені незалежно від використовуваної версії Mongoose.
— eAbi

@eAbi його там немає. запитувач також має ту ж проблему. Ви впевнені, що телефонуєте до JSON замість JSON.stringify ()?
— OMGPOP

2
@OMGPOP Так, я впевнений, що використовую метод toJSON. Різниця між прикладом використання OP та моїм полягає в тому, що у запитанні OP повернута usersзмінна є масивом екземплярів мангуста. Ви повинні переглядати масив і викликати метод toJSON на кожному екземплярі. У моєму прикладі я використовую метод findById, який безпосередньо передає знайдений екземпляр мангуста функції зворотного виклику. Тоді ви можете безпосередньо викликати метод toJSON (або toObject) на цьому екземплярі.
— eAbi

25

Перш за все, спробувати toObject()замість toJSON()можливо?

По-друге, вам потрібно буде викликати його на власне документах, а не на масиві, тож, можливо, спробуйте щось більш надокучливе, наприклад:

var flatUsers = users.map(function() {
  return user.toObject();
})
return res.end(JSON.stringify(flatUsers));

Це здогадка, але я сподіваюся, що це допоможе


Доводиться картографувати це так дратує, хіба в бібліотеці немає чогось цього зробити?
— Ентоні

15
model.find({Branch:branch},function (err, docs){
  if (err) res.send(err)

  res.send(JSON.parse(JSON.stringify(docs)))
});

Це найкраща відповідь на це питання. "Магія", яка приховує технічні поля мангуста, схована десь за JSON.stringify.
— mischka

8

Я дізнався, що припустився помилки. Немає необхідності викликати toObject () або toJSON () взагалі. __Proto__ у питанні походить від jquery, а не мангуста. Ось мій тест:

UserModel.find({}, function (err, users) {
    console.log(users.save);    // { [Function] numAsyncPres: 0 }
    var json = JSON.stringify(users);
    users = users.map(function (user) {
        return user.toObject();
    }
    console.log(user.save);    // undefined
    console.log(json == JSON.stringify(users));    // true
}

doc.toObject () видаляє doc.prototype з документа. Але це не має різниці в JSON.stringify (doc). І це не потрібно в цьому випадку.


3

Можливо, трохи збився з відповіді, але якщо хтось, хто прагне зробити все навпаки, може скористатися Model.hydrate() (починаючи з mongoose v4), щоб перетворити об’єкт javascript (JSON) на документ мангуста.

Корисним буде випадок, коли ви використовуєте Model.aggregate(...). Оскільки він фактично повертає звичайний об'єкт JS, тож, можливо, ви захочете перетворити його в мангустський документ, щоб отримати доступ доModel.method (наприклад, до вашої віртуальної властивості, визначеної у схемі).

PS. Я вважав, що у нього повинен бути потік, що працює на зразок " Перетворити json на документи Mongoose ", але насправді ні, і оскільки я знайшов відповідь, тому вважаю, що не варто робити самостійну відповідь та відповідь.


2

Ви можете використовувати res.json () для jsonify будь-якого об'єкта. lean () видалить усі порожні поля в запиті мангуста.

UserModel.find().lean().exec(function (err, users) { return res.json(users); }


2

Спробуйте наступні варіанти:

  UserModel.find({}, function (err, users) {
    //i got into errors using so i changed to res.send()
    return res.send( JSON.parse(JSON.stringify(users)) );
    //Or
    //return JSON.parse(JSON.stringify(users));
  }

1

Мені це вдалося:

Products.find({}).then(a => console.log(a.map(p => p.toJSON())))


також якщо ви хочете використовувати геттери, вам слід також додати його опцію (щодо визначення схеми):

new mongoose.Schema({...}, {toJSON: {getters: true}})

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.