如何在 Java 中使用 JSONPath 搜索数组?
How to search an array using JSONPath in Java?
我想使用 json-path-assert 为 Web 服务编写单元测试。鉴于此 JSON:
[
["Some short name","Some parent","Some name"],
["Some short name 2","Some parent 2","Some name 2"]
]
我想检查 "Some name 2" 的父级是 "Some parent 2"。我无法更改 JSON 的结构,因为它是由第三方库指定的。
这是我想出的JSON路径表达式:
$..[?(@[2] == 'Some name 2')][1]
此表达式工作正常,并在 this JSON tool 中给出 returns 预期结果 ('Some parent 2')。但是,当使用 JSON 路径库在 Java 中使用它时,我得到一个空结果而不是正确的值:
import com.jayway.jsonpath.JsonPath;
import org.junit.Test;
public class TestJSONPath
{
@Test
public void testJsonPath() {
String json = "[[\"Some short name\",\"Some parent\",\"Some name\"]," +
"[\"Some short name 2\",\"Some parent 2\",\"Some name 2\"]]";
System.out.println(JsonPath.read(json, "$[1][1]")); // OK, returns 'Some parent 2'
System.out.println(JsonPath.read(json, "$..[?(@[2] == 'Some name 2')][1]")); // Not OK, returns an empty list
}
}
这是我的 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
你能帮我解决这个问题吗?
这可行:
$[?(@[2] == 'Some name 2')][1]
背景:
如果你尝试 "original" JSONPath implementation written by Stefan Goessner,下面的表达式 returns 预期的数组:
$..[?(@[2] == 'Some name 2')]
(索引 2 处的值为 'Some name 2' 的后代)
===> ["Some parent 2"]
这很有趣...使用 jayway、Goessners-JSON-lib 或 jsonquerytool 尝试这些表达式:
"$..*" //list of all descendants (both child-arrays + elements in arrays)
"$.*" //list of all direct children (both child arrays)
"$" //actual element (the array itself)
Stefan Goessner 的 JavaScript 库 returns 与 "jayway" 实现相同。但是 "jsonquerytool" 为 $
给出了 false
- 这绝对是错误的。 $
是 "the root object/element".
对于 $..*
,这与所有三种实现的结果相同:
[
[
"Some short name",
"Some parent",
"Some name"
],
[
"Some short name 2",
"Some parent 2",
"Some name 2"
],
"Some short name",
"Some parent",
"Some name",
"Some short name 2",
"Some parent 2",
"Some name 2"
]
所以 $..[?(@[2] == 'Some name 2')]
应该匹配索引“1”处的数组...在我看来,jayway 做错了。
With JSONPath square brackets operate on the object or array addressed by the previous path fragment. (see http://goessner.net/articles/JsonPath/)
Goessner 是 JSONPath 的发明者 - 所以他的实现方式是正确的!!!
总结: jsonquerytool 和 jayway 的实现是错误的。
令人惊讶的是,这个查询在所有实现中都按预期工作(尽管 $
在 jsonquerytool 中是 false
)
$[?(@[2] == 'Some name 2')][1]
此版本也有效:
$.[?(@[2] == 'Some name 2')][1]
我想使用 json-path-assert 为 Web 服务编写单元测试。鉴于此 JSON:
[
["Some short name","Some parent","Some name"],
["Some short name 2","Some parent 2","Some name 2"]
]
我想检查 "Some name 2" 的父级是 "Some parent 2"。我无法更改 JSON 的结构,因为它是由第三方库指定的。
这是我想出的JSON路径表达式:
$..[?(@[2] == 'Some name 2')][1]
此表达式工作正常,并在 this JSON tool 中给出 returns 预期结果 ('Some parent 2')。但是,当使用 JSON 路径库在 Java 中使用它时,我得到一个空结果而不是正确的值:
import com.jayway.jsonpath.JsonPath;
import org.junit.Test;
public class TestJSONPath
{
@Test
public void testJsonPath() {
String json = "[[\"Some short name\",\"Some parent\",\"Some name\"]," +
"[\"Some short name 2\",\"Some parent 2\",\"Some name 2\"]]";
System.out.println(JsonPath.read(json, "$[1][1]")); // OK, returns 'Some parent 2'
System.out.println(JsonPath.read(json, "$..[?(@[2] == 'Some name 2')][1]")); // Not OK, returns an empty list
}
}
这是我的 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
你能帮我解决这个问题吗?
这可行:
$[?(@[2] == 'Some name 2')][1]
背景:
如果你尝试 "original" JSONPath implementation written by Stefan Goessner,下面的表达式 returns 预期的数组:
$..[?(@[2] == 'Some name 2')]
(索引 2 处的值为 'Some name 2' 的后代)
===> ["Some parent 2"]
这很有趣...使用 jayway、Goessners-JSON-lib 或 jsonquerytool 尝试这些表达式:
"$..*" //list of all descendants (both child-arrays + elements in arrays)
"$.*" //list of all direct children (both child arrays)
"$" //actual element (the array itself)
Stefan Goessner 的 JavaScript 库 returns 与 "jayway" 实现相同。但是 "jsonquerytool" 为 $
给出了 false
- 这绝对是错误的。 $
是 "the root object/element".
对于 $..*
,这与所有三种实现的结果相同:
[
[
"Some short name",
"Some parent",
"Some name"
],
[
"Some short name 2",
"Some parent 2",
"Some name 2"
],
"Some short name",
"Some parent",
"Some name",
"Some short name 2",
"Some parent 2",
"Some name 2"
]
所以 $..[?(@[2] == 'Some name 2')]
应该匹配索引“1”处的数组...在我看来,jayway 做错了。
With JSONPath square brackets operate on the object or array addressed by the previous path fragment. (see http://goessner.net/articles/JsonPath/)
Goessner 是 JSONPath 的发明者 - 所以他的实现方式是正确的!!! 总结: jsonquerytool 和 jayway 的实现是错误的。
令人惊讶的是,这个查询在所有实现中都按预期工作(尽管 $
在 jsonquerytool 中是 false
)
$[?(@[2] == 'Some name 2')][1]
此版本也有效:
$.[?(@[2] == 'Some name 2')][1]