Merge pull request #50773 from xfocus3

Closes gh-50773

* pr/50773:
  Polish 'Bind empty strings to empty maps'
  Bind empty strings to empty maps
This commit is contained in:
Phillip Webb
2026-06-20 19:56:18 -07:00
2 changed files with 25 additions and 0 deletions
@@ -39,6 +39,7 @@ import org.springframework.core.ResolvableType;
*
* @author Phillip Webb
* @author Madhura Bhave
* @author Ahmed El Amraouiyine
*/
class MapBinder extends AggregateBinder<Map<Object, Object>> {
@@ -64,6 +65,9 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
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);
}
}
@@ -65,6 +65,7 @@ import static org.mockito.Mockito.mock;
*
* @author Phillip Webb
* @author Madhura Bhave
* @author Ahmed El Amraouiyine
*/
class MapBinderTests {
@@ -274,6 +275,15 @@ class MapBinderTests {
assertThat(result.isBound()).isFalse();
}
@Test
void bindToMapWhenEmptyStringShouldReturnEmptyMap() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo", "");
this.sources.add(source);
Map<String, String> result = this.binder.bind("foo", STRING_STRING_MAP).get();
assertThat(result).isEmpty();
}
@Test
void bindToMapShouldConvertKey() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
@@ -510,6 +520,17 @@ class MapBinderTests {
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<NestableFoo> 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();