如何使用Jackson将单元素List属性序列化为单个对象?
Jackson实现List单元素自动序列化为单个对象的方案
实现思路
自定义Jackson序列化器,对List类型字段做长度判断,长度为1时直接序列化第一个元素,其他情况保持默认数组行为。
步骤1:定义通用单元素List序列化器
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; import java.util.List; public class SingleElementListSerializer extends StdSerializer<List<?>> { // 无参构造必须保留,Jackson序列化时通过反射调用 public SingleElementListSerializer() { this(null); } public SingleElementListSerializer(Class<List<?>> t) { super(t); } @Override public void serialize(List<?> value, JsonGenerator gen, SerializerProvider provider) throws IOException { // null值直接输出null,可根据需求修改为输出空数组 if (value == null) { gen.writeNull(); return; } switch (value.size()) { case 0: // 空列表输出空数组,可根据需求修改为输出null gen.writeStartArray(); gen.writeEndArray(); break; case 1: // 单个元素直接序列化对应对象 provider.defaultSerializeValue(value.get(0), gen); break; default: // 多个元素序列化为标准数组格式 gen.writeStartArray(); for (Object item : value) { provider.defaultSerializeValue(item, gen); } gen.writeEndArray(); } } }
步骤2:绑定序列化器
两种绑定方式可按需选择:
方式1:仅对指定字段生效(推荐,粒度更灵活)
直接在POJO的bars字段上加@JsonSerialize注解指定序列化器即可:
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.List; public class Foo { private String name; @JsonSerialize(using = SingleElementListSerializer.class) private List<Bar> bars; // 省略getters、setters }
方式2:全局对所有List类型生效
将序列化器注册到ObjectMapper,所有List类型字段都会自动应用该规则:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import java.util.List; ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 注册全局List序列化器 module.addSerializer(List.class, new SingleElementListSerializer()); objectMapper.registerModule(module);
反序列化适配
如果后续需要把序列化后的JSON反序列回Java对象,需要开启ACCEPT_SINGLE_VALUE_AS_ARRAY配置,支持单个对象自动转换为List:
import com.fasterxml.jackson.databind.DeserializationFeature; objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
效果验证
| bars字段值 | 序列化结果 |
|---|---|
| null | "bars": null |
| 空列表 | "bars": [] |
| 仅1个Bar元素 | "bars": {"bar属性":"对应值"} |
| 多个Bar元素 | "bars": [{},{}] |
内容的提问来源于stack exchange,提问作者andrewdleach
相关产品推荐
相关产品推荐

