Spring Expression Language (SpEL) для доступа json со списком - PullRequest
1 голос
/ 19 февраля 2020

Я пытаюсь понять, почему это не работает?

  context.addPropertyAccessor(new JsonPropertyAccessor());

  Object j = mapper.readTree(
"{\"foo\": {\"bar\": [ { \"fizz\": 5, \"buzz\": 6, \"doo\": 9 }, {\"fizz\": 7}, {\"fizz\": 8} ] } })");

System.out.println(evaluate(j, "foo.bar.![doo == 9]"));

Он всегда печатает:

[false, false, false]

Мне нужно проверить, содержит ли какой-либо из doo 9 .

1 Ответ

1 голос
/ 19 февраля 2020

Если вам не нужно использовать 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 запросов.

...