Java中GSON/ObjectMapper反序列化BigDecimal精度丢失如何解决?
问题根因
JSON规范中没有独立的BigDecimal类型,默认的反序列化逻辑将浮点数字解析为BigDecimal时,会自动裁剪末尾无意义的零,仅保留数值相等的最简形式,导致原始小数位数(scale)丢失。
Gson 修复方案
自定义BigDecimal类型适配器,直接读取JSON中数值的原始字符串构造BigDecimal,避免自动裁剪:
- 实现自定义TypeAdapter
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.math.BigDecimal; public class KeepScaleBigDecimalAdapter extends TypeAdapter<BigDecimal> { @Override public void write(JsonWriter out, BigDecimal value) throws IOException { out.value(value.toPlainString()); } @Override public BigDecimal read(JsonReader in) throws IOException { return new BigDecimal(in.nextString()); } }
- 注册适配器到Gson实例使用
Gson gson = new GsonBuilder() .registerTypeAdapter(BigDecimal.class, new KeepScaleBigDecimalAdapter()) // 非严格模式下支持读取数字类型的原始字符串 .setLenient() .create(); Amount amount = gson.fromJson(response, Amount.class);
Jackson(ObjectMapper) 修复方案
直接开启内置配置项即可保留原始小数位数:
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper objectMapper = new ObjectMapper(); // 直接使用解析器读取的原始字符串构造BigDecimal,不裁剪末尾零 objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FROM_PARSER, true); Amount amount = objectMapper.readValue(response, Amount.class);
补充最优方案(金融场景推荐)
如果允许调整上游JSON结构,将amount字段以字符串类型传递,示例:{"amount":"1.0000"},无需额外配置反序列化规则即可天然保留所有小数位,完全避免精度丢失风险。
内容的提问来源于stack exchange,提问作者vigneshwaran m
相关产品推荐
相关产品推荐

