我试图理解为什么这不起作用?
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>
通过上面提到的链接,您可以找到有关JsonPath查询的更多详细信息。
如果仍然需要将JsonPath与SPEL集成,则可以将解析函数添加到评估上下文中。幸运的是,您已经使用带有JsonPathUtils
方法的evaluate(String, String)
类的spring-integration。
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
的是什么?它不是String或Integer值。它返回ToStringFriendlyJsonNode
的实例。因此doo==9
总是会给您false
,因为它们不能相等。此外,您不能使用>
或<
,因为不允许比较Object
和Integer
。因此,在比较之前,您需要转换为合适的类型。
expression.getValue("foo.bar.![doo!=null and new Integer(doo.toString()) == 9]");
此外,我们需要检查
doo
是否存在,因此我们需要检查null
。ToStringFriendlyJsonNode
只能提供字符串值。这就是为什么我们必须使用ToString()
。如您所见,本机SPEL不方便且过于冗长,因为不应将其用于复杂的Json查询。