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