Jackson v3反序列化继承java.util.Properties的类时出现类型转换异常
Jackson v3升级后NodeProperties反序列化类型转换错误问题
问题背景
应用从Jackson v2升级到v3后,遭遇反序列化异常。自定义类NodeProperties继承自java.util.Properties,仅包含处理Properties的便利方法,无额外自定义字段:
public class NodeProperties extends Properties { ... }
错误详情
读取包含内部数据结构的JSON文件时,抛出以下异常:
tools.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `my.application.connections.RESTConnection`, problem: Cannot cast java.util.Properties to my.application.utils.NodeProperties at [Source: (BufferedInputStream); line: 38, column: 2]
已排查方向
- 给
NodeProperties添加虚拟字段,问题未解决,排除无自定义字段导致的问题 - 确认不属于多态场景,
NodeProperties未继承抽象类或实现相关接口
核心疑问
为何Jackson v3会尝试创建父类Properties对象,而非实际需要的NodeProperties子类?
原因分析
Jackson v3对java.util.Properties的反序列化逻辑做了变更:v2版本中,遇到继承自Properties的子类时,Jackson会优先实例化子类;但v3中,PropertiesDeserializer被优化为默认返回Properties实例,忽略了子类类型——因为Properties本质是特殊的Map实现,Jackson默认将其当作普通Map处理,不会自动关联到子类类型。
解决方案
1. 为NodeProperties添加自定义反序列化器
实现一个自定义反序列化器,强制实例化NodeProperties并填充属性:
public class NodePropertiesDeserializer extends StdDeserializer<NodeProperties> { protected NodePropertiesDeserializer() { super(NodeProperties.class); } @Override public NodeProperties deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { NodeProperties props = new NodeProperties(); JsonNode node = p.getCodec().readTree(p); if (node.isObject()) { for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext(); ) { Map.Entry<String, JsonNode> entry = it.next(); props.setProperty(entry.getKey(), entry.getValue().asText()); } } return props; } }
通过注解将反序列化器绑定到NodeProperties类:
@JsonDeserialize(using = NodePropertiesDeserializer.class) public class NodeProperties extends Properties { ... }
2. 通过Jackson模块全局配置替换默认反序列化逻辑
如果需要全局生效,可通过SimpleModule替换默认的PropertiesDeserializer:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(NodeProperties.class, new NodePropertiesDeserializer()); mapper.registerModule(module);
3. 可选:启用大小写不敏感配置
若JSON中的键存在大小写差异,可添加此配置避免属性丢失:
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
验证
应用上述任一配置后,Jackson会在反序列化时正确创建NodeProperties实例,避免类型转换错误。
内容的提问来源于stack exchange,提问作者mmo
相关产品推荐
相关产品推荐

