You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 15:15:08