Description
Affects: 6.0.8
Language: Kotlin
Spring Version: 6.0.8
I am using data binding for parsing form data into a form object. When using a singly nested map (Map<String, Map<String, String>
), I find that using the key property[map1key][map2key]
works as expected to set the nested value, but when adding another layer, e.g. Map<String, Map<String, Map<String, String>>>
with key property[map1key][map2key][map3key]
this fails with an exception cannot access indexed value of property referenced in indexed property path nested map
.
Looking into the source code, I believe I tracked it down to the AbstractNestablePropertyAccessor.getPropertyValue(PropertyTokenHolder tokens)
method which seems to only set the default value on the first token which explains why this works for a singly nested map but not a double or greater one. I suspect this affects any type of auto growing collection as well.
relevant snippet:
if (tokens.keys != null) {
if (value == null) {
if (isAutoGrowNestedPaths()) {
value = setDefaultValue(new PropertyTokenHolder(tokens.actualName));
}
else {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value of property referenced in indexed " +
"property path '" + propertyName + "': returned null");
}
}
StringBuilder indexedPropertyName = new StringBuilder(tokens.actualName);
// apply indexes and map keys
for (int i = 0; i < tokens.keys.length; i++) {
String key = tokens.keys[i];
if (value == null) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value of property referenced in indexed " +
"property path '" + propertyName + "': returned null");
}
As a workaround, I'm using a single map with a custom key that I deserialize manually and then convert to a nested map in application code, but it would be nice if this was supported as part of the data binding.
Activity
jhoeller commentedon Jan 30, 2024
As far as I was able to reproduce this, the case only applies to multi-nested Map values. There is a dedicated code path for auto-growing map values in
getPropertyHoldingValue
which currently assumes one level only.[-]AutoGrow not applied for nested collections[/-][+]AutoGrow not applied for nested map values[/+]Disabled test for auto-growing nested map values