如何仅配置Jackson将各类非存在List反序列化为空List?
问题:Jackson配置实现List类型缺失/Null时反序列化为空List(不修改实体类)
需求
将所有场景下的非有效List(包括JSON中字段缺失、值为Null、根对象为Null等情况)反序列化为空List,要求不可修改实体类,仅通过配置ObjectMapper实现。
测试代码
用于验证的测试类如下:
class EmptyListDeserializerTest { final ObjectMapper objectMapper = new ObjectMapper(); // 此处为待调整的ObjectMapper配置 @Test void test2() throws JsonProcessingException { // 测试根对象为Null的场景 final var result = objectMapper.readValue("null", new TypeReference<List<MyClass>>() {}); assertThat(result).isEmpty(); } @Test void test3() throws JsonProcessingException { // 测试实体类中List字段值为Null的场景 final var json = """ [{ "name": "John Doe", "address": null }] """; final var result = objectMapper.readValue(json, new TypeReference<List<MyComplexClass>>() {}); assertThat(result.get(0).address).isEmpty(); } @Test void test4() throws JsonProcessingException { // 测试实体类中List字段缺失的场景 final var json = """ [{ "name": "John Doe" }] """; final var result = objectMapper.readValue(json, new TypeReference<List<MyComplexClass>>() {}); assertThat(result.get(0).address).isEmpty(); } public static class MyClass { public MyClass() {} private String name; public MyClass(final String name) { this.name = name; } public String getName() { return name; } public void setName(final String name) { this.name = name; } } public static class MyComplexClass { public MyComplexClass() {} private String name; private List<String> address; public MyComplexClass(final String name, final List<String> address) { this.name = name; this.address = address; } public String getName() { return name; } public void setName(final String name) { this.name = name; } public List<String> getAddress() { return address; } public void setAddress(final List<String> address) { this.address = address; } } }
当前遇到的问题
- 仅配置
configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY, Nulls.AS_EMPTY))时,只有test3通过,test2(根对象Null)和test4(字段缺失)均失败。 - 添加自定义List反序列化器并修改test2输入为带引号的
"\"null\""后,test2通过但test3失败,且自定义反序列化器的泛型处理存在问题。
问题分析
- 初始配置仅处理了字段值为Null的场景,未覆盖字段缺失和根对象为Null的情况。
- 自定义反序列化器直接替换了List的默认反序列化逻辑,破坏了泛型类型的正确处理,导致test3中
address字段无法正确反序列化为List<String>。
正确配置方案
通过以下配置同时覆盖所有场景,无需修改实体类:
final ObjectMapper objectMapper = new ObjectMapper(); { // 配置List类型的setter规则:Null值、缺失字段均转为空List objectMapper.configOverride(List.class) .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY) .withSetterNulls(Nulls.AS_EMPTY) .withMissingSetter(Nulls.AS_EMPTY)); // 配置根对象为Null时返回空List,同时保留原有泛型反序列化逻辑 objectMapper.registerModule(new SimpleModule() { @Override public void setupModule(SetupContext context) { context.addBeanDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) { if (List.class.isAssignableFrom(beanDesc.getBeanClass())) { return new JsonDeserializer<>() { @Override public List<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.getCurrentToken() == JsonToken.VALUE_NULL) { return Collections.emptyList(); } // 委托原有反序列化器处理正常List,保留泛型支持 return (List<?>) deserializer.deserialize(p, ctxt); } }; } return deserializer; } }); } }); }
配置说明
configOverride部分:
forValueNulls(Nulls.AS_EMPTY):处理JSON中字段值为Null的场景(对应test3)。withMissingSetter(Nulls.AS_EMPTY):处理JSON中字段缺失的场景(对应test4)。withSetterNulls(Nulls.AS_EMPTY):确保当setter接收Null值时自动转为空List。
BeanDeserializerModifier部分:
- 仅针对List类型的根对象,当JSON输入为Null时返回空List(对应test2)。
- 委托原有反序列化器处理正常List结构,避免破坏泛型类型的解析。
测试修正
将之前错误修改的test2恢复为原始输入(反序列化JSON Null而非字符串"null"):
@Test void test2() throws JsonProcessingException { final var result = objectMapper.readValue("null", new TypeReference<List<MyClass>>() {}); assertThat(result).isEmpty(); }
此时三个测试用例均可正常通过。
内容的提问来源于stack exchange,提问作者DavidO
相关产品推荐
相关产品推荐

