
本文介绍在 jackson 中仅通过注解(不使用 typereference、自定义反序列化器或显式集合类型)将形如 [{"name":"a"},{"name":"b"}] 的数组型 json 直接反序列化为含 list
Jackson 默认要求 JSON 结构与目标类结构严格匹配:若 JSON 以数组(START_ARRAY)开头,而目标类是普通 POJO(非集合类型),则会抛出 JsonMappingException: Can not deserialize instance of ... out of START_ARRAY token。要绕过这一限制并纯靠注解实现,核心思路是让 Jackson 将整个 JSON 数组“当作构造函数参数传入”,而非尝试匹配字段名。
✅ 正确做法是:为封装类添加一个带 @JsonCreator 注解的单参构造函数,该参数类型为 List
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class GetPersonsResponseDto {
public List persons;
// ✅ 关键:用 @JsonCreator 告诉 Jackson ——
// 当遇到数组时,将整个数组作为此构造函数的参数传入
@JsonCreator
public GetPersonsResponseDto(List persons) {
this.persons = persons;
}
// ⚠️ 必须保留无参构造函数(Jackson 反序列化内部可能需要)
public GetPersonsResponseDto() {
this.persons = List.of(); // 或 new ArrayList<>()
}
}
// Person 类保持简洁(字段名与 JSON key 一致即可)
public class Person {
public String name;
} 此时,以下代码可直接工作:
ObjectMapper mapper = new ObjectMapper(); GetPersonsResponseDto response = mapper.readValue(jsonInput, GetPersonsResponseDto.class); // response.persons.size() == 2, 内容正确解析
? 注意事项:
- @JsonCreator 必须标注在接受 List
的构造函数上 ,而非静态工厂方法(否则 Jackson 无法识别数组输入); - 无参构造函数不可省略(尤其在较新 Jackson 版本中,部分内部逻辑依赖默认构造器);
- 若 Person 字段名与 JSON 不完全一致(如 JSON 是 "full_name"),需配合 @JsonProperty("full_name") 在 Person 类中声明;
- 此方案兼容 Jackson 2.9+(主流 Spring Boot 2.3+ 默认版本),但低于 2.7 的旧版本可能存在兼容性问题,建议升级 Jackson 至 2.12+ 以确保稳定性。
? 总结:无需 TypeReference、不写 Deserializer、不改调用方式——仅靠 @JsonCreator + 构造函数 + 无参构造器 三要素,即可优雅实现数组根 JSON 到对象包装类的零侵入反序列化。










