原生 BigInt 不能解决 JSON 解析精度丢失,因 JSON.parse() 在解析阶段已将大数转为不安全的 Number;需用 json-bigint 在词法层面拦截并返回 BigInt,或后端改用字符串传输。

直接用 JSON.parse() 解析 64 位整型 ID(比如雪花 ID、数据库自增主键)时,JavaScript 会把它转成 Number 类型,一旦超过 Number.MAX_SAFE_INTEGER(即 9007199254740991),末尾数字就会被悄悄抹掉——这不是 bug,是语言底层限制。BigInt 本身不能解决「解析阶段」的精度丢失,但配合 json-bigint 这类工具,就能从源头拦截并正确承载大整数。
为什么原生 BigInt 不能单独解决问题
BigInt 是 JavaScript 的数据类型,但它不参与标准 JSON 解析流程:
• JSON.parse('{ "id": 1234567890123456789 }') 永远返回 { id: 1234567890123456800 },此时精度已丢失,再转 1234567890123456800n 也没用;
• JSON.stringify({ id: 1234567890123456789n }) 会直接报错 TypeError: Do not know how to serialize a BigInt。
用 json-bigint 实现安全解析与序列化
核心是替换默认解析器,在词法层面识别数字字面量,避免落入 Number 类型陷阱:
- 安装依赖:
npm install json-bigint - 创建带配置的解析器实例:
const JSONbig = require('json-bigint')({ useNativeBigInt: true }); - 解析响应时使用它:
const data = JSONbig.parse(jsonString); // { id: 1234567890123456789n } - 后续可直接参与 BigInt 运算:
data.id + 1n或data.id.toString()安全输出
在 axios 中统一接管响应数据
避免每个接口手动 parse,推荐在响应拦截器中注入:
- 导入并初始化:
import JSONbig from 'json-bigint'; const JSONbigInt = JSONbig({ useNativeBigInt: true }); - 在 axios 响应拦截器中:
response.data = JSONbigInt.parse(JSON.stringify(response.data));
(注意:需先 stringify 再 parse,确保原始字符串未被浏览器提前解析) - 更稳妥的做法是让后端将大整数字段统一以字符串形式返回(如
"id": "1234567890123456789"),前端按需转BigInt或保持字符串——这能绕过解析器逻辑,兼容性更强
TypeScript 项目中的类型适配要点
启用 useNativeBigInt: true 后,解析结果字段类型不再是 number,需显式声明:
- 定义接口时用
bigint类型:interface User { id: bigint; name: string; } - 若部分字段可能为字符串或 bigint,可用联合类型:
id: bigint | string; - 注意:JSONbig.parse 返回的对象属性不可直接赋值给仅接受
number的旧接口,需做类型断言或转换处理


















