无注解反序列化时修改JSON AST的标准实现方案
Jackson反序列化第三方类时移除指定字段的标准方案
针对第三方类无法修改、反序列化时因id和ids字段冲突导致数据覆盖的问题,推荐使用BeanDeserializerModifier + DelegatingDeserializer的组合方案,无需编写全量反序列化器,同时兼容后续字段变更,且能避免无限循环。
核心思路
通过Jackson的扩展机制,在默认反序列化逻辑执行前,先修改JSON AST移除id字段,再让默认的BeanDeserializer处理剩余内容。既保留了默认反序列化的兼容性,又解决了字段冲突问题。
代码实现
1. 自定义DelegatingDeserializer处理字段移除
继承DelegatingDeserializer包装默认反序列化器,在反序列化前修改JSON节点:
public class RemoveIdFieldDeserializer extends DelegatingDeserializer { public RemoveIdFieldDeserializer(JsonDeserializer<?> delegate) { super(delegate); } @Override protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegate) { return new RemoveIdFieldDeserializer(newDelegate); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 将原始JSON解析为可修改的JsonNode JsonNode rootNode = p.readValueAsTree(); // 移除冲突的id字段 if (rootNode.isObject()) { ((ObjectNode) rootNode).remove("id"); } // 基于修改后的节点创建新的JsonParser JsonParser modifiedParser = ctxt.getNodeFactory().treeAsTokens(rootNode); // 交给默认反序列化器处理修改后的JSON return _delegate.deserialize(modifiedParser, ctxt); } }
2. 用BeanDeserializerModifier注册自定义处理逻辑
通过Modifier为目标第三方类绑定自定义Deserializer:
public class ThirdPartyClassDeserializerModifier extends BeanDeserializerModifier { private final Class<?> targetClass; public ThirdPartyClassDeserializerModifier(Class<?> targetClass) { this.targetClass = targetClass; } @Override public JsonDeserializer<?> modifyBeanDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) { // 仅对目标第三方类应用自定义处理 if (beanDesc.getBeanClass().equals(targetClass)) { return new RemoveIdFieldDeserializer(deserializer); } return super.modifyBeanDeserializer(config, beanDesc, deserializer); } }
3. 注册到ObjectMapper并使用
将Modifier注册到Jackson的ObjectMapper中,生效自定义逻辑:
// 初始化ObjectMapper ObjectMapper objectMapper = new ObjectMapper(); // 注册自定义模块,绑定目标类的反序列化修改器 objectMapper.registerModule(new SimpleModule() .setDeserializerModifier(new ThirdPartyClassDeserializerModifier(ThirdPartyClass.class))); // 执行反序列化 String json = "{\"id\":1,\"ids\":[1,2,3]}"; ThirdPartyClass instance = objectMapper.readValue(json, ThirdPartyClass.class);
方案优势
- 无全量反序列化器:完全复用Jackson默认的字段解析逻辑,第三方类后续新增字段无需修改代码。
- 无无限循环:通过委托模式调用默认反序列化器,仅在入口处修改一次JSON节点,不会触发递归调用。
- 精准控制:仅针对目标类移除指定字段,不影响其他类的反序列化行为。
内容的提问来源于stack exchange,提问作者Graham
相关产品推荐
相关产品推荐

