YAML to Map with Spring Boot

Read the Application Properties or a YAML file as a Java Map in Spring Boot.

Overview

In a Spring or Spring Boot application, an application properties file or an application YAML file help us externalize important configurations. On top of that, the @ConfigurationProperties annotation in Spring Boot allows us to easily read and bind those configurations into Java objects.

This tutorial focuses on reading application configurations from a property or a YAML file into Java HashMap objects.

To learn more about reading application properties or YAML files into Java beans, please read Using @ConfigurationProperties in Spring Boot.

YAML or a Properties File

For this tutorial, we will work on a YAML-based configuration. However, note that all the examples in this tutorial are also applicable when using any equivalent application properties file.

Look at a typical YAML application file from a Spring Boot application.

application.yaml

spring:
  application:
    name: data-service
  servlet:
    multipart:
      enabled: true
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3309/test
    password: password
    username: test_user
Code language: YAML (yaml)

Alternatively, We can rewrite the same configurations in a properties file.

application.properties

spring.application.name=data-service
spring.servlet.multipart.enabled=true
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3309/test
spring.datasource.password=password
spring.datasource.username=test_userCode language: Properties (properties)

Both files contain the same configurations, and Spring Boot seamlessly works with YAML and Properties files. However, the YAML syntax is more organized and readable when we compare a properties file to an equivalent YAML file.

YAML file To Java Map

A YAML and Properties files contain sets of key and value pairs. That makes it more similar to a Map data structure. Thus, mapping a YAML or properties file into a Java HashMap is straightforward.

The following snippet demonstrates how we can use plain Java Map instances to model the Properties or YAML-based configurations we saw in the previous section.

Map<String, String> application = Map.of("name", "data-service");
        
Map<String, String> servlet = Map.of(
  "multipart.enabled", "true"
);

Map<String, String> datasource = Map.of(
  "driverClassName", "com.mysql.cj.jdbc.Driver",
  "url", "mysql://localhost:3309/test",
  "password", "password",
  "username", "test_user"
);Code language: Java (java)

Interestingly, in our configuration, the sub-group of “servlet” has a nested Map. We can model the nested map using a dot notation, as seen here.

Alternatively, we change the type of the servlet map and make it a nested Map (Map of Maps).

Map<String, Map<String, String>> servlet = Map.of(
  "multipart", Map.of("enabled", "true")
);Code language: Java (java)

We understood how a Map, YAML or a Properties file have similar data structures. Next, we will learn how Spring Boot @ConfigurationProperties annotation help map the application configurations from a YAML or Properties file into Java Map instances.

Reading YAML or Properties as Java Map

To read application YAML or Properties configurations as a Java Map, we need to define a Map member in an @ConfigurationProperties class.

Under the root, ‘spring‘, the YAML (or Properties) file contains three nested subgroups of configurations. Let’s use the prefix ‘spring‘ to read them in separate Map instances.

@Configuration
@ConfigurationProperties(prefix = "spring")
public class MapProperties {
  Map<String, String> application;
  Map<String, String> servlet;
  Map<String, String> datasource;
    
  // Constructor, Getter and Setter methods
}Code language: Java (java)

The class has all three maps, and their names correspond to the name of the respective properties subgroups. We have also added a well-formatted toString() method that we will use to print the bean when the application starts.

* Java Map based Properties
application:
  name=data-service
servlet:
  multipart.enabled=true
datasource:
  driverClassName=com.mysql.cj.jdbc.Driver
  url=jdbc:mysql://localhost:3309/test
  password=password
  username=test_userCode language: plaintext (plaintext)

From the output, we can see all the fields in the map are populated as expected.

Reading YAML Properties as Nested Java Map

To read nested Java Maps from a YAML file or a Properties File, we can change the type of the “servlet” field to Map<String, Map<String, String>>.

@Configuration
@ConfigurationProperties(prefix = "spring")
public class NestedMapProperties {
  Map<String, String> application;
  Map<String, Map<String, String>> servlet;
  Map<String, String> datasource;

  // Constructor, Getter, and Setter methods
}Code language: Java (java)

When we print the populated bean, we see that the nested Maps are correctly read from our YAML file.

* Java Map based nested Properties
application:
  name=data-service
servlet:
  multipart={enabled=true}
datasource:
  driverClassName=com.mysql.cj.jdbc.Driver
  url=jdbc:mysql://localhost:3309/test
  password=password
  username=test_userCode language: plaintext (plaintext)

Reading YAML Properties as MultiValue Map

Sometimes, we may have a list of values in a YAML or a Properties Files that we want to bind in a Java Bean. Spring Boot @ConfigurationProperties allows binding a list from a YAML as a Java multi-value Map instance.

A list in a YAML file looks like this,

spring:
  application:
    name: data-service
  servlet:
    multipart:
      enabled: true
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3309/test
    password: password
    username: test_user
  profiles:
    active:
      - dev
      - qa
      - staging
      - prodCode language: YAML (yaml)

Or, use an in-line list with comma-separated values

spring:
  ## Skipped
  profiles:
    active: dev, qa, staging, prodCode language: YAML (yaml)

To read the ‘spring.profiles.active‘, we changed our Map to a multi-value Map.

@Configuration
@ConfigurationProperties(prefix = "spring")
public class NestedMapProperties {
  Map<String, String> application;
  Map<String, Map<String, String>> servlet;
  Map<String, String> datasource;
  Map<String, List<String>> profiles;

  // Constructor, Getter, and Setter methods
}Code language: Java (java)

Using that, we can verify list of all the active profiles is loaded correctly.

* Java Map based nested Properties
application:
  name=data-service
servlet:
  multipart={enabled=true}
datasource:
  driverClassName=com.mysql.cj.jdbc.Driver
  url=jdbc:mysql://localhost:3309/test
  password=password
  username=test_user
profiles:
  active=[dev, qa, staging, prod]Code language: plaintext (plaintext)

Summary

This tutorial focused on Reading different keys and value pairs from a YAML or a Properties file into a Java HashMap. We understood that a YAML or a Properties file are similar to the Map data structure. Thus, we can easily bind the configurations in Java Maps.

We covered examples of reading a simple Map, Nested Map, and MultiValueMap from a YAML or equivalent application properties file.

Refer to our GitHub Repository for the complete source code.

More like this: