I have a YAML application properties file and I'm trying to map a series of items to a Set
. This appears to be impossible given the Spring Beans code that processes the properties, but the documentation tells a different story.
YAML:
test:
- "value"
Code:
@ConfigurationProperties
public class MyTest {
private Set<String> test;
public void setTest(Set<String> test) {
this.test = test;
}
public Set<String> getTest() {
return this.test;
}
}
The spring-boot
documentation states:
To bind to properties like that using the Spring DataBinder utilities (which is what @ConfigurationProperties does) you need to have a property in the target bean of type java.util.List (or Set) and you either need to provide a setter, or initialize it with a mutable value, e.g. this will bind to the properties above
However, Set
is not supported. If you attempt to map a YAML property to a Set
, you'll get an exception similar to the following:
Property referenced in indexed property path 'test[0]' is neither an array nor a List nor a Map; returned value was [value]
The documentation should be corrected on this point.
There are tests working with Set in RelaxedDataBinderTests
so it should work. Can you put a sample project that reproduces the issue. Ideally here? Thanks
Closing due to lack of response. Please comment again and we can reopen the issue if you're still having trouble.
It looks like the RelaxedDataBinderTests
are testing that the YAML foo: bar,bat
can get mapped to a Set
, while this issue appears to be about the YAML:
foo:
-bar
-bat
I duplicated the issue in my Boot 1.2.5.RELEASE app and stumbled across this thread. Once I changed my Set
objects back to List
everything worked as expected. I don't really think it's a code issue as there is no guarantee of uniqueness in a YAML list, so trying to map them to a Set
is incomplete at best. However, I do agree with wooder79 that the (or Set) language in the documentation implies that the two types are interchangeable and is misleading.
@dan-nawrocki Are you able to share the code that duplicated the issue to https://github.com/spring-projects/spring-boot-issues?
Sure. It looks like adding this to RelaxedDataBinderTests
does the trick:
@Test
public void testBindNestedSetFromList() throws Exception {
TargetWithNestedSet target = new TargetWithNestedSet();
this.conversionService = new DefaultConversionService();
bind(target, "nested[0]: bar");
assertEquals("[bar]", target.getNested().toString());
}
Could you also support below syntax? the object array.
test:
foo:
- name: abc
value: 123
- name: efg
value: 456
This is still happening in Spring Boot 1.4.0.M3. Trying to set property this way always fails:
security:
filter-dispatcher-types:
- REQUEST
- ERROR
Only workaround I found is:
security:
filter-dispatcher-types: REQUEST, ERROR
@ulisesbocchio This issue is still open so it's to be expected that 1.4 behaves as you have described
@philwebb or @snicoll is there a reason this has to be pushed all the way to 2.0? This seems like a pretty simple bug fix that is impacting all 1.x users that declare Set
s. Thanks!
@lhazlewood Unfortunately it's not so easy to fix with our current design.
Taking into account Set
instances in the processKeyedProperty
method of AbstractNestablePropertyAccessor
in spring-beans
project passes the following test (based on the @dan-nawrocki 's test in this comment):
@Test
public void testBindNestedSetFromList() throws Exception {
TargetWithNestedSet target = new TargetWithNestedSet();
this.conversionService = new DefaultConversionService();
bind(target, "nested[0]: bar");
bind(target, "nested[1]: foo");
bind(target, "nested[2]: bar");
assertThat(target.getNested().toString()).isEqualTo("[bar, foo]");
}
@philwebb Do you think this problem must be managed here? If so, I can make a pull request to spring-framework
project.
@antoinecarton We have plans to rework the binding system entirely. I'd suggest waiting until we get a bit further before suggesting any framework changes. Thanks!
try this taken from here
#YAML also has a set type, which looks like this:
set:
? item1
? item2
? item3
#Like Python, sets are just maps with null values; the above is equivalent to:
set2:
item1: null
item2: null
item3: null
@philwebb Any news on this ?
Sorry for the interruption, that was done for Spring Boot 2.x
Most helpful comment
This is still happening in Spring Boot 1.4.0.M3. Trying to set property this way always fails:
Only workaround I found is: