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
相关产品推荐
相关产品推荐

