nodejs中使用mongoose和mongoose-long模块操作NumberLong时遇到的json格式化问题
背景
项目中使用了nodejs+mongo,使用的是mongoose
模块进行数据库操作,mongoose本身的SchemaTypes中不包含Long(对应mongo中的NumberLong),所以需要额外一个模块mongoose-long
来让它支持。
let mongoose = require('mongoose');
require('mongoose-long')(mongoose);
var SchemaTypes = mongoose.Schema.Types;
var MyNumber = mongoose.model('my_number', { num: SchemaTypes.Long });
使用以上定义的MyNumber
,使用JSON.stringify()的时候,里面的num
会按照字符串
输出。
var record = new MyNumber({ num: 1234556 });
console.log(JSON.stringify(record));
//输出:{"num":"123456"}
解决之道
傻办法
var record = new MyNumber({ num: 1234556 });
/*一些其他操作*/
//把类型转换成Number
record.num = record.num.toNumber();
console.log(JSON.stringify(record));
//输出:{"num":123456}
这是一种方法,但是这种方法治标不治本,在所有涉及到的地方都要改对应的值,少改一个就还是有问题。
新办法
在找办法的过程中,首先发现,JSON.stringify(obj)会首先去找有没有obj.prototype.toJSON这个方法,如果有的话就用这个方法的返回值。
所以,方向就变成去找到num
的原型。一开始我以为它的类型是SchemaTypes.Long
,增加SchemaTypes.Long.prototype.toJSON=function(){return this.toNumber();}
,测试后发现不起作用。
再经过调试发现,mongoose里面用到了一个模块bson,用到了bson中的大部分数据类型,其中就包括了bson.Long
,而上面的record
结构确实就是bson.Long
的结构,于是,就简单了。
// 修复mongoose-long转换成json字符串时变成string而不是number的bug
require("bson").Long.prototype.toJSON=function(){return this.toNumber();}
var record = new MyNumber({ num: 1234556 });
console.log(JSON.stringify(record));
//输出:{"num":123456}
至此,问题总算解决。
扩展
在解决问题的过程中,发现mongoose的api也提供了重新实现toJSON的方式。
https://mongoosejs.com/docs/api.html#document_Document-toJSON
这个方式貌似是对model中某个具体字段进行设置的,没有细研究,有兴趣的可以研究研究。
4 thoughts on “nodejs中使用mongoose和mongoose-long模块操作NumberLong时遇到的json格式化问题”
请问你这是买的主题吗?
不是购买的,我记得好像是从官网安装的
最好是 toString,long转number在大数情况下会有精度问题的,具体可以查询javascript的number最大值。
这个要看实际应用场景。我之前用的场景是单位为毫秒的时间戳,可以确定不会超过最大值,所以就放心大胆使用了。如果超过number最大值的话那还是需要按照string来处理比较好。
Comments are closed.