使用Jackson readerForUpdating更新@Builder对象遇反序列化不支持问题
解决Jackson
readerForUpdating无法更新@Builder+@Jacksonized类的问题 你遇到的错误根源是**@Jacksonized与@Builder的组合生成的反序列化器仅支持创建新对象,不兼容readerForUpdating修改已有实例的逻辑**。Lombok的@Jacksonized会生成基于Builder模式的反序列化逻辑,而Builder本身是用来构建新对象的,无法对已有实例的属性进行修改,这就和readerForUpdating的需求产生了冲突。
下面提供两种可行的解决办法:
方案一:给类添加无参构造器
Jackson的readerForUpdating要求目标类具备可访问的无参构造器,但@Builder默认会覆盖@Data的无参构造器生成逻辑。只需给每个实体类补充@NoArgsConstructor(可选搭配@AllArgsConstructor保留Builder的完整功能)即可:
@Data @Builder @Jacksonized @NoArgsConstructor // 新增无参构造器,让Jackson能处理实例更新 @AllArgsConstructor // 可选,不影响更新逻辑,但保留Builder创建对象的能力 public class Experiment { Integer id; String type; Monster monster; } @Data @Builder @Jacksonized @NoArgsConstructor @AllArgsConstructor public class Monster { String name; String type; }
添加注解后,原来的readerForUpdating代码就能正常运行,既保留了Builder模式的对象创建能力,又支持Jackson的实例更新逻辑。
方案二:通过对象拷贝实现批量更新
如果无法修改原有类的注解(比如类来自第三方依赖),可以先将更新JSON解析为新对象,再把非空属性拷贝到原有实例中。这里以Spring的BeanUtils为例(纯Jackson环境也可自行实现属性拷贝逻辑):
// 1. 将更新JSON解析为新的Experiment对象 Experiment updateSource = objectMapper.readValue(monster_json2, Experiment.class); // 2. 拷贝非空属性到原有实例,避免覆盖原有非null值 BeanUtils.copyProperties(updateSource, experiment, getNullPropertyNames(updateSource)); // 辅助方法:获取对象中值为null的属性名,拷贝时跳过这些属性 private static String[] getNullPropertyNames(Object source) { BeanWrapper srcWrapper = new BeanWrapperImpl(source); PropertyDescriptor[] propertyDescriptors = srcWrapper.getPropertyDescriptors(); Set<String> nullPropertyNames = new HashSet<>(); for (PropertyDescriptor pd : propertyDescriptors) { Object value = srcWrapper.getPropertyValue(pd.getName()); if (value == null) { nullPropertyNames.add(pd.getName()); } } return nullPropertyNames.toArray(new String[0]); }
这种方式无需修改原类结构,还能灵活控制更新范围(比如只更新非空属性),缺点是需要引入额外工具类或自行实现拷贝逻辑。
内容的提问来源于stack exchange,提问作者GenericUserName
相关产品推荐
相关产品推荐

