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
This commit is contained in:
parent
d6ae4e48d8
commit
16b7dbf487
|
@ -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;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Form;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Form;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
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.boot.context.properties.source.IterableConfigurationPropertySource;
|
||||||
import org.springframework.core.CollectionFactory;
|
import org.springframework.core.CollectionFactory;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
|
@ -55,10 +56,12 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
|
||||||
Map<Object, Object> map = CollectionFactory.createMap(
|
Map<Object, Object> map = CollectionFactory.createMap(
|
||||||
(target.getValue() == null ? target.getType().resolve() : Map.class), 0);
|
(target.getValue() == null ? target.getType().resolve() : Map.class), 0);
|
||||||
Bindable<?> resolvedTarget = resolveTarget(target);
|
Bindable<?> resolvedTarget = resolveTarget(target);
|
||||||
|
boolean hasDescendants = getContext().streamSources().anyMatch((source) -> source
|
||||||
|
.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT);
|
||||||
for (ConfigurationPropertySource source : getContext().getSources()) {
|
for (ConfigurationPropertySource source : getContext().getSources()) {
|
||||||
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
|
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
|
||||||
ConfigurationProperty property = source.getConfigurationProperty(name);
|
ConfigurationProperty property = source.getConfigurationProperty(name);
|
||||||
if (property != null) {
|
if (property != null && !hasDescendants) {
|
||||||
Object value = getContext().getPlaceholdersResolver()
|
Object value = getContext().getPlaceholdersResolver()
|
||||||
.resolvePlaceholders(property.getValue());
|
.resolvePlaceholders(property.getValue());
|
||||||
return ResolvableTypeDescriptor.forType(target.getType())
|
return ResolvableTypeDescriptor.forType(target.getType())
|
||||||
|
|
|
@ -545,6 +545,22 @@ public class MapBinderTests {
|
||||||
assertThat(map.get("b")).isNotNull();
|
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
|
@Test
|
||||||
public void bindToMapWithNoConverterForValue() {
|
public void bindToMapWithNoConverterForValue() {
|
||||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||||
|
|
Loading…
Reference in New Issue