概述
在进行对象更新操作时,若源对象部分字段为空,直接拷贝可能导致目标对象原有数据被空值覆盖。以下介绍两种常见处理方式。
一、使用 BeanUtils 忽略空属性
Spring 的 BeanUtils.copyProperties 支持指定忽略的属性列表。可以通过自定义方法获取源对象中值为 null 的属性名,并在拷贝时忽略这些属性。
public static void copyNonNullProperties(Object src, Object target) {
BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
}
public static String[] getNullPropertyNames(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<>();
for (PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) {
emptyNames.add(pd.getName());
}
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
二、使用 ObjectMapper 进行更新
Jackson 的 ObjectMapper 提供了灵活的序列化和反序列化配置。通过设置 NON_NULL 包含策略和忽略未知属性,可以实现仅更新非空字段。
ObjectMapper objectMapper = new ObjectMapper();
// 如果属性为空则不参与序列化
objectMapper.setSerializationInclusion(JsonInclude.Inclusion.NON_NULL);
// 如果源里面有的字段,目标里面没有就忽略
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, );
objectMapper.writeValueAsString(newCustomerRequestDTO);
objectMapper.readerForUpdating(newCustomer);
objectReader.readValue(outJson);

