Строка JSON в Node JS не сериализует массив объектов

Я использую sails.js (инфраструктура узла js).

Я пытаюсь JSON.stringify один из объектов, но когда я это делаю, он пропускает одно из полей (массив комнат ниже).

Вот что дает мне console.log(object):

[ { rooms: [ [Object], [Object] ],
    state: '53df76c278999310248072c6',
    name: 'Sydney Center',
    menuItems: null,
    createdAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
    updatedAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
    id: '53dff0205c89c03428a31cee' },
  { rooms: [ [Object], [Object], [Object] ],
    state: '53df76c278999310248072c6',
    createdAt: Mon Aug 04 2014 23:43:21 GMT+0300 (Jerusalem Summer Time),
    menuItems: null,
    name: 'Batata Center',
    updatedAt: Mon Aug 04 2014 23:51:11 GMT+0300 (Jerusalem Summer Time),
    id: '53dff06a5c89c03428a31cf3' } ]

Вывод JSON (номера не печатаются):

    [
      {
        "state": "53df76c278999310248072c6",
        "name": "Sydney Center",
        "menuItems": null,
        "createdAt": "2014-08-04T20:42:08.885Z",
        "updatedAt": "2014-08-04T20:42:08.885Z",
        "id": "53dff0205c89c03428a31cee"
      },
      {
        "state": "53df76c278999310248072c6",
        "createdAt": "2014-08-04T20:43:21.999Z",
        "menuItems": null,
        "name": "Batata Center",
        "updatedAt": "2014-08-04T20:51:11.740Z",
        "id": "53dff06a5c89c03428a31cf3"
      }
    ]

В чем может быть проблема? Данные номеров, кажется, в порядке.

Для полной функции (SailsJS):

getCentersData: function(req, res) {

    sails.log.info('Teacher.getCentersData: ', req.user.id);
    var userId = req.user.id;

    async.auto({

        teacher: function(cb) {
            Teacher.findOne({ user: userId }).populate('centers').exec(cb);
        },

        centers: [
            'teacher', function(cb, results) {
                var allCentersIds = _.pluck(results.teacher.centers, 'id');
                Center.findById(allCentersIds).populate('rooms').exec(cb);
            }
        ],

        rooms: [
            'centers', function(cb, results) {
                var allRoomIds = [];
                _.each(results.centers, function(center) {
                    allRoomIds = _.union(allRoomIds, _.pluck(center.rooms, 'id'));
                });
                Room.findById(allRoomIds).populate('children').exec(cb);
            }
        ],

        children: [
            'rooms', function(cb, results) {
                var allChildrenIds = [];
                _.each(results.rooms, function (room) {
                    allChildrenIds = _.union(allChildrenIds, _.pluck(room.children, 'id'));
                });
                Child.findById(allChildrenIds).populate('parents').exec(cb);
            }
        ],

        parentUsers: ['children', function(cb, results) {
            var allParentIds = [];
            _.each(results.children, function (child) {
                allParentIds = _.union(allParentIds, _.pluck(child.parents, 'id'));
            });
            Parent.findById(allParentIds).populate('user').exec(cb);
        }],

        map: ['parentUsers', function (cb, results) {

            // map children to parents
            var parentsMapper = _.indexBy(results.parentUsers, 'id');
            var childrenMappedToParents = _.map(results.children, function (child) {
                var _child = child.toObject();
                _child.parents = _.map(child.parents, function (parent) {
                    return parentsMapper[parent.id];
                });
                return _child;
            });
            var childrenMapper = _.indexBy(childrenMappedToParents, 'id');

            // map rooms to children
            var roomsMappedToChildren = _.map(results.rooms, function (room) {
                var _room = room.toObject();
                _room.children = _.map(room.children, function (child) {
                    return childrenMapper[child.id];
                });
                return _room;
            });
            var roomsMapper = _.indexBy(roomsMappedToChildren, 'id');

            // map center to rooms
            var centersMappedToRooms = _.map(results.centers, function (center) {
                var _center = center.toObject();
                _center.rooms = _.map(center.rooms, function (room) {
                    return roomsMapper[room.id];
                });
                return _center;
            });

            sails.log.info('centersMappedToRooms',centersMappedToRooms ); // includes rooms array
            sails.log.info('centersMappedToRooms json: ', JSON.stringify(centersMappedToRooms)); // does not include rooms array

            return cb(null, centersMappedToRooms);

        }]
    }, function(err, results) {
        if (err) {
            return res.serverError(err);
        }

        // added prints
        sails.log.info("results.map: ", results.map); 
        sails.log.info("JSON.stringify(results.map): ", JSON.stringify(results.map)); // same same, does not print the rooms array

        return res.json(results.map);
    });

},

