如何让Jackson将显式null反序列化为Optional.EMPTY且不序列化空Optional为null
Jackson中Optional序列化与反序列化的冲突解决
问题背景
现有如下POJO类:
public static class Test { private Optional<String> something; }
以及配置好的Jackson映射器:
var OBJECT_MAPPER = JsonMapper.builder() .addModule(new Jdk8Module()) .serializationInclusion(JsonInclude.Include.NON_ABSENT) .build();
当前遇到的问题:
- 反序列化JSON字符串
{"something": null}时,得到的Test对象中something属性为null,但期望该值为Optional.EMPTY。 - 期望的Optional反序列化规则:
- JSON中属性值为
null→ 反序列化为Optional.EMPTY - JSON中未提供该属性 → POJO中属性保持
null - JSON中属性为非
null值 → 反序列化为Optional.of(对应值)
- JSON中属性值为
但如果移除serializationInclusion(JsonInclude.Include.NON_ABSENT)配置,虽然能满足反序列化需求,却会导致序列化不符合预期:
Test test = new Test(); // 期望序列化为{}, 而非{"something": null} Test test2 = new Test(); test2.setSomething(Optional.EMPTY); // 期望序列化为{}, 而非{"something": null}
需求核心:能否为序列化和反序列化分别设置serializationInclusion?
解决方案
Jackson本身不支持直接为序列化、反序列化单独配置serializationInclusion,但可以通过两种方式实现需求:
方式一:自定义Optional序列化器与反序列化器
通过定制序列化和反序列化逻辑,精准控制Optional的处理行为:
自定义序列化器
确保当Optional为null或Optional.EMPTY时,配合NON_ABSENT配置过滤掉该属性;非空Optional则输出实际值:
public class CustomOptionalSerializer extends StdSerializer<Optional<?>> { public CustomOptionalSerializer() { super(Optional.class); } @Override public void serialize(Optional<?> value, JsonGenerator gen, SerializerProvider provider) throws IOException { if (value == null || value.isEmpty()) { gen.writeNull(); // 会被NON_ABSENT配置过滤 } else { gen.writeObject(value.get()); } } }
自定义反序列化器
将JSON中的null值转为Optional.EMPTY,非null值包装为Optional.of(),未提供属性则保留POJO属性为null:
public class CustomOptionalDeserializer extends StdDeserializer<Optional<?>> { public CustomOptionalDeserializer() { super(Optional.class); } @Override public Optional<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node.isNull()) { return Optional.empty(); } Object value = ctxt.readValue(p, ctxt.getContextualType().getContentType().getRawClass()); return Optional.ofNullable(value); } }
注册自定义组件到映射器
var OBJECT_MAPPER = JsonMapper.builder() .addModule(new Jdk8Module()) .serializationInclusion(JsonInclude.Include.NON_ABSENT) .addSerializer(Optional.class, new CustomOptionalSerializer()) .addDeserializer(Optional.class, new CustomOptionalDeserializer()) .build();
方式二:使用两个独立的ObjectMapper
分别创建用于序列化和反序列化的映射器,各自配置所需规则:
// 序列化专用Mapper:保留NON_ABSENT配置,过滤空值属性 var SERIALIZE_MAPPER = JsonMapper.builder() .addModule(new Jdk8Module()) .serializationInclusion(JsonInclude.Include.NON_ABSENT) .build(); // 反序列化专用Mapper:不设置序列化过滤规则,满足null转Optional.EMPTY的需求 var DESERIALIZE_MAPPER = JsonMapper.builder() .addModule(new Jdk8Module()) .build();
使用时序列化调用SERIALIZE_MAPPER,反序列化调用DESERIALIZE_MAPPER即可。
内容的提问来源于stack exchange,提问作者k.liakos
相关产品推荐
相关产品推荐

