如何配置Jackson解析数字时使用BigDecimal类型?
解决Jackson解析高精度小数时的精度丢失问题
问题背景
使用Jackson Databind 2.14.2解析JSON时,17位小数的数字(如"myval": 0.09345678901234567)会被默认转换为double类型,导致最后一位精度丢失,实际存储为近似值0.0934567890123456646...。这是因为double作为IEEE 754双精度浮点数,仅能保证15-16位有效数字的精度,无法完整存储17位小数的精确值。
解决方案:强制Jackson用BigDecimal解析数字
可以通过两种方式配置Jackson,让其将JSON中的数字解析为BigDecimal类型,保留完整精度:
1. 全局配置(对整个ObjectMapper生效)
修改ObjectMapper的反序列化配置,开启USE_BIG_DECIMAL_FOR_FLOATS特性,所有浮点类型的JSON数字都会被解析为BigDecimal:
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonConfig { public static ObjectMapper getConfiguredMapper() { ObjectMapper mapper = new ObjectMapper(); // 强制将所有浮点数字解析为BigDecimal mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true); return mapper; } }
2. 局部字段配置(仅对特定字段生效)
如果不需要全局修改,仅针对特定DTO字段配置,可以使用@JsonDeserialize注解指定BigDecimalDeserializer:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.BigDecimalDeserializer; import java.math.BigDecimal; public class MyData { // 仅该字段用BigDecimal解析 @JsonDeserialize(using = BigDecimalDeserializer.class) private BigDecimal myval; // getter、setter方法 public BigDecimal getMyval() { return myval; } public void setMyval(BigDecimal myval) { this.myval = myval; } }
验证测试
使用配置后的ObjectMapper解析目标JSON,验证精度是否保留:
public class TestJacksonPrecision { public static void main(String[] args) throws Exception { String json = "{\"myval\": 0.09345678901234567}"; ObjectMapper mapper = JacksonConfig.getConfiguredMapper(); MyData data = mapper.readValue(json, MyData.class); // 输出精确值:0.09345678901234567 System.out.println(data.getMyval().toString()); } }
注意事项
- 全局配置会影响所有浮点数字的解析,包括原本用
float/double定义的字段,需确保业务代码适配BigDecimal类型。 BigDecimal虽然能保留精度,但计算时需注意设置合适的舍入模式,避免出现其他精度问题。
内容的提问来源于stack exchange,提问作者PatS
相关产品推荐
相关产品推荐

