Если вам не нужно использовать SPEL, вы обязательно можете сделать это легко с помощью Jayway JsonPath
Включить зависимость:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>
Затем используйте JsonPath
и запрос:
Srgin json = "{\"foo\": {\"bar\": [ { \"fizz\": 5, \"buzz\": 6, \"doo\": 9 },
{\"fizz\": 7}, {\"fizz\": 8, \"doo\": 6} ] } })";
JSONArray array = JsonPath.read(json, "foo.bar[?(@.doo==9)]");
// now array is a List of size 1, since second "doo" is not equal 9
// using array.get(0) you can get first object as a HashMap<String, Object>
По указанной выше ссылке вы можете найти более подробную информацию о запросах JsonPath.
Если вам все еще нужно интегрировать JsonPath с SPEL, вы можете добавить функцию синтаксического анализа в контекст оценки. К счастью, вы уже используете пружинную интеграцию с классом JsonPathUtils
с методом evaluate(String, String)
.
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
Method method = BeanUtils.resolveSignature("evaluate", JsonPathUtils.class);
evaluationContext.registerFunction("jsonPath", method);
String json = "{\"foo\": {\"bar\": [ { \"fizz\": 5, \"buzz\": 6, \"doo\": 9 }, " +
"{\"fizz\": 7}, {\"fizz\": 8, \"doo\": 7} ] } })";
evaluationContext.setVariable("foo", json);
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("#jsonPath(#foo, 'foo.bar[?(@.doo>6)]')");
Object result = expression.getValue(evaluationContext);
//now result contains still the same JSONArray
И, наконец, я выяснил причину вашей проблемы. Прежде всего: угадайте, что возвращает выражение foo.bar.doo
? Это не строковое или целочисленное значение. Возвращает экземпляр ToStringFriendlyJsonNode
. Так что doo==9
всегда даст вам false
, так как они не могут быть равны. Более того, вы не можете использовать >
или <
, потому что нельзя сравнивать Object
и Integer
. Поэтому перед сравнением необходимо привести к подходящему типу.
expression.getValue("foo.bar.![doo!=null and new Integer(doo.toString()) == 9]");
Также нам нужно проверить, существует ли doo
, поэтому нам нужно проверить на null
. ToStringFriendlyJsonNode
может предоставить только строковое значение. Вот почему мы должны использовать ToString()
. Как вы видите, нативный SPEL неудобен и слишком многословен, поскольку он не должен использоваться для сложных Json запросов.