记录一次vue 和 prisma的问题排查

在Vue前端与Prisma ORM结合的项目中,遇到数据库BigInt报错和Decimal类型数据被序列化为字符串的问题。BigInt错误通过重写toJSON()函数解决,而Decimal类型的值在Prisma从MySQL获取后默认序列化为字符串,需通过toNumber()转换。解决方案是在Express序列化之前替换Prisma内建类型的toJSON()方法,确保数据正确传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目背景: 前端使用vue 后端使用node
其中后端服务器框架用express orm框架使用prisma 数据库是mysql
前后端使用json传输数据

问题:

  1. 数据库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(); }
    
  2. 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
    是个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(); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值