I encouter a problem while accessing a JsonNode with org.springframework.expression.spel.standard.SpelExpressionParser into a Spring Boot 2.2.4 service. I can describe the issue with the example below:
Given the Json as root object in a StandardEvaluationContext :
{"property":[{"name":"value1"},{"name":"value2"}]}
the spring expression language value with selector below returns value1
with no problem:
property.^[name != null].name
but this selector below returns null
instead of value1
:
property.^[name == 'value1'].name
any idea ?
EDIT:
here's a main method class example:
import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.integration.json.JsonPropertyAccessor;
public class TestJsonAccessor {
public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
StandardEvaluationContext context = new StandardEvaluationContext();
context.setPropertyAccessors(List.of(new JsonPropertyAccessor()));
context.setRootObject(new ObjectMapper().readTree("{\"property\":[{\"name\":\"value1\"},{\"name\":\"value2\"}]}"));
SpelExpressionParser parser = new SpelExpressionParser();
System.out.println(parser.parseExpression("property.^[name != null].name").getValue(context));
System.out.println(parser.parseExpression("property.^[name == 'value1'].name").getValue(context));
}
}
in the console that prints :
value1
Exception in thread "main" org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51)
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:406)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:92)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:272)
at TestJsonAccessor.main(TestJsonAccessor.java:20)
The problem is here: name == 'value1'
. That name
is not a plain text to compare - it is a ToStringFriendlyJsonNode
and to make it working expected with that equal
operator you need to make it as string. Therefore like this:
property.^[name.toString() == 'value1'].name
There is another much longer way to reach the goal:
property.^[name.getTarget().asText() == 'value1'].name
The point of the JsonPropertyAccessor
it to make a final result end-user friendly. In the middle it is still some JSON object we need to deal with.