在全栈开发中,遇到过这样一个"诡异"的问题:
后端返回一个
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博客