Spring Boot中Jackson实现Optional属性默认设为empty的全局方案
解决Spring Boot中Jackson自动初始化未传值的Optional属性为Optional.empty
方案一:通过BeanDeserializerModifier在反序列化前初始化属性
这个方案利用Jackson的beforeDeserialization扩展点,在实例创建完成、Jackson开始赋值之前,自动将所有Optional类型的空属性设为Optional.empty()。
1. 自定义BeanDeserializerModifier及包装类
import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.BeanDeserializer; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; import java.lang.reflect.Field; import java.util.Optional; public class OptionalDefaultDeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) { if (deserializer instanceof BeanDeserializer) { return new OptionalDefaultBeanDeserializer((BeanDeserializer) deserializer); } return super.modifyDeserializer(config, beanDesc, deserializer); } private static class OptionalDefaultBeanDeserializer extends BeanDeserializer implements ResolvableDeserializer { private final BeanDeserializer originalDeserializer; public OptionalDefaultBeanDeserializer(BeanDeserializer originalDeserializer) { super(originalDeserializer); this.originalDeserializer = originalDeserializer; } @Override public Object beforeDeserialization(com.fasterxml.jackson.core.JsonParser p, DeserializationContext ctxt) throws java.io.IOException { Object bean = super.beforeDeserialization(p, ctxt); // 遍历所有字段,初始化空的Optional属性 for (Field field : bean.getClass().getDeclaredFields()) { if (field.getType().equals(Optional.class)) { field.setAccessible(true); try { if (field.get(bean) == null) { field.set(bean, Optional.empty()); } } catch (IllegalAccessException e) { // 按需处理异常,比如打印日志 } } } return bean; } @Override public void resolve(DeserializationContext ctxt) throws java.io.IOException { ((ResolvableDeserializer) originalDeserializer).resolve(ctxt); } } }
2. 注册自定义Module
import com.fasterxml.jackson.databind.module.SimpleModule; public class OptionalDefaultModule extends SimpleModule { public OptionalDefaultModule() { super(); setDeserializerModifier(new OptionalDefaultDeserializerModifier()); } }
3. 配置Spring Boot Jackson
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.fasterxml.jackson.databind.ObjectMapper; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new OptionalDefaultModule()); // 可添加其他Jackson配置,比如JavaTimeModule等 return objectMapper; } }
方案二:自定义ValueInstantiator在实例化时初始化属性
这个方案直接替换Jackson的默认实例化器,在通过空构造创建对象后,立即初始化所有Optional类型的空属性,完全符合你“空构造实例化后、赋值前”的需求。
1. 自定义ValueInstantiator
import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.util.StdValueInstantiator; import java.lang.reflect.Field; import java.util.Optional; public class OptionalDefaultValueInstantiator extends StdValueInstantiator { public OptionalDefaultValueInstantiator(StdValueInstantiator src) { super(src); } @Override public Object createUsingDefault(DeserializationContext ctxt) throws java.io.IOException { Object bean = super.createUsingDefault(ctxt); // 初始化空的Optional属性 for (Field field : bean.getClass().getDeclaredFields()) { if (field.getType().equals(Optional.class)) { field.setAccessible(true); try { if (field.get(bean) == null) { field.set(bean, Optional.empty()); } } catch (IllegalAccessException e) { // 按需处理异常 } } } return bean; } }
2. 自定义Modifier替换实例化器
import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; public class OptionalInstantiatorModifier extends BeanDeserializerModifier { @Override public ValueInstantiator modifyValueInstantiator(DeserializationConfig config, BeanDescription beanDesc, ValueInstantiator defaultInstantiator) { if (defaultInstantiator instanceof StdValueInstantiator) { return new OptionalDefaultValueInstantiator((StdValueInstantiator) defaultInstantiator); } return super.modifyValueInstantiator(config, beanDesc, defaultInstantiator); } }
3. 注册Module及配置Spring(同方案一)
只需把Module里的Modifier换成OptionalInstantiatorModifier即可,其余配置和方案一一致。
注意事项
- 两个方案都会保留类中已手动设置的
Optional默认值(比如private Optional<String> name = Optional.empty();),因为代码中判断了属性为null时才赋值。 - 若需要处理嵌套对象中的
Optional属性,可以在遍历字段时增加递归逻辑:判断字段类型是否为自定义非基础类型,然后递归初始化该字段对象的Optional属性。
内容的提问来源于stack exchange,提问作者Iv4n
相关产品推荐
相关产品推荐

