解決后端傳long類(lèi)型數(shù)據(jù)到前端精度丟失問(wèn)題
后端傳long類(lèi)型數(shù)據(jù)到前端精度丟失
在 Spring Boot 中,將 long 類(lèi)型傳輸?shù)角岸藭r(shí),會(huì)發(fā)現(xiàn)該類(lèi)型的值可能會(huì)出現(xiàn)精度丟失的問(wèn)題。
這是因?yàn)樵?JavaScript 中,數(shù)字類(lèi)型默認(rèn)會(huì)被轉(zhuǎn)換為雙精度浮點(diǎn)數(shù),而雙精度浮點(diǎn)數(shù)的精度有限,只能精確表示 2 的 53 次方以內(nèi)(即 Number.MAX_SAFE_INTEGER,約為 9 x 10^15)的整數(shù)。
對(duì)于超過(guò)該范圍的長(zhǎng)整數(shù),JavaScript 會(huì)發(fā)生精度丟失,導(dǎo)致值變得不準(zhǔn)確。
解決方案一
將 long 轉(zhuǎn)換為字符串
1:在后端將 long 類(lèi)型的值轉(zhuǎn)換為字符串類(lèi)型,可以使用 String.valueOf()
方法或者 Long.toString()
方法
如下所示:
long num = 123456789012345L; String str = String.valueOf(num); // 或者 String str = Long.toString(num);
2:在前端通過(guò) AJAX 請(qǐng)求獲取該字符串類(lèi)型的值,并將其解析為數(shù)字類(lèi)型。
由于 JavaScript 中的數(shù)值類(lèi)型默認(rèn)使用 IEEE 754 標(biāo)準(zhǔn)的雙精度浮點(diǎn)數(shù)表示,因此需要使用 JavaScript 的 BigInt()
方法將其轉(zhuǎn)換為大整數(shù)類(lèi)型。
let str = "123456789012345"; let num = BigInt(str);
解決方案二
使用第三方庫(kù)進(jìn)行高精度運(yùn)算
1:在后端將 long 類(lèi)型的值轉(zhuǎn)換為 BigDecimal
類(lèi)型(Java 中的高精度類(lèi)型),并通過(guò) JSON 序列化后傳遞到前端。
這里以 Spring Boot 中使用 FastJSON 序列化為例
如下所示:
BigDecimal num = new BigDecimal("123456789012345"); String jsonStr = JSON.toJSONString(num);
2:在前端使用第三方庫(kù) big.js
或 bignumber.js
進(jìn)行高精度運(yùn)算。
這里以 big.js
為例,首先需要引入 big.min.js
文件,在代碼中使用 Big()
類(lèi)構(gòu)造高精度對(duì)象,并進(jìn)行相應(yīng)的運(yùn)算。
<script src="big.min.js"></script> let num = new Big("123456789012345"); let result = num.plus(1);
還可以使用注解來(lái)解決long類(lèi)型的精度丟失問(wèn)題
Spring Boot 中提供了 @JsonFormat
注解,可以對(duì)實(shí)體類(lèi)中的屬性進(jìn)行序列化和反序列化格式化。
對(duì)于 long 類(lèi)型的屬性,可以設(shè)置其格式為字符串類(lèi)型,并在前端進(jìn)行相應(yīng)的處理,以保持其精度不丟失。
具體實(shí)現(xiàn)方式
1:在實(shí)體類(lèi)中添加 @JsonFormat
注解,設(shè)置其 shape
屬性為 JsonFormat.Shape.STRING
如下所示:
public class Example { @JsonFormat(shape = JsonFormat.Shape.STRING) private Long num; }
2:在前端獲取該值時(shí),直接使用字符串類(lèi)型進(jìn)行處理
如下所示:
let numStr = data.num;
Spring Boot 中可以通過(guò)配置文件來(lái)解決 long 類(lèi)型的精度丟失問(wèn)題。
在 Spring Boot 的配置文件 application.properties
中添加如下配置:
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false # 將 long 類(lèi)型序列化為字符串類(lèi)型 spring.jackson.serialization.WRITE_NUMBERS_AS_STRINGS=true
其中,
WRITE_DATES_AS_TIMESTAMPS
表示是否將日期類(lèi)型序列化為時(shí)間戳類(lèi)型,默認(rèn)為true
,這里設(shè)置為false
如果需要將日期類(lèi)型序列化為時(shí)間戳類(lèi)型,則不需要設(shè)置此屬性。- 而
WRITE_NUMBERS_AS_STRINGS
則表示是否將數(shù)字類(lèi)型序列化為字符串類(lèi)型,默認(rèn)為false
,這里設(shè)置為true
即可將 long 類(lèi)型序列化為字符串類(lèi)型。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java 使用HttpURLConnection發(fā)送數(shù)據(jù)簡(jiǎn)單實(shí)例
這篇文章主要介紹了java 使用HttpURLConnection發(fā)送數(shù)據(jù)簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-06-06一文帶你掌握J(rèn)ava8中函數(shù)式接口的使用和自定義
函數(shù)式接口是?Java?8?引入的一種接口,用于支持函數(shù)式編程,下面我們就來(lái)深入探討函數(shù)式接口的概念、用途以及如何創(chuàng)建和使用函數(shù)式接口吧2023-08-08Spring/SpringBoot?@RequestParam注解無(wú)法讀取application/json格式數(shù)據(jù)問(wèn)題
RequestParam用于將指定的請(qǐng)求參數(shù)賦值給方法中的形參,可以接受簡(jiǎn)單類(lèi)型屬性,也可以接受對(duì)象類(lèi)型,一般用于GET請(qǐng)求,下面這篇文章主要給大家介紹了關(guān)于Spring/SpringBoot?@RequestParam注解無(wú)法讀取application/json格式數(shù)據(jù)問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下2022-10-10Java的System.getProperty()方法獲取大全
這篇文章主要介紹了Java的System.getProperty()方法獲取大全,羅列了System.getProperty()方法獲取各類(lèi)信息的用法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-12-12Java的函數(shù)式接口@FunctionalInterface的使用說(shuō)明
這篇文章主要介紹了Java的函數(shù)式接口@FunctionalInterface的使用說(shuō)明,我們常用的一些接口Callable、Runnable、Comparator等在JDK8中都添加了@FunctionalInterface注解,需要的朋友可以參考下2024-01-01