YAML to List of Objects in Spring Boot – 从YAML到Spring Boot中的对象列表

最后修改: 2020年 7月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this short tutorial, we’re going to have a closer look at how to map a YAML list into a List in Spring Boot.

在这个简短的教程中,我们将仔细研究如何在Spring Boot中把YAML列表映射成List

We’ll start with some background on how to define lists in YAML.

我们先介绍一下如何在YAML中定义列表的背景。

Then we’ll dig deeper to see how to bind YAML lists to Lists of objects.

然后我们将深入研究如何将YAML列表与对象的Lists绑定。

2. Quick Recap About Lists in YAML

2.关于YAML中的列表的快速回顾

In short, YAML is a human-readable data serialization standard that provides a concise and clear way to write configuration files. The good thing about YAML is the fact that it supports multiple data types such as Lists, Maps and scalar types.

简而言之,YAML是一种人类可读的数据序列化标准,它提供了一种简洁明了的方式来编写配置文件。YAML的好处是它支持多种数据类型,如Lists、Maps和标量类型。

The elements in a YAML list are defined using the “-” character, and they all share the same indentation level:

YAML 列表中的元素是用”-“字符定义的,它们都有相同的缩进程度。

yamlconfig:
  list:
    - item1
    - item2
    - item3
    - item4

As a comparison, the properties-based equivalent uses indices:

作为比较,基于属性的等价物使用指数。

yamlconfig.list[0]=item1
yamlconfig.list[1]=item2
yamlconfig.list[2]=item3
yamlconfig.list[3]=item4

For more examples, feel free to take a look at our article on how to define lists and maps using YAML and properties files.

关于更多的例子,请看我们的文章:如何使用YAML和属性文件定义清单和地图

As a matter of fact, the hierarchical nature of YAML significantly enhances readability compared to properties files. Another interesting feature of YAML is the possibility to define different properties for different Spring profiles. Starting with Boot version 2.4.0, this is also possible for properties files.

事实上,与属性文件相比,YAML 的分层性质大大增强了可读性。YAML 的另一个有趣的功能是可以为不同的 Spring 配置文件定义不同的属性。从 Boot 2.4.0 版本开始,属性文件也可以这样做了。

It’s worth mentioning that Spring Boot provides out-of-the-box support for YAML configuration. By design, Spring Boot loads configuration properties from application.yml at startup without any extra work.

值得一提的是,Spring Boot对YAML配置提供了开箱即用的支持。根据设计,Spring Boot在启动时从application.yml加载配置属性,无需任何额外工作。

3. Binding a YAML List to a Simple List of Objects

3.将YAML列表绑定到一个简单的List 对象上

Spring Boot provides the @ConfigurationProperties annotation to simplify the logic of mapping external configuration data into an object model.

Spring Boot提供了@ConfigurationProperties注解来简化将外部配置数据映射到对象模型的逻辑。

In this section, we’ll be using @ConfigurationProperties to bind a YAML list into a List<Object>.

在本节中,我们将使用@ConfigurationProperties将YAML列表绑定到List<Object>

We start by defining a simple list in application.yml:

我们首先在application.yml中定义了一个简单的列表。

application:
  profiles:
    - dev
    - test
    - prod
    - 1
    - 2

Then we’ll create a simple ApplicationProps POJO to hold the logic of binding our YAML list to a List of objects:

然后我们将创建一个简单的ApplicationProps POJO来保持将我们的YAML列表绑定到List对象的逻辑。

@Component
@ConfigurationProperties(prefix = "application")
public class ApplicationProps {

    private List<Object> profiles;
    
    // getter and setter

}

The ApplicationProps class needs to be decorated with @ConfigurationProperties to express the intention of mapping all the YAML properties with the specified prefix to an object of ApplicationProps.

ApplicationProps 类需要用@ConfigurationProperties 来表达将所有具有指定前缀的YAML属性映射到ApplicationProps对象的意图。

To bind the profiles list, we just need to define a field of type List, and the @ConfigurationProperties annotation will take care of the rest.

为了绑定profiles列表,我们只需要定义一个List类型的字段,而@ConfigurationProperties注解将处理其余的事情。

Notice that we register the ApplicationProps class as a normal Spring bean using @Component. As a result, we can inject it into other classes in the same way as any other Spring bean.

