如何让ObjectMapper在更新实体时忽略空字符串字段?
解决Jackson updateValue覆盖空字符串字段的问题
问题原因
你使用ObjectMapper.updateValue()将CustomerDetail DTO映射到CustomerRegistration实体时,请求体中的空字符串字段会覆盖数据库原有值,但@JsonInclude(Include.NON_NULL)仅忽略null值,空字符串不属于null范畴,因此无法阻止更新。
解决方案一:使用NON_EMPTY注解规则
将CustomerDetail类上的@JsonInclude注解改为Include.NON_EMPTY,该规则会忽略null值、空字符串、空集合/数组等空值类型:
@JsonInclude(JsonInclude.Include.NON_EMPTY) public class CustomerDetail { private String firstName; private String middleName; private String lastName; private String addr1; private String addr2; // getter、setter方法 }
修改后,当middleName为空字符串时,Jackson在执行updateValue()时会跳过该字段,不会覆盖实体中已有的值。
如果不想修改DTO的全局注解,也可以在ObjectMapper实例上全局配置:
ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); objectMapper.updateValue(customer, customerDetail);
解决方案二:手动过滤空属性(自定义控制)
若需要更精细的过滤逻辑(比如仅忽略特定字段的空字符串),可以手动提取空属性名,再使用BeanUtils复制非空属性:
public CustomerRegistration editCustomerDetails(Long id, CustomerDetail customerDetail) { CustomerRegistration customer = customerRegistrationRepository.findByRegistrationId(id); if (customer == null) return null; // 复制时跳过空字符串和null的属性 BeanUtils.copyProperties(customerDetail, customer, getEmptyPropertyNames(customerDetail)); customer.setModifiedTs(Timestamp.valueOf(LocalDateTime.now())); return customerRegistrationRepository.save(customer); } // 提取需要忽略的空属性名 private String[] getEmptyPropertyNames(Object source) { BeanWrapper srcWrapper = new BeanWrapperImpl(source); PropertyDescriptor[] descriptors = srcWrapper.getPropertyDescriptors(); Set<String> emptyFields = new HashSet<>(); for (PropertyDescriptor desc : descriptors) { Object value = srcWrapper.getPropertyValue(desc.getName()); // 判断是否为null或空白字符串(含空格的空字符串) if (value == null || (value instanceof String && ((String) value).isBlank())) { emptyFields.add(desc.getName()); } } return emptyFields.toArray(new String[0]); }
这种方式可以根据需求调整判断逻辑,比如是否忽略带空格的空字符串,灵活性更高。
内容的提问来源于stack exchange,提问作者I_GOT_THIS
相关产品推荐
相关产品推荐

