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

如何使用Jackson 2.0.2实现指定格式的JSON浮点数输出

解决Jackson序列化浮点数格式不一致的问题

咱们先还原下你的场景:用Jackson 2.0.2版本,执行代码后得到了两种不同的输出,而你想要的是结合两者的优点——data保持10000000.00的格式,data2变成0.0。

先说说为什么会出现这种差异:

  • 第一个开启了USE_BIG_DECIMAL_FOR_FLOATS的ObjectMapper,会把JSON里的浮点数解析成BigDecimal类型,序列化时会保留原始的数字字符串格式,所以0E-7就原样输出了;
  • 第二个默认的ObjectMapper会把浮点数解析成Double类型,序列化时用Double的默认规则,把10000000.00转成科学计数法1.0E7,同时把0E-7转成0.0。

要实现你想要的输出,咱们可以通过自定义BigDecimal序列化器来控制格式,具体步骤如下:

步骤1:编写自定义BigDecimal序列化器

这个序列化器会针对不同的BigDecimal值做特殊处理:0值统一输出为0.0,其他值保留原始的小数格式。

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.math.BigDecimal;

public class CustomBigDecimalSerializer extends JsonSerializer<BigDecimal> {
    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (BigDecimal.ZERO.compareTo(value) == 0) {
            // 所有0值统一输出为0.0
            gen.writeNumber("0.0");
        } else {
            // 其他值保留原始的小数格式
            gen.writeNumber(value.toPlainString());
        }
    }
}

步骤2:配置ObjectMapper并使用

把自定义序列化器注册到开启了USE_BIG_DECIMAL_FOR_FLOATS的ObjectMapper中,这样解析和序列化时就会按照我们的规则来:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class Main {
    public static void main(String[] args) throws Exception {
        String jsonString = "{\"data\":10000000.00, \"data2\" : 0E-7}";
        
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
        
        // 注册自定义序列化器
        SimpleModule module = new SimpleModule();
        module.addSerializer(BigDecimal.class, new CustomBigDecimalSerializer());
        mapper.registerModule(module);
        
        JsonNode jsonNode = mapper.readTree(jsonString);
        System.out.println(jsonNode.toString());
    }
}

执行这段代码后,就能得到你想要的输出:{"data":10000000.00,"data2":0.0}。

如果你的场景里只有个别字段需要调整,也可以不用全局注册序列化器,而是直接修改JsonNode的对应节点值,比如:

((ObjectNode) jsonNode).put("data2", BigDecimal.ZERO.setScale(1));

这种方式更适合字段固定的简单场景。

内容的提问来源于stack exchange,提问作者user636856

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:27:37