请注意,我们使用@ComponentApplicationProps类注册为普通Spring Bean。因此,我们可以像其他Spring Bean一样,将其注入其他类中。

Finally, we inject the ApplicationProps bean into a test class and verify if our profiles YAML list is correctly injected as a List<Object>:

最后,我们将ApplicationPropsbean注入到一个测试类中,并验证我们的profilesYAML列表是否被正确注入为List<Object>

@ExtendWith(SpringExtension.class)
@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class)
@EnableConfigurationProperties(value = ApplicationProps.class)
class YamlSimpleListUnitTest {
 
    @Autowired
    private ApplicationProps applicationProps;
 
    @Test
    public void whenYamlList_thenLoadSimpleList() {
        assertThat(applicationProps.getProfiles().get(0)).isEqualTo("dev");
        assertThat(applicationProps.getProfiles().get(4).getClass()).isEqualTo(Integer.class);
        assertThat(applicationProps.getProfiles().size()).isEqualTo(5);
    }
}

4. Binding YAML Lists to Complex Lists

4.将YAML列表绑定到复杂列表上

Now let’s dive deeper and see how to inject nested YAML lists into complex structured Lists.

现在让我们深入研究,看看如何将嵌套的YAML列表注入到复杂的结构化Lists。

First, let’s add some nested lists to application.yml:

首先,让我们在application.yml中添加一些嵌套列表。

application:
  // ...
  props: 
    -
      name: YamlList
      url: http://yamllist.dev
      description: Mapping list in Yaml to list of objects in Spring Boot
    -
      ip: 10.10.10.10
      port: 8091
    -
      email: support@yamllist.dev
      contact: http://yamllist.dev/contact
  users:
    -
      username: admin
      password: admin@10@
      roles:
        - READ
        - WRITE
        - VIEW
        - DELETE
    -
      username: guest
      password: guest@01
      roles:
        - VIEW

In this example, we’re going to bind the props property to a List<Map<String, Object>>. Similarly, we’ll map users into a List of User objects.

在这个例子中,我们将把props 属性绑定到一个List<Map<String, Object>>。同样地,我们将把users 映射到User对象的List中。

Since each element of the props entry holds different keys, we can inject it as a List of Maps. Be sure to check out our article on how to inject a map from a YAML file in Spring Boot.

由于props 入口的每个元素都持有不同的键,我们可以将其作为List of Maps来注入。请务必查看我们的文章,了解如何在Spring Boot中从YAML文件注入一个地图.

However, in the case of users, all items share the same keys, so to simplify its mapping, we may need to create a dedicated User class to encapsulate the keys as fields:

然而用户的情况下,所有项目都共享相同的键,所以为了简化其映射,我们可能需要创建一个专门的用户类来将键封装为字段

public class ApplicationProps {
    
    // ...
	
    private List<Map<String, Object>> props;
    private List<User> users;
    
    // getters and setters

    public static class User {

        private String username;
        private String password;
        private List<String> roles;

        // getters and setters

    }
}

Now we verify that our nested YAML lists are properly mapped:

现在我们验证一下我们的嵌套YAML列表是否被正确映射。

@ExtendWith(SpringExtension.class)
@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class)
@EnableConfigurationProperties(value = ApplicationProps.class)
class YamlComplexListsUnitTest {
 
    @Autowired
    private ApplicationProps applicationProps;
 
    @Test
    public void whenYamlNestedLists_thenLoadComplexLists() {
        assertThat(applicationProps.getUsers().get(0).getPassword()).isEqualTo("admin@10@");
        assertThat(applicationProps.getProps().get(0).get("name")).isEqualTo("YamlList");
        assertThat(applicationProps.getProps().get(1).get("port").getClass()).isEqualTo(Integer.class);
    }
	
}

5. Conclusion

5.总结

In this article, we learned how to map YAML lists into Java Lists.

在这篇文章中,我们学习了如何将YAML列表映射成Java Lists。

We also checked how to bind complex lists to custom POJOs.

我们还检查了如何将复杂的列表与自定义POJO绑定。

As always, the complete source code for this article is available over on GitHub.

与往常一样,本文的完整源代码可在GitHub上获得over