gh-32154: BeanWrapper - fix autogrow for nested maps

Signed-off-by: Dmitrii Bocharov <bdshadow@gmail.com>
This commit is contained in:
Dmitrii Bocharov 2025-05-15 12:23:09 +02:00
parent 2a29e16456
commit 2ac248d27e
2 changed files with 23 additions and 3 deletions

View File

@ -649,11 +649,14 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
value = list.get(index);
}
else if (value instanceof Map map) {
Class<?> mapKeyType = ph.getResolvableType().getNested(i + 1).asMap().resolveGeneric(0);
ResolvableType mapResolvableType = ph.getResolvableType().getNested(i + 1).asMap();
Class<?> mapKeyType = mapResolvableType.resolveGeneric(0);
Class<?> mapValueType = mapResolvableType.resolveGeneric(1);
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor);
growMapIfNecessary(map, convertedMapKey, mapValueType, indexedPropertyName.toString());
value = map.get(convertedMapKey);
}
else if (value instanceof Iterable iterable) {
@ -792,6 +795,17 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
}
}
private void growMapIfNecessary(Map<Object, Object> map, @Nullable Object convertedMapKey,
@Nullable Class<?> mapValueType, String name) {
if (mapValueType == null || !isAutoGrowNestedPaths()) {
return;
}
if (!map.containsKey(convertedMapKey) && map.size() < this.autoGrowCollectionLimit) {
map.put(convertedMapKey, newValue(mapValueType, null, name));
}
}
/**
* Get the last component of the path. Also works if not nested.
* @param pa property accessor to work on

View File

@ -20,7 +20,6 @@ import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -200,6 +199,13 @@ class BeanWrapperAutoGrowingTests {
assertThat(bean.getNestedNestedList().get(0).get(0)).singleElement().isInstanceOf(Bean.class);
}
@Test
void getPropertyValueAutoGrowNestedNestedMap() {
assertThat(wrapper.getPropertyValue("nestedNestedMap[A][B][C]")).isNotNull();
assertThat(bean.getNestedNestedMap()).hasSize(1);
assertThat(bean.getNestedNestedMap().get("A").get("B").get("C")).isInstanceOf(Bean.class);
}
@Test
void getPropertyValueAutoGrowListNotParameterized() {
assertThatExceptionOfType(InvalidPropertyException.class).isThrownBy(() ->
@ -224,7 +230,7 @@ class BeanWrapperAutoGrowingTests {
assertThat(bean.getNestedMap().get("A").get("B")).isInstanceOf(Bean.class);
}
@Test @Disabled // gh-32154
@Test
void setPropertyValueAutoGrowNestedNestedMapWithinMap() {
wrapper.setPropertyValue("nestedNestedMap[A][B][C]", new Bean());
assertThat(bean.getNestedNestedMap().get("A").get("B").get("C")).isInstanceOf(Bean.class);