如何避免 JSON 解析中 BigInt 导致的 64 位整型 ID 精度丢失及溢出问题使用 BigInt?

2026-05-07 15:351阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计665个文字,预计阅读时间需要3分钟。

如何避免 JSON 解析中 BigInt 导致的 64 位整型 ID 精度丢失及溢出问题使用 BigInt?

直接使用`JSON.parse()`解析64位整型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 + 1ndata.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 的旧接口,需做类型断言或转换处理
标签:JSJson

本文共计665个文字,预计阅读时间需要3分钟。

如何避免 JSON 解析中 BigInt 导致的 64 位整型 ID 精度丢失及溢出问题使用 BigInt?

直接使用`JSON.parse()`解析64位整型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 + 1ndata.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 的旧接口,需做类型断言或转换处理
标签:JSJson