YAML是一种轻量级数据交换格式,易于阅读和编写,被广泛用于配置文件、数据序列化、日志记录等领域。SnakeYAML是一个用Java编写的YAML解析器和生成器,在Java开发中常常用来读取和写入YAML数据。
一、什么是SnakeYAML
SnakeYAML是一个用Java编写的YAML解析器和生成器,具有流式API、对象图API两种使用方式。它支持严格的YAML 1.1规范和宽松的YAML 1.2规范,可以轻松地读取和写入YAML数据。
使用SnakeYAML可以快速地将Java对象序列化为YAML格式的数据,并将YAML格式的数据反序列化为Java对象,非常适用于配置文件、数据存储和数据交换等场景。
二、SnakeYAML的基本使用
下面我们通过一个简单的示例来介绍SnakeYAML的基本使用。
1、添加Maven依赖
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.27</version>
</dependency>
2、将Java对象序列化为YAML格式的数据
import org.yaml.snakeyaml.Yaml;
public class User {
private String name;
private int age;
// 省略构造方法和getter/setter方法
public static void main(String[] args) {
User user = new User("张三", 20);
Yaml yaml = new Yaml();
String output = yaml.dump(user);
System.out.println(output);
}
}
上面的代码定义了一个User类,用于存储用户的姓名和年龄。通过Yaml类的dump方法可以将一个Java对象序列化为YAML格式的数据。
运行上面的代码,输出如下:
!!com.example.User
age: 20
name: 张三
可以看到,SnakeYAML将Java对象序列化为了YAML格式的数据,每个属性对应一个YAML键值对。
3、将YAML格式的数据反序列化为Java对象
import org.yaml.snakeyaml.Yaml;
public class User {
private String name;
private int age;
// 省略构造方法和getter/setter方法
public static void main(String[] args) {
String input = "!!com.example.User\nage: 20\nname: 张三";
Yaml yaml = new Yaml();
User user = yaml.loadAs(input, User.class);
System.out.println("姓名:" + user.getName());
System.out.println("年龄:" + user.getAge());
}
}
上面的代码将上一步中生成的YAML格式的数据反序列化为了User对象。
运行上面的代码,输出如下:
姓名:张三
年龄:20
可以看到,SnakeYAML将YAML格式的数据反序列化为了一个Java对象。
三、SnakeYAML的高级使用
除了基本的序列化和反序列化功能,SnakeYAML还提供了一些高级功能。
1、Java对象图的序列化和反序列化
上面的示例中介绍了如何将单个Java对象序列化为YAML格式的数据,也介绍了如何将YAML格式的数据反序列化为单个Java对象。但是,在实际应用中,我们有时需要将整个Java对象图序列化为YAML格式的数据,或者将YAML格式的数据反序列化为整个Java对象图。
SnakeYAML提供了以下两种方式来处理Java对象图的序列化和反序列化:
- 流式API:使用Dumper和Loader对数据流进行处理
- 对象图API:通过创建JavaBean对象模型的方式处理整个Java对象图
下面我们分别介绍一下这两种方式的使用。
使用流式API
- 将Java对象图序列化为YAML格式的数据
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class User {
private String name;
private int age;
private List<String> hobbies;
private Map<String, String> addresses;
// 省略构造方法和getter/setter方法
public static void main(String[] args) throws Exception {
User user1 = new User("张三", 20);
user1.setHobbies(new ArrayList<>());
user1.getHobbies().add("篮球");
user1.getHobbies().add("游泳");
user1.setAddresses(new HashMap<>());
user1.getAddresses().put("work", "中国北京");
user1.getAddresses().put("home", "中国上海");
User user2 = new User("李四", 30);
user2.setHobbies(new ArrayList<>());
user2.getHobbies().add("书法");
user2.getHobbies().add("绘画");
user2.setAddresses(new HashMap<>());
user2.getAddresses().put("work", "中国广州");
user2.getAddresses().put("home", "中国深圳");
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(true);
options.setExplicitStart(true);
Yaml yaml = new Yaml(options);
FileWriter writer = new FileWriter("users.yml");
yaml.dump(users, writer);
writer.close();
}
}
上面的代码定义了一个User类,用于存储用户的姓名、年龄、爱好和地址。通过流式API将两个User对象序列化为YAML格式的数据,并将数据写入文件中。
其中,DumperOptions类用于配置序列化的选项。Yaml类的dump方法可以序列化整个Java对象图,将Java对象图转换为YAML格式的数据。
- 将YAML格式的数据反序列化为Java对象图
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.FileInputStream;
import java.util.List;
public class User {
private String name;
private int age;
private List<String> hobbies;
private Map<String, String> addresses;
// 省略构造方法和getter/setter方法
public static void main(String[] args) throws Exception {
LoaderOptions options = new LoaderOptions();
options.setAllowDuplicateKeys(false);
Yaml yaml = new Yaml(options);
FileInputStream stream = new FileInputStream("users.yml");
List<User> users = yaml.loadAs(stream, List.class);
stream.close();
for (User user : users) {
System.out.println("姓名:" + user.getName());
System.out.println("年龄:" + user.getAge());
System.out.println("爱好:" + user.getHobbies());
System.out.println("地址:" + user.getAddresses());
}
}
}
上面的代码使用流式API将文件中的YAML格式的数据反序列化为Java对象图,并输出反序列化后的User对象。
其中,LoaderOptions类用于配置反序列化选项。Yaml类的loadAs方法可以反序列化整个Java对象图,将YAML格式的数据转换为Java对象图。
使用对象图API
在对象图API中,可以通过创建JavaBean对象模型的方式处理整个Java对象图。
- 将Java对象图序列化为YAML格式的数据
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.Yaml;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class User {
private String name;
private int age;
private List<String> hobbies;
private Map<String, String> addresses;
// 省略构造方法和getter/setter方法
public static void main(String[] args) {
User user1 = new User("张三", 20);
user1.setHobbies(new ArrayList<>());
user1.getHobbies().add("篮球");
user1.getHobbies().add("游泳");
user1.setAddresses(new HashMap<>());
user1.getAddresses().put("work", "中国北京");
user1.getAddresses().put("home", "中国上海");
User user2 = new User("李四", 30);
user2.setHobbies(new ArrayList<>());
user2.getHobbies().add("书法");
user2.getHobbies().add("绘画");
user2.setAddresses(new HashMap<>());
user2.getAddresses().put("work", "中国广州");
user2.getAddresses().put("home", "中国深圳");
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
Representer representer = new Representer();
representer.addClassTag(User.class, new Tag("!user"));
representer.addProperty("name", String.class);
representer.addProperty("age", int.class);
representer.addProperty("hobbies", List.class);
representer.addProperty("addresses", Map.class);
Yaml yaml = new Yaml(representer);
String output = yaml.dump(users);
System.out.println(output);
}
}
上面的代码使用对象图API将两个User对象序列化为YAML格式的数据。
其中,Representer类用于配置如何将Java对象图转换为YAML格式的数据,其addClassTag方法用于添加类别标签,addProperty方法用于添加类属性。
- 将YAML格式的数据反序列化为Java对象图
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.Yaml;
import java.util.List;
import java.util.Map;
public class User {
private String name;
private int age;
private List<String> hobbies;
private Map<String, String> addresses;
// 省略构造方法和getter/setter方法
public static void main(String[] args) {
String input = "--- !!seq\n"
+ "- !user\n"
+ " name: 张三\n"
+ " age: 20\n"
+ " hobbies:\n"
+ " - 篮球\n"
+ " - 游泳\n"
+ " addresses:\n"
+ " work: 中国北京\n"
+ " home: 中国上海\n"
+ "- !user\n"
+ " name: 李四\n"
+ " age: 30\n"
+ " hobbies:\n"
+ " - 书法\n"
+ " - 绘画\n"
+ " addresses:\n"
+ " work: 中国广州\n"
+ " home: 中国深圳";
Representer representer = new Representer();
representer.addClassTag(User.class, new Tag("!user"));
representer.addProperty("name", String.class);
representer.addProperty("age", int.class);
representer.addProperty("hobbies", List.class);
representer.addProperty("addresses", Map.class);
Yaml yaml = new Yaml(representer);
List<User> users = yaml.loadAs(input, List.class);
for (User user : users) {
System.out.println("姓名:" + user.getName());
System.out.println("年龄:" + user.getAge());
System.out.println("爱好:" + user.getHobbies());
System.out.println("地址:" + user.getAddresses());
}
}
}
上面的代码使用对象图