Bin Hawking opened SPR-15893 and commented
given variable = 9
, I expect:
map[variable] = map[9]
but in the current SpEL implementation:
map[variable]
= map[ (variable) ] = map[ ((((variable)))) ] // weird
= map['variable']
After reading the code, I found the cause in org.springframework.expression.spel.ast.Indexer::getValueRef()
.
// This first part of the if clause prevents a 'double dereference' of
// the property (#10516)
if (targetObject instanceof Map && (this.children[0] instanceof PropertyOrFieldReference)) {
...
}
else ...
10516 was for SpEL 3.x; while, as far as I can see from the 4.3.x code, dot property has nothing to do with Indexer
. An Indexer
node is instantiated only after eating [
. Hence the fix of #10516 should NOT be in Indexer
.
In practice, I used my revision of spring-expression
in which removed are those lines cited above. Then I got map[variable]=map[9]
in my app and the other parts still function correctly.
I hope it can be the official behavior of SpEL.
Affects: 4.3.10, 5.0 RC3
Issue Links:
-
10516
Comment From: spring-projects-issues
Bin Hawking commented
Indexer::generateCode(...)
is also impacted:
else if (this.indexedType == IndexedType.MAP) {
mv.visitTypeInsn(CHECKCAST, "java/util/Map");
// Special case when the key is an unquoted string literal that will be parsed as
// a property/field reference
if ((this.children[0] instanceof PropertyOrFieldReference)) {
PropertyOrFieldReference reference = (PropertyOrFieldReference) this.children[0];
String mapKeyName = reference.getName();
mv.visitLdcInsn(mapKeyName);
}
else ......
Comment From: sbrannen
Apologies for getting to this issue so many years later!
If the key supplied to a map is an unquoted string literal, the key will be parsed as a property or field reference.
If var
is a SpEL variable assigned the value of 9
, then to access map[9]
using the variable you would need to use the #
syntax to reference the variable as in map[#var]
.
In light of that, I am closing this issue as "works as designed".