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
因为它们不可能相等。此外,您不能使用 >
或 <
,因为不允许比较 Object
和 Integer
。因此,您需要在比较之前转换为合适的类型。
expression.getValue("foo.bar.![doo!=null and new Integer(doo.toString()) == 9]");
我们还需要检查 doo
是否存在,这就是我们需要检查 null
的原因。 ToStringFriendlyJsonNode
只能提供字符串值。这就是为什么我们必须使用 ToString()
。如您所见,本机 SPEL 不方便且过于冗长,因为它不应该用于复杂的 Json 查询。
我想了解为什么这不起作用?
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
因为它们不可能相等。此外,您不能使用 >
或 <
,因为不允许比较 Object
和 Integer
。因此,您需要在比较之前转换为合适的类型。
expression.getValue("foo.bar.![doo!=null and new Integer(doo.toString()) == 9]");
我们还需要检查 doo
是否存在,这就是我们需要检查 null
的原因。 ToStringFriendlyJsonNode
只能提供字符串值。这就是为什么我们必须使用 ToString()
。如您所见,本机 SPEL 不方便且过于冗长,因为它不应该用于复杂的 Json 查询。