后端Long型数据传到前端js后精度丢失的问题(前后端传输踩坑指南)

在全栈开发中,遇到过这样一个"诡异"的问题:

后端返回一个 Long 类型 ID,前端接收到后却变了值 😨

比如:

json 复制代码
{
  "id": 9007199254740993
}

前端 JS 打印出来却是:

javascript 复制代码
9007199254740992

这不是 bug,这是经典的精度丢失问题

出现这种问题,可以做一个测试:在浏览器的Network(网络)面板中,不要看Preview(预览)标签页,而是点开Response(响应/原始数据)标签页。你会发现,原始的纯文本字符串是正常的,但只要经过工具的"美化/格式化"它就会因为超出JS安全整数范围,被自动进位,进而改变数据呈现方式。

你用来查看接口返回数据的工具(比如浏览器的Network面板、Postman、Swagger 等),它们底层在格式化展示 JSON 时,也是用 JavaScript 解折的!


文章目录

    • 一、问题本质
      • [1. Java 的 Long 是什么?](#1. Java 的 Long 是什么?)
      • [2. JavaScript 的 Number 是什么?](#2. JavaScript 的 Number 是什么?)
      • [⚠️ 超过这个值会发生什么?](#⚠️ 超过这个值会发生什么?)
    • 二、典型场景
    • 三、解决方案
    • [方案一:后端转 String(最推荐 ⭐)](#方案一:后端转 String(最推荐 ⭐))
    • [方案二:前端使用 BigInt](#方案二:前端使用 BigInt)
    • [方案三:前端使用 JSON 解析库](#方案三:前端使用 JSON 解析库)
    • 不推荐方案
      • [方案:强行用 Number](#方案:强行用 Number)
    • [🧩 四、最佳实践总结](#🧩 四、最佳实践总结)
    • 参考

一、问题本质

1. Java 的 Long 是什么?

在 Java 中:

java 复制代码
Long.MAX_VALUE = 9223372036854775807

👉 64 位整数(long),精度完全没问题。


2. JavaScript 的 Number 是什么?

在 JavaScript 中:

  • 所有数字都是 Number
  • 基于 IEEE 754 双精度浮点数

👉 最大安全整数:

javascript 复制代码
Number.MAX_SAFE_INTEGER === 9007199254740991

⚠️ 超过这个值会发生什么?

javascript 复制代码
9007199254740991 + 1 === 9007199254740992 // ✅
9007199254740991 + 2 === 9007199254740992 // ❌ 精度丢失

👉 这就是为什么 Long 在 JS 中会"变"。


二、典型场景

后端返回

java 复制代码
@Data
public class User {
    private Long id;
}

接口返回:

json 复制代码
{
  "id": 9223372036854775807
}

前端接收

javascript 复制代码
console.log(res.id);
// 输出:9223372036854776000 ❌

👉 精度直接炸掉。


三、解决方案


方案一:后端转 String(最推荐 ⭐)

✔ 原理

👉 避免 JS 解析为 Number,直接作为字符串处理。


✔ 实现方式(Jackson)

使用 @JsonSerialize

java 复制代码
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

public class User {

    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
}

全局配置(推荐)

java 复制代码
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
    return builder -> builder.serializerByType(Long.class, ToStringSerializer.class)
                             .serializerByType(Long.TYPE, ToStringSerializer.class);
}

返回结果

json 复制代码
{
  "id": "9223372036854775807"
}

前端处理

javascript 复制代码
const id = res.id; // string

👉 安全 ✅ 无损 ✅


方案二:前端使用 BigInt

适用场景

  • 需要参与计算
  • 不只是展示

示例

javascript 复制代码
const id = BigInt("9223372036854775807");
console.log(id + 1n);

⚠️ 注意

  • 必须加 n
  • 不能和普通 Number 混用
javascript 复制代码
1n + 1 // ❌ 报错

方案三:前端使用 JSON 解析库

比如:

  • json-bigint

地址:https://www.npmjs.com/package/json-bigint


示例

javascript 复制代码
import JSONbig from 'json-bigint';

const data = JSONbig.parse(responseText);

console.log(data.id.toString());

优点

  • 自动处理大整数
  • 不需要改后端

缺点

  • 增加依赖
  • 性能略低

不推荐方案

方案:强行用 Number

javascript 复制代码
parseInt(res.id)

👉 依然会丢精度,没意义。


🧩 四、最佳实践总结

方案 推荐指数 说明
后端转 String ⭐⭐⭐⭐⭐ 最稳定,最通用
BigInt ⭐⭐⭐⭐ 适合计算
json-bigint ⭐⭐⭐ 特殊场景
直接 Number 一定会出问题

参考

使用axios请求,前端数字long类型精度问题解决方法-CSDN博客

长得太长也是错?------后端 Long 型 ID 精度丢失的"奇妙"修复之旅-腾讯云开发者社区-腾讯云

解决后端Long型数据传到前端js后精度丢失的问题-知乎

相关推荐
We་ct4 分钟前
深度剖析浏览器跨域问题
开发语言·前端·浏览器·跨域·cors·同源·浏览器跨域
身如柳絮随风扬11 分钟前
多数据源切换实战:从业务场景到3种实现方案全解析
java·分布式·微服务
weixin_4277716129 分钟前
前端调试隐藏元素
前端
threelab41 分钟前
Three.js 代码云效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
Java小生不才42 分钟前
Spring AI文生音
java·人工智能·spring
凯尔萨厮1 小时前
Springboot2.x+Thymeleaf项目创建
java
fish_xk1 小时前
map和set
java·开发语言
李崧正1 小时前
Java技术分享:Lambda表达式与函数式编程
java·开发语言·python
老了,不知天命1 小时前
鳶尾花項目JAVA
java·开发语言·机器学习
永远不会的CC1 小时前
浙江华昱欣实习(4月23日~ 4月19日)
后端·学习