Jackson解析Double:字符串/纯数字格式兼容问题及解决问询
问题分析与解决方案
问题场景
JSON中的field1字段存在两种格式:
{ "field1" : 123.00 }
或
{"field1" : "123.00" }
对应的POJO定义如下:
class Response{ Double field1; }
当field1为字符串格式时,抛出以下错误:
Caused by: java.lang.NoSuchFieldError: USE_FAST_DOUBLE_PARSER at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$DoubleDeserializer._parseDouble(NumberDeserializers.java:755) at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$DoubleDeserializer.deserialize(NumberDeserializers.java:684)
但Int/Long类型的字段在两种格式下均可正常解析,疑问点包括:Double解析失败的原因、是否有兼容注解、修复方法(已用@JsonSetter解决)。
为什么Double解析失败而Int/Long可以?
- Jackson版本依赖不匹配:
报错中的USE_FAST_DOUBLE_PARSER是Jackson-core库中新增的常量,如果你的jackson-databind和jackson-core版本不一致(比如databind用了高版本、core用了低版本),就会出现找不到该字段的错误。 - 反序列化器逻辑差异:
Jackson默认的Int/Long反序列化器内置了字符串转数值的兼容逻辑,能直接处理字符串格式的数字;而旧版本的Double反序列化器默认没有这个兼容逻辑,且依赖特定版本的core库字段,导致解析字符串格式时触发错误。
兼容两种格式的解决方案
1. 自定义@JsonSetter方法(当前可用方案)
通过在setter方法中处理两种类型的输入,手动完成类型转换:
class Response { Double field1; @JsonSetter public void setField1(Object value) { if (value instanceof String) { this.field1 = Double.parseDouble((String) value.trim()); } else if (value instanceof Number) { this.field1 = ((Number) value).doubleValue(); } } }
2. 自定义反序列化器+@JsonDeserialize注解
编写通用的Double兼容反序列化器,指定给字段使用:
public class FlexibleDoubleDeserializer extends JsonDeserializer<Double> { @Override public Double deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken token = p.getCurrentToken(); if (token == JsonToken.VALUE_STRING) { return Double.parseDouble(p.getText().trim()); } else if (token.isNumeric()) { return p.getDoubleValue(); } return null; } }
在POJO字段上添加注解:
class Response { @JsonDeserialize(using = FlexibleDoubleDeserializer.class) Double field1; }
3. 统一Jackson依赖版本
升级jackson-databind和jackson-core到相同的稳定版本(比如2.15.x及以上),新版本的Jackson已经修复了Double反序列化器的兼容问题,默认支持直接解析字符串格式的Double值,无需额外配置。
内容的提问来源于stack exchange,提问作者Deekshith Anand
相关产品推荐
相关产品推荐

