您的位置:首页 >JSON 反序列化大浮点数转 BigDecimal 方法
发布于2026-01-31 阅读(0)
扫一扫,手机访问

JSON 中的高精度数字(如 "123345555789123495.38")若经 double 中间解析会丢失精度;正确做法是**跳过 double 类型,直接从原始字符串构造 BigDecimal**。
在 Java 处理 JSON 数据时,若后端将 JSON 数字字段(如 "amount": 123345555789123495.38)反序列化为 double 或 Double 类型,会导致严重精度丢失——因为 double 仅能精确表示约 15–17 位十进制有效数字,而示例中的整数部分已达 17 位(123345555789123495),超出 double 的安全整数范围(Long.MAX_VALUE ≈ 9.2×10¹⁸,但精度限制更早发生)。此时 123345555789123495.38 被转为 double 后实际存储为 1.23345555789123488E17,即 123345555789123488.0,已丢失末尾 7 个单位的整数精度。
根本解决方法是:避免经过 double 解析环节,直接获取 JSON 中该字段的原始字符串表示,再用 BigDecimal(String) 构造器初始化。BigDecimal 的字符串构造器可完全保留任意长度的十进制数字精度。
以 Jackson 为例,推荐以下实践方式:
✅ 正确做法(推荐):
// 假设使用 Jackson,且已通过 JsonNode 或 ObjectMapper 获取原始值
JsonNode node = objectMapper.readTree(jsonString);
String amountStr = node.path("amount").asText(); // 确保 asText() —— 不调用 asDouble()
BigDecimal amount = new BigDecimal(amountStr).setScale(2, RoundingMode.HALF_UP);✅ 若必须兼容现有 ConcurrentHashMap<String, Object> 结构(如 extensionMap),需先判断值类型:
Object rawValue = extensionMap.get("amount");
BigDecimal amount;
if (rawValue instanceof String) {
amount = new BigDecimal((String) rawValue).setScale(2, RoundingMode.HALF_UP);
} else if (rawValue instanceof Number) {
// ⚠️ 警告:此处 Number 可能已是 double/Long,精度已失!应尽量避免进入此分支
amount = BigDecimal.valueOf(((Number) rawValue).doubleValue()) // ❌ 不推荐!
.setScale(2, RoundingMode.HALF_UP);
} else {
throw new IllegalArgumentException("Unsupported amount type: " + rawValue.getClass());
}⚠️ 注意事项:
总结:精度保障始于数据源头。只要 JSON 中的数值以字符串形式传递,并在 Java 层跳过任何 double 解析步骤,即可实现任意长度小数的无损 BigDecimal 转换。
下一篇:网易大神全境封锁2战绩查询方法
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9