项目背景: 前端使用vue 后端使用node
其中后端服务器框架用express orm框架使用prisma 数据库是mysql
前后端使用json传输数据
问题:
-
数据库BigInt报错
TypeError: Do not know how to serialize a BigInt
查了一下发现根本就不是问题 是一个历史遗留问题,然后chrome的程序员开玩笑就不给解析,但是实际上一行代码就解决问题了解决方案: 在用到BigInt的serialize之前 给BigInt换上新的toJSON()函数
// 因为这里项目用的是express 所以就是在根目录项目启动文件app.js 中添加这行代码 BigInt.prototype.toJSON = function() { return this.toString(); }
-
vue里,发现vuex中返回的带小数点的(数据库里是Decimal类型)的数据全都变成undefined了
一开始还以为是后端出问题了,后来才发现element-plus的组件报错说,期待数值0.4,却收到了字符串对象’0.4’
回头一看后端返回的数据{ //... hrRatio: "0.4" //... }
好家伙原来是后端返回成字符串了
为什么会返回成字符串呢? 这里输出hrRatio的类型,发现竟然是Object,也不是String也不是Number,而是一种奇怪的值,
初步猜测是prisma自定义对象,数据库是prisma从mysql取过来的,看这样子 有s有e的,可能是科学计数法的Decimal
在vscode中把hrRatio取到,然后鼠标移上去看对象类型,发现果然是Decimal.
拿到这个Decimal一看
是个class,那就大概猜出来了,可能它的valueOf()返回的是String类型而不是Number类型的.
点开源码,跳出来一个d.ts文件,一看果然是这样的
然后又发现原来人家有toNumber()啊…那序列化的时候还整成string类型…
唉到这里就一切明了了:
Prisma从MySQL取回的Decimal
类型不是Number
类型,而是一种Prisma内建类型,这种类型内部不是完整的数字,读取时需要通过函数专门函数去转换.
Prisma内部提供了toString()
和toNumber()
两种转换的方式,但是在toJSON()
和valueOf()
时默认转换成String类型,所以express在返回结果时,会自动把这种类型的变量序列化为hrRatio: "0.4"
而不是hrRatio: 0.4
,这样心心念念着Number的前端到手却变成了String,自然就会炸锅了.
解决方案:把Prisma内建的Decimal
类型的原型里的toJSON()换掉,换成返回Number
类型的函数(如果该valueOf()估计也是可以的,但是改valueOf()担心会波及到其他的地方)
跟上面一样,也是在express第一次序列化Decimal之前,把proto原型里的函数换掉
const { Decimal } = require("@prisma/client/runtime")
Decimal.prototype.toJSON = function () { return this.toNumber(); }