写点什么

将 YAML 文件解析为 JAVA 对象的方法

作者:AlexLei
  • 2024-10-09
    广东
  • 本文字数:1686 字

    阅读完需:约 6 分钟

Yaml 是目前常用的一种软件参数存储格式,用于应对软件运行时调整参数的需求。本文介绍将 yaml 文件解析成对象的几种方法。

YAML 小知识

YAML 的全称是“YAML Ain't Markup Language”,是一个对人类阅读友好的数据序列化格式,几乎所有编程语言都有支持。


YAML 的在册媒体类型是“application/yaml”(RFC9512),常用的文件扩展名是yamlyml


本文的所有例子在java8org.yaml:snakeyaml:1.30spring-boot 2.7.18环境下测试通过。

方式 1:Snak Yaml

Snake yaml 是在 Java 中解析 YAML 文件必用的库。本文介绍的其他方法也都依赖 Snak yaml。


Snake yaml 本身就支持将 yaml 转换成 java bean 规范的对象。


来看这个例子:


  1. Yaml 文件


user:  name: "root"  age: 18app:  name: "springboot"  version: "1.0.0"
复制代码


  1. 数据类


public class App {  public String name;  public String version;}public class User {  String name;  int age;  int birthYear;  //省略 get set}public class ConfigFile {  User user;  App app;  //省略get set; }
复制代码


于是,可以使用Yaml.loadAs方法来将数据转换成对象:


public class LoadYaml {
public static final Path application_yml = Paths.get("src/main/resources/application.yml"); Yaml yaml = new Yaml();
@Test void yaml_to_dto() throws Exception { ConfigFile config = yaml.loadAs(Files.newInputStream(application_yml), ConfigFile.class); assertThat(config).isNotNull(); assertThat(config.user).isNotNull(); assertThat(config.user.getName()).isEqualTo("root"); assertThat(config.app).isNotNull(); }}
复制代码

方式 2:Jackson

第二种方法是使用 jackson。jackson 加载 yaml 扩展后,就能支持从 yaml 到对象的转换。并且这样的好处是可以使用 jackson 的注解来调整映射行为,比直接使用Yaml.loadAs功能要多。


@Testvoid parseYaml() throws Exception {  ConfigFile config = new ObjectMapper(new YAMLFactory())      .readerFor(ConfigFile.class)      .readValue(application_yml.toFile());
assertThat(config).isNotNull(); assertThat(config.user).isNotNull(); assertThat(config.user.getName()).isEqualTo("root"); assertThat(config.app).isNotNull(); assertThat(config.app.name).isNotNull();}
复制代码


提醒一下,有个缺陷,尚不支持含有 anchor 的 yaml 转换成对象。相应的问题跟踪:https://github.com/FasterXML/jackson-dataformats-text/issues/98

方式 3:Spring Boot

第三种方式是使用 spring boot 中提供的 bind 工具,好处是在类型的转换上更灵活,映射处理上更完善。


@Testvoid parseYaml() throws Exception {  YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();  factoryBean.setResources(new FileSystemResource(application_yml));  Properties properties = factoryBean.getObject();
ConfigurationPropertySource propertySource = new MapConfigurationPropertySource(properties); Binder binder = new Binder(propertySource);
User u = binder.bind("user", User.class).get();
assertThat(u.getName()).isEqualTo("root");}
复制代码


注意 spring boot 默认不支持 public field bind。但支持 relax name bind,例如在 yaml 中写 birth-year: 2023可以自动映射到 user.setBirthYear方法上。


注意 2,spring boot 的处理逻辑与第 1、2 种是有明显差异的,前述 2 种方法大体上都是 tree→object 直接转换,但 spring boot 是 tree→properties→object,中间多了一步将 tree 展开成单层 hash map 的过程。

小结

  1. Snake Yaml:支持 Java Bean,支持 public fields

  2. Jackson:支持 Java Bean,支持 public fields,支持用注解调整对象构造

  3. Spring Boot:支持 Java Bean,支持 relax name bind,支持类型转换


除了 yaml 以外,inipropertiestoml都可以用来存储参数。除了文件存储以外,还可以使用配置中心(如 nacos),关系数据库也可以,根据需要而选择。

参考资料

https://yaml.org/https://www.baeldung.com/jackson-yaml

发布于: 刚刚阅读数: 3
用户头像

AlexLei

关注

I'm a program writer. 2023-09-22 加入

系统架构设计师,从业10+年。 专精工程实践、DevOps、程序设计。

评论

发布
暂无评论
将YAML文件解析为JAVA对象的方法_spring_AlexLei_InfoQ写作社区