
本文详解如何使用 Jackson 的 YAMLFactory 和 treeToValue 方法,将 YAML 中嵌套的键值对列表(如 service.env)直接反序列化为 Java 的 List 类型,避免类型擦除导致的 ClassCastException 或空集合问题。
本文详解如何使用 jackson 的 yamlfactory 和 treetovalue 方法,将 yaml 中嵌套的键值对列表(如 service.env)直接反序列化为 java 的 list
在使用 Jackson 处理 YAML 配置时,一个常见误区是试图用 readValue(String, TypeReference) 将 JSON/YAML 数组节点转为泛型集合(如 List<env></env>),但由于 Java 泛型擦除,TypeReference<map env>></map> 与实际数据结构(YAML 中是数组而非对象映射)不匹配,会导致解析失败或空结果。
正确的做法是:优先使用 treeToValue(TreeNode, Class<t>)</t> 方法,它能直接基于 JSON/YAML 树节点的结构进行类型推导,无需手动构造 TypeReference,且天然支持泛型集合反序列化。
以下是完整、可运行的示例代码:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.IOException;
import java.util.List;
// 假设 Env 类已定义如下(需提供无参构造器和 getter/setter)
public class Env {
private String name;
private String value;
public Env() {} // Jackson 反序列化必需
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
@Override
public String toString() {
return String.format("{name=%s, value=%s}", name, value);
}
}
// 解析入口示例
public class YamlEnvParser {
public static void main(String[] args) throws IOException {
String yaml = """
service:
env:
- name: WAN_PORT
value: "80"
- name: LAN_PORT
value: "8080"
- name: SITE_URL
value: "http://google.com"
""";
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
JsonNode root = mapper.readTree(yaml);
JsonNode envArrayNode = root.at("/service/env"); // 安全导航,返回缺失时为 MissingNode
// ✅ 正确方式:treeToValue + raw List.class(Jackson 自动识别为 List<env>)
List<env> envList = mapper.treeToValue(envArrayNode, List.class);
System.out.println(envList);
// 输出:[{name=WAN_PORT, value=80}, {name=LAN_PORT, value=8080}, {name=SITE_URL, value=http://google.com}]
}
}</env></env>
⚠️ 关键注意事项:
-
Env类必须有无参构造函数(public 或 package-private),否则 Jackson 无法实例化; -
at("/path")比get("service").get("env")更健壮——若路径不存在,返回MissingNode而非NullPointerException; - 不要使用
jsonNode.toString()后再readValue(..., TypeReference),这会丢失原始节点类型信息,且易因引号转义引发解析异常; - 若需强类型安全(如 IDE 提示/编译期检查),可配合
@JsonCreator和@JsonProperty注解优化Env类,但非必需; -
treeToValue(..., List.class)在 Jackson 2.10+ 中已完全支持泛型推导,无需额外配置。
总结:面对 YAML/JSON 数组到 List<t></t> 的反序列化,应摒弃 TypeReference + readValue(String) 的绕路方案,直接采用 treeToValue(node, List.class) —— 简洁、高效、零配置,且语义清晰、错误率低。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











