前言:
? ? ? ? 公司項目中有一個板塊需要解析JWT令牌獲取載荷里面封裝的數據,遇到要解析一個BigDecimal類型的數據
問題發現過程:
? ? ? ? 正常來說,我們解析一個JWT令牌的步驟如下:
public static Claims getDataFromToken(String token){JwtParser jwtParser = Jwts.parser();// 通過簽名對Token進行解析,得到的結果是一個類似集合的封裝類Jws<Claims> claimsJws = jwtParser.setSigningKey(Constants.TOKEN_SECRET.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(token);解析出來的類別 xxx= dataFromToken.get("令牌載荷鍵", 解析出來的類的字節碼文件);}
但是我按照解析Integer、String等類別的數據的做法,通過
BigDecimal price= dataFromToken.get("price", BigDecimal.class);
來解析一個BigDecimal類型的參數會報錯,查過后發現好像是這種轉換方法并不支持轉換BigDecimal類型的數據
? ? ? ? 為此,我想著先將其解析為一個Double類型的參數,再通過new BigDecimal(double val)方法來將其轉換為一個BigDecimal類型的數據
BigDecimal forntPrice = new BigDecimal(0.2);
但經過斷點發現 frontPrice 的值不是 0.2,而是?0.200000000000000011102230246251565404236316680908203125?。
問題解決:
查看相關文檔:
簡單翻一下:
將 double 類型轉換成 BigDecimal 類型。
- 這個構造函數的結果在某種程度上是不可預測的。你可能會覺得
new BigDecimal(0.1)
會創建一個剛好等于 0.1 的 BigDecimal,但它實際上等于 0.1000000000000000055511151231257827021181583404541015625 。這是因為 0.1 不能被精確地表示為一個雙精度數。 - String 構造函數是完全可預測的,
new BigDecimal("0.1")
會創建一個完全等于 0.1 的 BigDecimal,建議優先使用 String 構造函數。 - 如果必須使用 double 作為轉換源時,可以使用?
BigDecimal.valueOf(0.1)
?,它返回的結果也是精確的。
總結:
將 double 類型轉換為 BigDecimal 類型的時候,不要使用new BigDecimal(0.1)
這個構造函數,應為它得到的結果是不精確的,
使用BigDecimal.valueOf(0.1)
或new BigDecimal("0.1")
?。
BigDecimal transactionAmount = BigDecimal.valueOf(dataFromToken.get("transactionAmount", Double.class));