使用JSON.stringify序列化Web3交易对象时遭遇BigInt序列化错误
JSON.stringify序列化Web3交易对象时遭遇BigInt序列化错误
我太懂这个坑了!你从Web3获取的交易对象里,那些带n后缀的(比如blockNumber: 0n、gas: 0n)都是BigInt类型,而JSON标准本身并不支持BigInt的序列化,所以直接用JSON.stringify就会抛出那个讨厌的类型错误。
问题根源
JS里的BigInt是为了处理超大整数而生的(毕竟以太坊里的数值经常会超过Number的安全精度范围2^53-1),但JSON规范里压根没这个类型,所以默认的序列化函数不知道该怎么处理它。
几种快速解决方法
1. 给JSON.stringify加Replacer函数(最推荐)
这是最灵活且无副作用的方式,在序列化时专门处理BigInt:
const txString = JSON.stringify(x, (key, value) => { // 把所有BigInt转成字符串,彻底避免精度丢失 return typeof value === 'bigint' ? value.toString() : value; });
如果你的交易数值都很小(比如测试网里的0n),也可以转成Number,但强烈不推荐在主网这么做——一旦数值超过2^53-1,转Number会直接丢失精度,字符串才是安全选项。
2. 扩展BigInt的toJSON方法(一劳永逸,但要注意副作用)
如果项目里经常要序列化BigInt,可以给BigInt原型加个toJSON方法,以后直接用JSON.stringify就行:
// 全局扩展BigInt的序列化逻辑 BigInt.prototype.toJSON = function() { return this.toString(); }; // 现在直接序列化交易对象就没问题了 const txString = JSON.stringify(x);
⚠️ 注意:修改原生对象原型可能会和其他库冲突,如果是团队项目最好先和队友沟通确认。
3. 手动转换字段(适合需要自定义处理的场景)
如果你只需要处理这一个交易对象,也可以手动遍历把所有BigInt字段转成字符串:
const serializableTx = { ...x, blockNumber: x.blockNumber.toString(), gas: x.gas.toString(), gasPrice: x.gasPrice.toString(), maxFeePerGas: x.maxFeePerGas.toString(), maxPriorityFeePerGas: x.maxPriorityFeePerGas.toString(), nonce: x.nonce.toString(), transactionIndex: x.transactionIndex.toString(), value: x.value.toString(), type: x.type.toString(), chainId: x.chainId.toString(), v: x.v.toString() }; const txString = JSON.stringify(serializableTx);
这种方式虽然繁琐,但能精准控制每个字段的处理方式,比如某些字段你确实想转成Number也可以在这里改。
额外提醒
Web3返回BigInt而不是普通数字,本质是为了避免超大数值的精度丢失问题——比如以太坊里的gasPrice可能是1e18量级的,用Number存直接就变科学计数法且丢精度了,所以序列化时优先转字符串是最稳妥的选择。
备注:内容来源于stack exchange,提问作者Teyrox
相关产品推荐
相关产品推荐

