Node string中的JSON字符串不会序列化对象数组 [英] JSON stringify in Node JS not serializing array of objects

查看:109
本文介绍了Node string中的JSON字符串不会序列化对象数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 sails.js (节点js框架)。



我正在尝试JSON.stringify其中一个对象,但是当我这样做时,它会省略一个字段(下面的房间数组)。



这是什么console.log(object)给了我:

  [{rooms:[[Object],[Object]],
状态:'53df76c278999310248072c6',
名称:'悉尼中心',
menuItems:null,
createdAt:Mon Aug 04 2014 23:42:08 GMT + 0300(耶路撒冷夏令时间)
updatedAt:Mon Aug 04 2014 23:42:08 GMT + 0300(Jerusalem Summer Time),
id:'53dff0205c89c03428a31cee'},
{rooms:[[Object],[Object] ,[对象]],
状态:'53df76c278999310248072c6',
createdAt:Mon Aug 04 2014 23:43:21 GMT + 0300(耶路撒冷夏令时间),
menuItems:null,
name:'Batata Center',
updatedAt:Mon Aug 04 2014 23:51:11 GMT + 0300(Jerusalem Summer Time),
id:'5 3dff06a5c89c03428a31cf3'}]

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);
},

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

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

children:[
'rooms',function(cb,results){
var allC hildrenIds = [];
_.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){

//将孩子映射到父级
var parentsMapper = _.indexBy(results.parentUsers,'id');
var childrenMappedToParents = _.map(results.children,function(child){
var _child = child.toObject();
_child.parents = _.map(child.parents,function (父){
return parentsMapper [parent.id];
});
return _child;
});
var childrenMapper = _.indexBy(childrenMappedToParents,'id');

//映射房间给孩子
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');

//映射中心到房间
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); //包括房间数组
sails.log.info('centersMappedToRooms json:',JSON.stringify(centersMappedToRooms)); //不包括房间数组

return cb(null,centersMappedToRooms);

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

//添加打印
sails.log.info(results.map:,results.map);
sails.log.info(JSON.stringify(results.map):,JSON.stringify(results.map)); //同样的,不打印房间数组

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

},

EDITED



模式:

  schema:true,

属性:{

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

//与教师模型的多对多关系
教师:{
集合:'老师',
通过:'中心'
},

//状态模型的一对多关联
状态:{
model:'state'
},

//一对一 - 与房间模型的许多关联
房间:{
集合:'房间',
通过:'center'
},

// One- To-One与主体模型的关系
principal:{
model:'principal'
},

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


解决方案

因为Waterline查询返回模型,而不是纯粹的JavaScript对象,它们在其上具有其他属性和功能。其中一个是覆盖 toJSON()函数,它删除尚未填充的属性。这里似乎发生的一个事情是,您将对象附加到父模型,该模型不知道它有已填充的子项,因此它剥离了值。



这样做的原因是,如果您查询所有用户,并且不填充房间,则不会得到显示空房间阵列的错误结果。



不知道你在这里操作什么,但是如果你 _。cloneDeep 是因为它删除了自定义的 toJSON 字段。当您从这样的查询中更改父对象时,这是推荐策略。


I am using sails.js (node js framework).

I am trying to JSON.stringify one of the objects, but when I do that it omits one of the fields (rooms array below).

Here is what console.log(object) gives me:

[ { 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 output (rooms are not printed):

    [
      {
        "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"
      }
    ]

What might be the problem? The rooms data seems to be fine.

For the complete function (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);
    });

},

EDITED

Schema:

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
    }
},

解决方案

Because Waterline queries return models, not plain javascript objects, they have additional properties and functions on them. One of these is an overridden toJSON() function which removes attributes that have not been populated. What seems to be happening here is that you are attaching objects to a parent model which doesn't know it has children that have been populated so it strips off the values.

The reasoning behind this is so that if you query for all Users and don't populate Rooms you don't get an incorrect result showing an empty rooms array.

I'm not sure what all you are manipulating here but the reason it works if you _.cloneDeep is because it removes the custom toJSON field. This is the recommend strategy when you are mutating a parent object from a query like this.

这篇关于Node string中的JSON字符串不会序列化对象数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