ОТРЕДАКТИРОВАНО

Схема:

schema: true,

attributes: {

    name: {
        type: 'string',
        required: true,
        minLength: 5
    },

    // Many-To-Many association with Teacher model
    teachers: {
        collection: 'teacher',
        via: 'centers'
    },

    // One-To-Many association with State model
    state: {
        model: 'state'
    },

    // One-To-Many association with Room model
    rooms: {
        collection: 'room',
        via: 'center'
    },

    // One-To-One association with Principal model
    principal: {
        model: 'principal'
    },

    menuItems: {
        type: 'array',
        defaultsTo: null
    }
},

person user2867106    schedule 05.08.2014    source источник
comment
Мое первое предположение состоит в том, что ваша схема мангуста определяет преобразования для toJSON, которые опускают свойство room. Можете ли вы опубликовать схему, которую вы определили для рассматриваемой модели?   -  person Peter Lyons    schedule 05.08.2014
comment
может быть асинхронная синхронизация. добавьте console.log в код (перед последним оператором возврата), чтобы исключить это.   -  person Robert Levy    schedule 05.08.2014
comment
@PeterLyons я добавил схему.   -  person user2867106    schedule 05.08.2014
comment
@RobertLevy, я видел журналы, которые я распечатал и где, не помогло.   -  person user2867106    schedule 05.08.2014
comment
@user2867106 user2867106, чтобы подтвердить, что это не проблема асинхронности, вам нужно войти в систему до final возврата (return res.json(results.map);)   -  person Robert Levy    schedule 05.08.2014
comment
я добавил принты, смотрите отредактированную версию. но ничего не изменилось :/   -  person user2867106    schedule 05.08.2014
comment
хорошо, я могу с уверенностью сказать, что это связано с глубоким клонированием, я изменил назначения на _.cloneDeep() внутри карты, и теперь это дает рациональные результаты. Тем не менее, у меня нет хорошего объяснения этому :)   -  person user2867106    schedule 06.08.2014


Ответы (1)


Поскольку запросы Waterline возвращают модели, а не простые объекты javascript, они имеют дополнительные свойства и функции. Одной из них является переопределенная функция toJSON(), которая удаляет не заполненные атрибуты. Кажется, что здесь происходит то, что вы присоединяете объекты к родительской модели, которая не знает, что у нее есть дочерние элементы, которые были заполнены, поэтому она удаляет значения.

Причина этого заключается в том, что если вы запрашиваете всех пользователей и не заполняете комнаты, вы не получите неверный результат, показывающий пустой массив комнат.

Я не уверен, что все, что вы здесь манипулируете, но причина, по которой это работает, если вы _.cloneDeep, заключается в том, что он удаляет пользовательское поле toJSON. Это рекомендуемая стратегия, когда вы изменяете родительский объект из такого запроса.

person particlebanana    schedule 12.08.2014
comment
Я согласен с @particlebanana! Похоже, что причина, по которой на окончательной карте «комнаты» не заселены, несмотря на то, что в начале вызывается «население», связана с потоком. .cloneDeep() решает эту проблему. - person Suraj Pathak; 27.01.2015