diff --git a/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java b/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java index f1e57fa32eee..db40be47d8c0 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java @@ -39,6 +39,7 @@ * * @author Phillip Webb * @author Madhura Bhave + * @author Ahmed El Amraouiyine */ class MapBinder extends AggregateBinder> { @@ -64,6 +65,9 @@ protected boolean isAllowRecursiveBinding(@Nullable ConfigurationPropertySource if (property != null) { getContext().setConfigurationProperty(property); Object result = getContext().getPlaceholdersResolver().resolvePlaceholders(property.getValue()); + if (result instanceof CharSequence charSequence && charSequence.isEmpty()) { + return createMap(target); + } return getContext().getConverter().convert(result, target); } } diff --git a/core/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java b/core/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java index 7b591d785a14..3e6165472279 100644 --- a/core/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java +++ b/core/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java @@ -65,6 +65,7 @@ * * @author Phillip Webb * @author Madhura Bhave + * @author Ahmed El Amraouiyine */ class MapBinderTests { @@ -274,6 +275,15 @@ void bindToMapWhenNoValueShouldReturnUnbound() { assertThat(result.isBound()).isFalse(); } + @Test + void bindToMapWhenEmptyStringShouldReturnEmptyMap() { + MockConfigurationPropertySource source = new MockConfigurationPropertySource(); + source.put("foo", ""); + this.sources.add(source); + Map result = this.binder.bind("foo", STRING_STRING_MAP).get(); + assertThat(result).isEmpty(); + } + @Test void bindToMapShouldConvertKey() { MockConfigurationPropertySource source = new MockConfigurationPropertySource(); @@ -510,6 +520,17 @@ void nestedMapsShouldNotBindToNull() { assertThat(foo2.getValue()).isEqualTo("three"); } + @Test + void nestedMapsWhenEmptyStringShouldReturnEmptyMap() { + MockConfigurationPropertySource source = new MockConfigurationPropertySource(); + source.put("foo.value", "one"); + source.put("foo.foos", ""); + this.sources.add(source); + BindResult foo = this.binder.bind("foo", NestableFoo.class); + assertThat(foo.get().getValue()).isEqualTo("one"); + assertThat(foo.get().getFoos()).isEmpty(); + } + @Test void bindToMapWithCustomConverter() { DefaultConversionService conversionService = new DefaultConversionService();