Bind empty string to empty collection or array of rich types
Previously, when an empty String was bound to a collection or array of rich types it would fail as there was no converter capable of creating a Collection<RichType> or RichType[] from the String. This commit updates IndexedElementsBinder to apply special treatment to empty String values. Now, when such a value is being processed, an empty Collection or array is the result. Closes gh-12965
This commit is contained in:
parent
45f4e8795e
commit
3992dacdc8
|
@ -18,6 +18,7 @@ package org.springframework.boot.context.properties.bind;
|
|||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -32,6 +33,7 @@ import org.springframework.boot.context.properties.source.IterableConfigurationP
|
|||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for {@link AggregateBinder AggregateBinders} that read a sequential run of
|
||||
|
@ -81,11 +83,17 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
|||
ResolvableType aggregateType, ResolvableType elementType) {
|
||||
ConfigurationProperty property = source.getConfigurationProperty(root);
|
||||
if (property != null) {
|
||||
Object aggregate = convert(property.getValue(), aggregateType,
|
||||
target.getAnnotations());
|
||||
ResolvableType collectionType = ResolvableType
|
||||
.forClassWithGenerics(collection.get().getClass(), elementType);
|
||||
Collection<Object> elements = convert(aggregate, collectionType);
|
||||
Collection<Object> elements;
|
||||
Object value = property.getValue();
|
||||
if (value instanceof String && !StringUtils.hasText((String) value)) {
|
||||
elements = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
Object aggregate = convert(value, aggregateType, target.getAnnotations());
|
||||
ResolvableType collectionType = ResolvableType
|
||||
.forClassWithGenerics(collection.get().getClass(), elementType);
|
||||
elements = convert(aggregate, collectionType);
|
||||
}
|
||||
collection.get().addAll(elements);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -363,6 +363,19 @@ public class CollectionBinderTests {
|
|||
assertThat(foo.getFoos().get(1).getValue()).isEqualTo("three");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindToNestedCollectionWhenEmptyStringShouldReturnEmptyCollection() {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("foo.value", "one");
|
||||
source.put("foo.foos", "");
|
||||
this.sources.add(source);
|
||||
Bindable<BeanWithNestedCollection> target = Bindable
|
||||
.of(BeanWithNestedCollection.class);
|
||||
BeanWithNestedCollection foo = this.binder.bind("foo", target).get();
|
||||
assertThat(foo.getValue()).isEqualTo("one");
|
||||
assertThat(foo.getFoos()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindToCollectionShouldUsePropertyEditor() {
|
||||
// gh-12166
|
||||
|
|
Loading…
Reference in New Issue