Commit 16b7dbf4 authored by Phillip Webb's avatar Phillip Webb

Only use Map converter binding when no descendants

Update `MapBinder` to only attempt conversion based binding when there
are no know descendant elements.

See gh-11892
parent d6ae4e48
......@@ -24,6 +24,7 @@ import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Form;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertyState;
import org.springframework.boot.context.properties.source.IterableConfigurationPropertySource;
import org.springframework.core.CollectionFactory;
import org.springframework.core.ResolvableType;
......@@ -55,10 +56,12 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
Map<Object, Object> map = CollectionFactory.createMap(
(target.getValue() == null ? target.getType().resolve() : Map.class), 0);
Bindable<?> resolvedTarget = resolveTarget(target);
boolean hasDescendants = getContext().streamSources().anyMatch((source) -> source
.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT);
for (ConfigurationPropertySource source : getContext().getSources()) {
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
ConfigurationProperty property = source.getConfigurationProperty(name);
if (property != null) {
if (property != null && !hasDescendants) {
Object value = getContext().getPlaceholdersResolver()
.resolvePlaceholders(property.getValue());
return ResolvableTypeDescriptor.forType(target.getType())
......
......@@ -545,6 +545,22 @@ public class MapBinderTests {
assertThat(map.get("b")).isNotNull();
}
@Test
public void bindToMapWithCustomConverterAndChildElements() {
// gh-11892
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new MapConverter());
Binder binder = new Binder(this.sources, null, conversionService);
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo", "boom");
source.put("foo.a", "a");
source.put("foo.b", "b");
this.sources.add(source);
Map<String, String> map = binder.bind("foo", STRING_STRING_MAP).get();
assertThat(map.get("a")).isEqualTo("a");
assertThat(map.get("b")).isEqualTo("b");
}
@Test
public void bindToMapWithNoConverterForValue() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment