js精度丟失解決方案(響應(yīng)和預(yù)覽數(shù)據(jù)不一致)
背景
后端使用雪花算法生成的id,在接口文檔測(cè)試中,響應(yīng)體中正常顯示。
在后續(xù)測(cè)試中,卻出現(xiàn)通過(guò)id查不到數(shù)據(jù)的情況,通過(guò)打開(kāi)瀏覽器控制臺(tái)(F12)發(fā)現(xiàn),響應(yīng)和預(yù)覽中的數(shù)據(jù)不一致。
從下面圖片可以看出,響應(yīng)中JSON格式的數(shù)據(jù)是正常的,但是在預(yù)覽中卻出現(xiàn)跟原id不一致的情況,且通過(guò)分析發(fā)現(xiàn)只有最后兩位不一致,這里明顯出現(xiàn)了精度丟失
這里的id是正常的
在這里出現(xiàn)了精度丟失
問(wèn)題分析
1. JavaScript 的數(shù)字精度限制
JavaScript 使用 IEEE 754 雙精度浮點(diǎn)數(shù)格式表示所有數(shù)字,這意味著:
- 它能準(zhǔn)確表示的整數(shù)范圍是
-2^53 + 1
到2^53 - 1
(即-9007199254740991
到9007199254740991
) - 你的 ID
1922304585509261314
已經(jīng)超過(guò)了這個(gè)范圍(2^53 = 9007199254740992
)
2. 當(dāng)數(shù)字超過(guò)安全整數(shù)范圍時(shí)
超出 Number.MAX_SAFE_INTEGER
(即 2^53 - 1
)的數(shù)字會(huì)出現(xiàn)精度丟失(前端測(cè)試):
const bigId = 1922304585509261314; console.log(bigId); // 輸出 1922304585509261300
為什么預(yù)覽顯示不正確?
開(kāi)發(fā)工具(如瀏覽器控制臺(tái)、Postman等)在顯示 JSON 響應(yīng)時(shí),會(huì)自動(dòng)將數(shù)字類型的值轉(zhuǎn)換為 JavaScript 數(shù)字,從而導(dǎo)致精度丟失。實(shí)際響應(yīng)數(shù)據(jù)可能是正確的,但顯示時(shí)被轉(zhuǎn)換了。
解決方案
后端解決方案:
代碼
SpringBoot中可以通過(guò)編寫JsonConfig
處理json精度丟失的配置,將Long類型轉(zhuǎn)化為String類型
@JsonComponent public class JsonConfig { /** * 添加 Long 轉(zhuǎn) json 精度丟失的配置 */ @Bean public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); SimpleModule module = new SimpleModule(); module.addSerializer(Long.class, ToStringSerializer.instance); module.addSerializer(Long.TYPE, ToStringSerializer.instance); objectMapper.registerModule(module); return objectMapper; } }
代碼解釋
1. @JsonComponent
注解
- 這個(gè)注解是 Spring Boot 提供的,用于標(biāo)記一個(gè)類作為 Jackson 的序列化/反序列化組件。
- 被標(biāo)記的類會(huì)自動(dòng)注冊(cè)到 Spring 的 Jackson
ObjectMapper
中,全局生效。
2. JsonConfig
類
public class JsonConfig {
- 這是一個(gè)配置類,專門用于自定義 Jackson 的 JSON 序列化行為。
3. jacksonObjectMapper
方法
@Bean public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
@Bean
表示這個(gè)方法會(huì)返回一個(gè)由 Spring 管理的 Bean(這里是ObjectMapper
)。Jackson2ObjectMapperBuilder
是 Spring Boot 提供的工具類,用于方便地配置ObjectMapper
。
4. 創(chuàng)建和配置 ObjectMapper
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
- 通過(guò)
builder
創(chuàng)建一個(gè)新的ObjectMapper
實(shí)例,并禁用 XML 映射功能(createXmlMapper(false)
)。
5. 注冊(cè)自定義序列化模塊
SimpleModule module = new SimpleModule(); module.addSerializer(Long.class, ToStringSerializer.instance); module.addSerializer(Long.TYPE, ToStringSerializer.instance); objectMapper.registerModule(module);
SimpleModule
:是 Jackson 提供的模塊,用于自定義序列化/反序列化規(guī)則。module.addSerializer
:
Long.class
:針對(duì)包裝類型的Long
。Long.TYPE
:針對(duì)基本類型的long
。ToStringSerializer.instance
:將Long
值直接轉(zhuǎn)換為字符串(而不是數(shù)字),避免精度丟失。
objectMapper.registerModule(module)
:將配置好的模塊注冊(cè)到ObjectMapper
。
6. 返回配置好的 ObjectMapper
return objectMapper;
- 最終返回定制化的
ObjectMapper
,Spring 會(huì)用它來(lái)處理所有 JSON 序列化/反序列化。
修改后測(cè)試
id已經(jīng)轉(zhuǎn)為字符串,顯示正常,無(wú)精度丟失
總結(jié)
- JavaScript 的
Number
類型無(wú)法安全表示超過(guò) 53 位的整數(shù)(2^53
),而 Java 的Long
是 64 位。 - 如果直接將
Long
作為數(shù)字序列化到 JSON,前端 JavaScript 解析時(shí)可能會(huì)丟失精度(例如1234567890123456789
可能變成1234567890123456800
)。 - 解決方案:將
Long
序列化為字符串(如"1234567890123456789"
),前端可以通過(guò)字符串解析避免精度問(wèn)題。
到此這篇關(guān)于js精度丟失解決方案的文章就介紹到這了,更多相關(guān)js精度丟失解決內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用js判斷手機(jī)是否安裝某個(gè)app的多種方案
這篇文章主要介紹了利用js檢測(cè)手機(jī)是否安裝某個(gè)app的多種方案,當(dāng)判斷后如果安裝了直接打開(kāi),如果有沒(méi)有安裝將自動(dòng)跳轉(zhuǎn)到下載的界面,有需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-02-02JS解決IOS中拍照?qǐng)D片預(yù)覽旋轉(zhuǎn)90度BUG的問(wèn)題
下面小編就為大家?guī)?lái)一篇JS解決IOS中拍照?qǐng)D片預(yù)覽旋轉(zhuǎn)90度BUG的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09理運(yùn)用命名空間讓js不產(chǎn)生沖突避免全局變量的泛濫
為了避免變量之間的覆蓋與沖突,可以生成命名空間,命名空間是一種特殊的前綴,在不同的匿名函數(shù)中,根據(jù)功能聲明一個(gè)不同的命名空間2014-06-06利用HTML與JavaScript實(shí)現(xiàn)注冊(cè)頁(yè)面源碼
這篇文章主要給大家介紹了關(guān)于利用HTML與JavaScript實(shí)現(xiàn)注冊(cè)頁(yè)面的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家實(shí)現(xiàn)注冊(cè)頁(yè)面具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-12-12原生js+canvas實(shí)現(xiàn)驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了原生js+canvas實(shí)現(xiàn)驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11微信小程序?qū)崿F(xiàn)拉鏈?zhǔn)降幕瑒?dòng)驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)拉鏈?zhǔn)降幕瑒?dòng)驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05JavaScript 中的 this 簡(jiǎn)單規(guī)則
想要確定this里規(guī)則是什么,其實(shí)方法很簡(jiǎn)單,通過(guò)檢查它的調(diào)用位置,在函數(shù)被調(diào)用的時(shí)候確定this,下面就跟隨腳本之家小編一起通過(guò)本文學(xué)習(xí)吧2017-09-09