Перетворити документи 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.