如何将JSON空字符串反序列化为Java POJO的空List?
问题描述
我的POJO类Student包含List<String>类型的courseNames字段,定义如下:
public class Student { private List<String> courseNames; // getter、setter省略 }
当第三方传入数组格式的JSON时,反序列化正常:
{ "courseNames": ["abc", "xyz"] }
但第三方偶尔会传入空字符串:
{ "courseNames": "" }
此时希望courseNames被自动填充为空List。我尝试实现自定义JsonDeserializer但未完成,代码如下:
public class StringToEmptyListJsonDeserializer extends JsonDeserializer<List<String>> { @Override public List<String> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { if(jsonParser.getCurrentToken() != JsonToken.START_ARRAY) { return new ArrayList<>(); } return // 此处该如何实现? } }
请问如何委托默认的List反序列化器处理数组情况?或者有更优的解决方案?
解决方案
方案一:完善自定义JsonDeserializer,委托默认反序列化器
你可以通过DeserializationContext获取默认的List<String>反序列化器,在数组格式时委托它处理,非数组格式(比如空字符串)则返回空List。完整代码如下:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class StringToEmptyListJsonDeserializer extends StdDeserializer<List<String>> { protected StringToEmptyListJsonDeserializer() { super(List.class); } @Override public List<String> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { JsonToken currentToken = jsonParser.getCurrentToken(); // 非数组类型(空字符串、null等)直接返回空List if (currentToken != JsonToken.START_ARRAY) { // 跳过当前无效token,避免后续解析出错 jsonParser.skipChildren(); return new ArrayList<>(); } // 获取默认的List<String>反序列化器 JavaType listType = deserializationContext.getTypeFactory() .constructCollectionType(List.class, String.class); JsonDeserializer<?> defaultDeserializer = deserializationContext.findRootValueDeserializer(listType); // 委托默认反序列化器处理数组 @SuppressWarnings("unchecked") List<String> result = (List<String>) defaultDeserializer.deserialize(jsonParser, deserializationContext); // 确保返回非null的List return result != null ? result : new ArrayList<>(); } }
然后在Student类的字段上添加注解,指定使用该反序列化器:
public class Student { @JsonDeserialize(using = StringToEmptyListJsonDeserializer.class) private List<String> courseNames; // getter、setter省略 }
方案二:更简洁的注解+配置方案(无需自定义反序列化器)
如果你不想写自定义反序列化器,可以结合Jackson的配置和注解实现:
- 首先配置
ObjectMapper,允许将空字符串视为null:
ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
- 然后在
courseNames字段上添加@JsonSetter(nulls = Nulls.AS_EMPTY),将null值转换为空List:
public class Student { @JsonSetter(nulls = Nulls.AS_EMPTY) private List<String> courseNames; // getter、setter省略 }
这样当传入空字符串时,会先被转为null,再被自动替换为空List;传入数组时则正常反序列化。
方案三:通过Setter方法直接处理(简单但不够优雅)
你可以修改courseNames的Setter方法,直接处理不同类型的输入:
public class Student { private List<String> courseNames = new ArrayList<>(); public void setCourseNames(Object courseNames) { if (courseNames instanceof List) { this.courseNames = (List<String>) courseNames; } else if (!(courseNames instanceof String) || !((String) courseNames).isEmpty()) { // 非空字符串或其他类型,可根据需求调整逻辑,比如抛出异常或清空List this.courseNames.clear(); } // 空字符串情况保持当前空List } // getter省略 }
这种方式无需额外配置,但需要将Setter的参数改为Object类型,破坏了类型安全性,适合简单场景。
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

