Skip to content

Commit 69de06a

Browse files
committed
Remove origin support for empty YAML maps
Adding origin support caused an unexpected and unwanted change in behavior where configuration property binding would fail. The failure would occur because there was no way to convert from the entry in the environment that represents the empty map to the target type. The commit changes the YAML loader to drop empty maps, effectively reverting the map portion of 3bcbb0e and gh-21704. This aligns the behavior with the decision we made in gh-19095. Origin support for an empty list has been retained as it does not have a negative effect on configuration property binding. Prior to these changes, an empty YAML list was mapped to an origin tracked value that contains an empty list. Fully reverting 3bcbb0e would have resulted in an empty YAML list being mapped to an empty string. To avoid adding a collection type to the environment, we now map an empty YAML list to an origin tracked value that contains an empty string. Closes gh-35403
1 parent bcb2049 commit 69de06a

File tree

2 files changed

+13
-12
lines changed

2 files changed

+13
-12
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedYamlLoader.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929
import org.yaml.snakeyaml.constructor.Constructor;
3030
import org.yaml.snakeyaml.constructor.SafeConstructor;
3131
import org.yaml.snakeyaml.error.Mark;
32-
import org.yaml.snakeyaml.nodes.CollectionNode;
3332
import org.yaml.snakeyaml.nodes.MappingNode;
3433
import org.yaml.snakeyaml.nodes.Node;
3534
import org.yaml.snakeyaml.nodes.NodeTuple;
3635
import org.yaml.snakeyaml.nodes.ScalarNode;
36+
import org.yaml.snakeyaml.nodes.SequenceNode;
3737
import org.yaml.snakeyaml.nodes.Tag;
3838
import org.yaml.snakeyaml.representer.Representer;
3939
import org.yaml.snakeyaml.resolver.Resolver;
@@ -105,8 +105,8 @@ public Object getData() throws NoSuchElementException {
105105

106106
@Override
107107
protected Object constructObject(Node node) {
108-
if (node instanceof CollectionNode && ((CollectionNode<?>) node).getValue().isEmpty()) {
109-
return constructTrackedObject(node, super.constructObject(node));
108+
if (node instanceof SequenceNode sequenceNode && sequenceNode.getValue().isEmpty()) {
109+
return constructTrackedObject(node, "");
110110
}
111111
if (node instanceof ScalarNode) {
112112
if (!(node instanceof KeyScalarNode)) {

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/env/OriginTrackedYamlLoaderTests.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
1717
package org.springframework.boot.env;
1818

1919
import java.nio.charset.StandardCharsets;
20-
import java.util.Collections;
2120
import java.util.List;
2221
import java.util.Map;
2322

@@ -115,18 +114,19 @@ void processListOfMaps() {
115114
void processEmptyAndNullValues() {
116115
OriginTrackedValue empty = getValue("empty");
117116
OriginTrackedValue nullValue = getValue("null-value");
117+
OriginTrackedValue emptyList = getValue("emptylist");
118118
assertThat(empty.getValue()).isEqualTo("");
119119
assertThat(getLocation(empty)).isEqualTo("27:8");
120120
assertThat(nullValue.getValue()).isEqualTo("");
121121
assertThat(getLocation(nullValue)).isEqualTo("28:13");
122+
assertThat(emptyList.getValue()).isEqualTo("");
123+
assertThat(getLocation(emptyList)).isEqualTo("29:12");
122124
}
123125

124126
@Test
125-
void processEmptyListAndMap() {
126-
OriginTrackedValue emptymap = getValue("emptymap");
127-
OriginTrackedValue emptylist = getValue("emptylist");
128-
assertThat(emptymap.getValue()).isEqualTo(Collections.emptyMap());
129-
assertThat(emptylist.getValue()).isEqualTo(Collections.emptyList());
127+
void emptyMapsAreDropped() {
128+
Object emptyMap = getValue("emptymap");
129+
assertThat(emptyMap).isNull();
130130
}
131131

132132
@Test
@@ -194,11 +194,12 @@ void canLoadFilesBiggerThan3Mb() {
194194
assertThat(loaded).isNotEmpty();
195195
}
196196

197-
private OriginTrackedValue getValue(String name) {
197+
@SuppressWarnings("unchecked")
198+
private <T> T getValue(String name) {
198199
if (this.result == null) {
199200
this.result = this.loader.load();
200201
}
201-
return (OriginTrackedValue) this.result.get(0).get(name);
202+
return (T) this.result.get(0).get(name);
202203
}
203204

204205
private String getLocation(OriginTrackedValue value) {

0 commit comments

Comments
 (0)