Allow SpEL MapAccessor to return null for nonexistent keys in its canRead() and read() methods.
My usage scenario:
A long text, such as an HTML template or email template, contains variables and expressions. Use a map to provide variable values, replace and evaluate expressions with SpEL, but some variables may not be in the map.
Comment From: sbrannen
Hi @jobmission,
Congratulations on submitting your first issue for the Spring Framework! 👍
I just introduced dedicated tests for the status quo.
https://github.com/spring-projects/spring-framework/blob/27b2243b43117e59ddc1d0f99e3f48e4ced632df/spring-context/src/test/java/org/springframework/context/expression/MapAccessorTests.java#L111-L120
If I understand you correctly, you would like for MapAccessor to support a boolean flag, which when enabled would allow that first assertion to be isTrue() and the second assertion to assert that the accessor returns null instead of throwing a MapAccessException.
Is that correct?
Comment From: jobmission
Yes, your explanation is what I want to express, thank you!
Comment From: sbrannen
After putting more thought into this, I have decided that it is best if we do not introduce such a flag in MapAccessor.
Rationale
MapAccessor is a PropertyAccessor implementation which merely provides syntactic sugar for accessing a map with a key used as a "property". Thus, you are not required to use that syntax to access values within a map.
You can instead use the standard "map indexing" syntax (supported by the built-in Indexer) to index into a map, and that will return null if an entry does not exist for the provided key.
In other words, the support you are asking for already exists.
In commit d81f1a55c2, I introduced two tests to demonstrate your options.
mapAccessThroughIndexerForNonexistentKey(): demonstrates that map access via the built-in support in theIndexerreturnsnullfor a nonexistent key.nullAwareMapAccessor(): demonstrates that users can implement and register a custom extension ofMapAccessorwhich reports that it can read any map (ignoring whether the map actually contains an entry for the given key) and returnsnullfor a nonexistent key.
Take a look at NullAwareMapAccessor for an example of how to achieve the latter. However, if you choose to implement and register such an accessor, please be aware that it can adversely conflict with other registered property accessors.
https://github.com/spring-projects/spring-framework/blob/d6fbe257f517cda9c1e66a2b579e579705e29334/spring-expression/src/test/java/org/springframework/expression/spel/MapAccessTests.java#L117-L133
As alluded to above, MapAccessor should not declare that it can read a value that it cannot, since that violates the PropertyAccessor contract.
As a side note, I discovered that this request is effectively a duplicate of #12270, dating back to 2010, and @jhoeller actually came to the same conclusion that I did. 😉
In light of the above, I am closing this issue as a:
- Duplicate of #12270
Cheers,
Sam