在Java项目开发中,YAML格式因结构清晰、可读性强的特点,常被用来作为配置文件或者数据交换格式。当YAML结构包含多层嵌套、数组、自定义类型等复杂内容时,使用SnakeYAML可以便捷地将这些内容映射到对应的Java对象中,减少手动解析的工作量。

SnakeYAML基础使用流程
首先需要在项目中引入SnakeYAML的依赖,如果是Maven项目,在pom.xml中添加如下依赖:
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
SnakeYAML的核心类是Yaml,通过它可以将YAML内容加载为Java对象,基本的使用步骤如下:
- 创建
Yaml实例 - 调用
load或者loadAs方法,传入YAML内容和目标Java类类型 - 获取映射后的Java对象进行后续操作
简单YAML到Java对象的映射
先来看一个简单的YAML示例,包含一个用户的基本信息:
user: name: 张三 age: 25 email: test@ipipp.com
对应的Java实体类需要定义和YAML字段匹配的属性和对应的getter、setter方法:
public class User {
private String name;
private int age;
private String email;
// getter和setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
解析这个YAML的代码如下:
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
public class YamlDemo {
public static void main(String[] args) {
Yaml yaml = new Yaml();
// 加载类路径下的yaml文件
InputStream inputStream = YamlDemo.class.getClassLoader().getResourceAsStream("simple.yaml");
// 将YAML映射到User对象
User user = yaml.loadAs(inputStream, User.class);
System.out.println("用户名:" + user.getName());
System.out.println("年龄:" + user.getAge());
System.out.println("邮箱:" + user.getEmail());
}
}
复杂嵌套结构的映射
实际的YAML结构往往会包含多层嵌套,比如一个公司信息包含多个部门,每个部门又包含多个员工:
company:
name: 科技有限公司
address: 北京市海淀区
departments:
- name: 研发部
employees:
- name: 李四
age: 28
position: 后端开发
- name: 王五
age: 26
position: 前端开发
- name: 产品部
employees:
- name: 赵六
age: 30
position: 产品经理
这种结构需要定义对应的嵌套实体类,首先是员工类:
public class Employee {
private String name;
private int age;
private String position;
// getter和setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
然后是部门类,包含员工集合:
import java.util.List;
public class Department {
private String name;
private List<Employee> employees;
// getter和setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
最后是公司类,包含部门集合:
import java.util.List;
public class Company {
private String name;
private String address;
private List<Department> departments;
// getter和setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Department> getDepartments() {
return departments;
}
public void setDepartments(List<Department> departments) {
this.departments = departments;
}
}
解析这个复杂YAML的代码如下:
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
public class ComplexYamlDemo {
public static void main(String[] args) {
Yaml yaml = new Yaml();
InputStream inputStream = ComplexYamlDemo.class.getClassLoader().getResourceAsStream("complex.yaml");
Company company = yaml.loadAs(inputStream, Company.class);
System.out.println("公司名称:" + company.getName());
System.out.println("公司地址:" + company.getAddress());
for (Department dept : company.getDepartments()) {
System.out.println("部门名称:" + dept.getName());
for (Employee emp : dept.getEmployees()) {
System.out.println(" 员工姓名:" + emp.getName() + ",职位:" + emp.getPosition());
}
}
}
}
自定义类型构造器的使用
如果YAML中使用了自定义标签,或者需要特殊处理某些类型的映射,可以通过自定义Constructor来实现。比如YAML中用一个特定格式的字符串表示日期,需要自动转换为Date类型:
event: name: 产品发布会 date: 2024-05-20
自定义构造器代码如下:
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Node;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CustomConstructor extends Constructor {
public CustomConstructor() {
super(Event.class);
}
@Override
protected Date constructDate(Node node) {
String dateStr = (String) node.getValue();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.parse(dateStr);
} catch (ParseException e) {
throw new RuntimeException("日期格式解析失败", e);
}
}
}
对应的Event类:
import java.util.Date;
public class Event {
private String name;
private Date date;
// getter和setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
使用自定义构造器解析YAML:
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
public class CustomConstructorDemo {
public static void main(String[] args) {
Yaml yaml = new Yaml(new CustomConstructor());
InputStream inputStream = CustomConstructorDemo.class.getClassLoader().getResourceAsStream("event.yaml");
Event event = yaml.loadAs(inputStream, Event.class);
System.out.println("事件名称:" + event.getName());
System.out.println("事件日期:" + event.getDate());
}
}
注意事项
- Java实体类的属性名需要和YAML中的字段名完全一致,或者通过
@YamlProperty注解指定映射关系,不过SnakeYAML默认支持驼峰和下划线的自动转换 - 集合类型在YAML中需要用短横线加空格的形式表示数组元素,对应Java中的
List或者Set类型 - 如果YAML中存在根节点,需要定义对应的外层实体类来包裹内部内容,避免映射失败
- 解析YAML时要处理可能的异常,比如文件不存在、格式错误等情况,保证程序的健壮性