SPeL
cannot understand lambda expressions (->), but there is an implicit method.
You can register and use lambdas as SPeL
#functions.
You can extend SPeL
by registering user defined functions that can be called within the expression string. The function is registered with the StandardEvaluationContext
using the method.
We can write an example that takes the SPeL
code directly or contains the StandardEvaluationContext
:
public class SPeLExample {
public static void main(String[] args) {
try {
// JSON payload.
String payload = "...";
// Response 1 test.
List<HashMap<String, Object>> response1 = (List<HashMap<String, Object>>)
doSomething(payload, "#root['array']");
System.out.println("Response 1 => " + response1);
// Response 2 test.
StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext();
standardEvaluationContext.registerFunction("getMapItem",
SPeLExample.class.getMethod("getMapItem", String.class));
standardEvaluationContext.registerFunction("toInteger",
SPeLExample.class.getMethod("toInteger"));
Integer response2 = (Integer) doSomething(payload,
"#root['array'] == null ? null " +
": #root['array'].stream()" +
" .map(#getMapItem('c'))" +
" .mapToInt(#toInteger()).sum()",
standardEvaluationContext);
System.out.println("Response => " + response2);
} catch (Exception e) { throw new RuntimeException(e); }
}
public static Object doSomething(String payload,
String expressionString) {
return doSomething(payload, expressionString, null);
}
public static Object doSomething(String payload,
String expressionString,
StandardEvaluationContext standardEvaluationContext) {
try {
Map<String, Object> map = new ObjectMapper()
.readValue(payload, HashMap.class);
ExpressionParser expressionParser = new SpelExpressionParser();
Expression expression = expressionParser.parseExpression(expressionString);
if (standardEvaluationContext == null)
return expression.getValue(map);
return expression.getValue(standardEvaluationContext, map);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Function<LinkedHashMap, Object> getMapItem(String key) {
return o -> o.get(key);
}
public static ToIntFunction<Object> toInteger() {
return o -> Integer.valueOf((int)o);
}
}
I added two lambda functions getMapItem
and toInteger
, I registered them in StandardEvaluationContext
.
I rewrote your "data.array.stream().map(item -> item.get('c')).sum()"
code to handle special functions like this:
"#root['array'] == null ? null : #root['array'].stream().map(#getMapItem('c')).mapToInt(#toInteger()).sum()"