Spring Boot
YAML
Map Key
Dot Escaping
Configuration

Escaping a dot in a Map key in Yaml in Spring Boot

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Spring Boot configuration binding, dots in property names usually represent nested paths. That can become a problem when the dot is part of an actual map key, such as a domain name or file extension rule. The fix is to use bracket notation with quoted keys so the binder treats the full key as literal text.

Why Dots Break Map Binding

Spring Boot property binding interprets a key like settings.api.timeout as nested objects. If your intended map key is api.timeout, you need to stop path splitting and preserve that exact string.

Consider this YAML:

yaml
app:
  settings:
    api.timeout: "30s"

Depending on your target type, this may not bind as expected to a flat map key. Bracket notation is safer for literal keys.

Correct YAML Pattern for Dot Keys

Use quoted bracket keys under the map field.

yaml
1app:
2  settings:
3    "[api.timeout]": "30s"
4    "[feature.flag.alpha]": "enabled"
5    "[domain.example.com]": "allow"

Then bind to a map in your configuration class.

java
1import java.util.LinkedHashMap;
2import java.util.Map;
3import org.springframework.boot.context.properties.ConfigurationProperties;
4
5@ConfigurationProperties(prefix = "app")
6public class AppProperties {
7    private Map<String, String> settings = new LinkedHashMap<>();
8
9    public Map<String, String> getSettings() {
10        return settings;
11    }
12
13    public void setSettings(Map<String, String> settings) {
14        this.settings = settings;
15    }
16}

With this pattern, keys remain exactly as written.

Verify Binding in a Test

A focused test prevents surprises during upgrades.

java
1import static org.assertj.core.api.Assertions.assertThat;
2import org.junit.jupiter.api.Test;
3import org.springframework.beans.factory.annotation.Autowired;
4import org.springframework.boot.test.context.SpringBootTest;
5
6@SpringBootTest
7class AppPropertiesTest {
8
9    @Autowired
10    private AppProperties properties;
11
12    @Test
13    void bindsLiteralDotKeys() {
14        assertThat(properties.getSettings().get("api.timeout")).isEqualTo("30s");
15        assertThat(properties.getSettings().get("feature.flag.alpha")).isEqualTo("enabled");
16        assertThat(properties.getSettings().get("domain.example.com")).isEqualTo("allow");
17    }
18}

This is especially useful when configuration is loaded from several profile files.

Alternative Using properties Files

If your team prefers application.properties, map key preservation is often simpler to read:

properties
app.settings[api.timeout]=30s
app.settings[feature.flag.alpha]=enabled
app.settings[domain.example.com]=allow

The same binding class works with this format.

Work with Nested Maps and Typed Values

Literal dot keys are common when loading per host settings or extension based rules. If you need more structure than a string-to-string map, bind to nested map values and keep bracket notation for the outer key.

yaml
1app:
2  host-rules:
3    "[api.example.com]":
4      timeout: 30
5      retries: 2
6    "[cdn.example.com]":
7      timeout: 10
8      retries: 1
java
1import java.util.LinkedHashMap;
2import java.util.Map;
3import org.springframework.boot.context.properties.ConfigurationProperties;
4
5@ConfigurationProperties(prefix = "app")
6public class HostRuleProperties {
7    private Map<String, Rule> hostRules = new LinkedHashMap<>();
8
9    public Map<String, Rule> getHostRules() {
10        return hostRules;
11    }
12
13    public void setHostRules(Map<String, Rule> hostRules) {
14        this.hostRules = hostRules;
15    }
16
17    public static class Rule {
18        private int timeout;
19        private int retries;
20
21        public int getTimeout() { return timeout; }
22        public void setTimeout(int timeout) { this.timeout = timeout; }
23        public int getRetries() { return retries; }
24        public void setRetries(int retries) { this.retries = retries; }
25    }
26}

This pattern gives type safety while preserving exact map key text.

Environment Overrides and Key Names

Environment variable overrides flatten key names and can become hard to read for dotted map keys. In teams that depend on environment overrides, prefer loading values from profile specific files or config maps instead of trying to encode complex key syntax in environment variable names.

Common Pitfalls

A common mistake is using plain dotted keys in YAML and expecting literal key storage. Spring may parse them as nested fields.

Another issue is forgetting to quote bracket notation in YAML. Unquoted syntax can be parsed differently by YAML processors.

A third issue is mixing styles across profile files, which produces inconsistent maps across environments. Pick one style and use it everywhere.

Summary

  • Dots in configuration keys are treated as path separators by default.
  • Use quoted bracket notation for literal map keys with dots.
  • Bind to a string keyed map in a @ConfigurationProperties class.
  • Add tests that assert key exactness across profiles.
  • Keep one consistent format across YAML and properties files.

Course illustration
Course illustration

All Rights Reserved.