解決Long類型后端到前端精度丟失問題
Long類型后端到前端精度丟失問題
在開發(fā)中,后端經(jīng)常需要處理一些大數(shù)值的 Long 類型數(shù)據(jù)(id等)。但當這些數(shù)據(jù)通過接口傳遞到前端時,可能會出現(xiàn)精度丟失的問題。
原因:
JavaScript 的 Number 類型遵循 IEEE 754 雙精度浮點數(shù)標準,只能精確表示范圍在 -(2^53 - 1) 到 2^53 - 1 之間的整數(shù)(約等于 -9007199254740991 到 9007199254740991)。
這意味著,任何超過這個范圍的整數(shù)在 JavaScript 中都無法精確表示。
例如:
console.log(9007199254740991); // 輸出:9007199254740991(準確) console.log(9007199254740992); // 輸出:9007199254740992(準確) console.log(9007199254740993); // 輸出:9007199254740992(精度丟失)
在后端(例如 Java)中,Long 類型的范圍是 -2^63 到 2^63 - 1,即 -9223372036854775808 到 9223372036854775807。
這種數(shù)值在 Java 中可以被精確表示,但當通過 JSON 傳遞到前端的 JavaScript 環(huán)境時,由于 JavaScript 數(shù)字精度限制,往往會出現(xiàn) 精度丟失 的問題。
典型場景
當后端返回一個 ID 值 1234567890123456789,前端可能會收到 1234567890123456000,這樣就導致了數(shù)據(jù)的錯誤。
解決方案
方案一:后端將 Long 類型序列化為 String 類型
一種簡單有效的解決方案是,將后端的 Long 類型值序列化為 String,這樣前端會將其當作字符串處理,從而避免了精度丟失的問題。下面是具體的實現(xiàn)方法。
1. 使用@JsonSerialize注解單獨處理字段
如果只是需要處理某個特定字段(例如 id),可以在字段上添加 @JsonSerialize 注解,指定 Jackson 使用 ToStringSerializer 序列化器。
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
public class PassengerQueryResp {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private Long memberId;
private String name;
private String idCard;
// Getter 和 Setter
}配置了這個 ObjectMapper 之后,所有的 Long 類型字段在序列化時都會被轉換為字符串格式,不再需要逐個字段添加注解。
2. 配置全局的ObjectMapper設置
如果需要對所有 Long 類型的字段進行字符串處理,可以在 Spring Boot 的配置類中定義一個全局 ObjectMapper Bean,使用 SimpleModule 注冊 ToStringSerializer,這會對所有 Long 類型字段生效。
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}配置類的作用詳解
在 JacksonConfig 類中,通過以下代碼將 Long 類型序列化為 String:
SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(Long.class, ToStringSerializer.instance); objectMapper.registerModule(simpleModule);
具體工作原理
1.Spring Boot 自動配置 ObjectMapper
- Spring Boot 自帶 Jackson 作為默認的 JSON 處理庫,并在后臺自動配置了
ObjectMapper。 - 當你在項目中引入 Jackson 時,Spring Boot 會自動加載一個全局共享的
ObjectMapper實例,用于所有 JSON 序列化和反序列化操作。
2.控制器的自動 JSON 轉換
- 在 Spring MVC 中,控制器(
@RestController或@Controller)中的方法返回值會被自動轉換為 JSON 格式,這個轉換由 Spring Boot 的ObjectMapper處理。 - 例如:
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
return new User(123456789012345L, "Alice");
}
}- 當
User對象被返回時,Spring MVC 會自動使用ObjectMapper將其序列化為 JSON 響應發(fā)送給客戶端。 - 如果你配置了
JacksonConfig類,Spring 會使用你配置的ObjectMapper,因此所有Long類型字段會自動以字符串形式輸出,避免精度丟失。
3.自定義 ObjectMapper 配置的全局效果
通過自定義 JacksonConfig,實際上是讓 Spring Boot 使用你定義的 ObjectMapper Bean 作為全局配置。
Spring Boot 會自動檢測應用中的 ObjectMapper Bean,并將其用于所有 JSON 序列化和反序列化操作,這包括:
@RestController返回的對象。@RequestBody和@ResponseBody注解處理的 JSON 請求和響應。- 其他 Spring Boot 內(nèi)部或第三方庫需要 JSON 處理的地方。
總結
在后端開發(fā)中處理 Long 類型數(shù)據(jù)時,注意 JavaScript 的精度限制十分重要。
通過配置 Jackson 的 ObjectMapper,可以讓所有 Long 類型字段序列化為字符串,從而避免精度丟失的問題。
Spring Boot 的自動化配置特性讓我們無需手動調(diào)用 ObjectMapper,就能在全局范圍內(nèi)應用此配置,使得后端傳遞到前端的數(shù)據(jù)在大數(shù)值時也能準確無誤。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
基于Spring Cloud Gateway實現(xiàn)灰度發(fā)布的具體配置示例
這篇文章主要介紹了如何基于 Spring Cloud Gateway 實現(xiàn)灰度發(fā)布,核心思路是通過定義路由規(guī)則,將特定流量導向新版本服務,下面我用一個表格匯總主要策略,然后提供具體配置示例和關鍵說明,需要的朋友可以參考下2025-10-10
java編程實現(xiàn)根據(jù)EXCEL列名求其索引的方法
這篇文章主要介紹了java編程實現(xiàn)根據(jù)EXCEL列名求其索引的方法,涉及Java元素遍歷與數(shù)學運算的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11
spring中@Transactional?注解失效的原因及解決辦法
面試中經(jīng)常會被問到事務失效的場景有哪些,本文主要介紹了spring中@Transactional?注解失效的原因及解決辦法,具有一定的參考價值,感興趣的可以了解一下2024-06-06

