spring-projects / spring-projects/spring-framework

AutoGrow not applied for nested map values

Open
#32,154 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: core type: enhancement
Dominant language
Java
Stars
60.2k
Forks
38.8k
Avg merge
5d 2h
Merged PRs (30d)
27

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with AbstractNestablePropertyAccessor.getPropertyValue(PropertyTokenHolder tokens) and the indexed-property handling shown in the report. Reproduce the nested Map<String, Map<String, Map<String, String>>> binding case using property[map1key][map2key][map3key], then verify that auto-growing supports the additional nested map level without the reported exception.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.