Spring json 列表访问的表达式语言 (SpEL)

Spring Expression Language (SpEL) for json access with list

我想了解为什么这不起作用?

  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。

如果您不一定需要使用 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>

通过上面提到的link你可以找到更多关于Json路径查询的细节。


如果您仍然需要将 JsonPath 与 SPEL 集成,您可以将解析函数添加到评估上下文中。幸运的是,您已经使用 spring-integration,它具有 JsonPathUtils class 和 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

我终于弄清楚了你的问题的原因。首先:猜猜 returns 表达式 foo.bar.doo 是什么?它不是字符串或整数值。它 returns ToStringFriendlyJsonNode 的一个实例。所以 doo==9 总是会给你 false 因为它们不可能相等。此外,您不能使用 ><,因为不允许比较 ObjectInteger。因此,您需要在比较之前转换为合适的类型。

 expression.getValue("foo.bar.![doo!=null and new Integer(doo.toString()) == 9]");

我们还需要检查 doo 是否存在,这就是我们需要检查 null 的原因。 ToStringFriendlyJsonNode 只能提供字符串值。这就是为什么我们必须使用 ToString()。如您所见,本机 SPEL 不方便且过于冗长,因为它不应该用于复杂的 Json 查询。