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

ObjectMapper.readTree返回ObjectNode/TextNode而非DecimalNode问题求解

异常行为成因
  • MongoDB Java驱动的Document.toJson()方法默认会将Decimal128类型序列化为MongoDB扩展JSON格式,输出结构为{"$numberDecimal": "实际数值字符串"},而非直接输出数值本身
  • 普通未适配MongoDB数据类型的Jackson ObjectMapper无法识别该扩展结构,会将其解析为嵌套ObjectNode,其中$numberDecimal对应值为TextNode,无法生成预期的DecimalNode
修复方案

第一步:引入MongoDB Jackson数据类型适配依赖

如果使用Maven,在pom.xml中添加如下依赖:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-mongo</artifactId>
</dependency>

Gradle配置:

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-mongo'

第二步:自定义ObjectMapper配置

在Spring Boot中配置ObjectMapper时注册Mongo模块,同时开启大十进制数解析配置:

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册MongoDB数据类型适配模块
        objectMapper.registerModule(new MongoModule());
        // 开启浮点数自动解析为BigDecimal,避免精度丢失
        objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
        return objectMapper;
    }
}

第三步:调整转换器实现

不要通过Document.toJson()序列化再反序列化的方式转换,直接使用convertValue方法完成对象到JsonNode的转换:

@ReadingConverter
public class DocumentToJsonNodeConverter implements Converter<Document, JsonNode> {

    private final ObjectMapper objectMapper;

    public DocumentToJsonNodeConverter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @SneakyThrows
    public JsonNode convert(Document source) {
        // 直接转换Document对象而非先转JSON字符串
        return objectMapper.convertValue(source, JsonNode.class);
    }
}

如果你不想引入额外依赖,也可以自行实现Document的递归遍历逻辑,遇到Decimal128类型字段时调用decimal128.bigDecimalValue()转为BigDecimal对象,再构建JsonNode,不过适配成本更高,不推荐。

调整完成后,Decimal128类型会被直接映射为存储BigDecimal的DecimalNode,符合预期使用需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 17:18:03