学习使用Jayway的JsonPath从JSON文档中提取信息。JsonPath类似于XML文档的Xpath。本教程将通过JsonPath的语法和一些例子来更好地理解它的用法。
目录
1.设置JsonPath
如果没有加入JsonPath,请将其加入到应用程序中。我们可以在Maven资源库中找到JsonPath的最新版本。
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.7.0</version>
</dependency>
通常情况下,我们会从API响应或应用程序中的任何其他来源获取JSON文档。但在这个例子中,我们是在读取JSON文件。
{
"widget": {
"debug": "on",
"window": {
"title": "Client Info",
"name": "client_info",
"width": 500,
"height": 500,
"padding": [10,10,10,50],
"locations" : [
{ "name": "header", "display": "true" },
{ "name": "footer", "display": "true" },
{ "name": "sidebar", "display": "false" }
]
}
}
}
如果我们要写一个Junit测试,我们可以在setup()方法中把JSON读成一个字符串。
static String json;
@BeforeAll
public static void setup() {
try {
URL fileUrl = TestJsonPathExpressions.class.getClassLoader().getResource("widget.json");
File file = new File(fileUrl.getFile());
json = new String(Files.readAllBytes(file.toPath()));
} catch (Exception e) {
e.printStackTrace();
}
}
2.一个简单的例子
在深入研究语法之前,让我们从一个简单的例子开始,看看如何从给定文件中提取信息。在下面的例子中,我们提取widget的标题名称,并验证其预期值。
@Test
public void testGetWidgetTitle_ThenSuccess(){
String widgetTitle = JsonPath.read(json, "$.widget.window.title");
Assertions.assertEquals("Client Info", widgetTitle);
}
3.JsonPath 语法
3.1.符号
JsonPath支持两种表示节点的符号:点和括号。在下面的例子中,两个表达式都指向同一个节点。
$.widget.window.title//圆点符号$['widget']['window']['title']//括号表示法
3.2.操作符
JsonPath支持许多操作符,可以用来表示JSON文档中的特定节点或范围。
$代表根节点。所有的路径表达式都以它开始。@代表当前正在处理的节点。它与一个过滤器谓词一起使用。在下面的例子中,我们要找到所有显示为true的位置。
@Test
public void testGetDisplayLocations_ThenSuccess(){
List<String> locations = JsonPath.read(json, "$.widget.window.locations[?(@.display == 'true')].name");
Assertions.assertTrue(List.of("header", "footer").containsAll(locations));
}
*代表当前范围内的所有节点。例如,下面的表达式返回所有的位置,而不考虑显示属性。
@Test
public void testGetAllDisplayLocations_ThenSuccess(){
List<String> locations = JsonPath.read(json, "$.widget.window.locations[*].name");
Assertions.assertTrue(List.of("header", "footer", "sidebar").containsAll(locations));
}
[start:end]将数组中的元素从起点索引切到终点索引。
@Test
public void testFirstDisplayLocation_ThenSuccess(){
List<String> locations = JsonPath.read(json, "$.widget.window.locations[0,1].name");
Assertions.assertTrue(List.of("header", "footer").containsAll(locations));
}
3.3.函数
JsonPath提供了内置的函数来支持一些常见的操作,如:sum(),min(),max(),avg(),stddev(),length(),keys(),concat(input)和append(input)。
在下面的例子中,我们要为小组件找到最大的padding值。
@Test
public void testLargestPadding_ThenSuccess(){
Double largestPadding = JsonPath.read(json, "$.widget.window.padding.max()");
Assertions.assertEquals(50, largestPadding);
}
4.JsonPath谓词
谓词有助于根据提供的条件过滤一个数组的节点。当我们想只提取那些符合特定标准的数组项目时,这很有用。
我们已经在上一节中看到了内联谓词的例子。
List<String> locations = JsonPath.read(json, "$.widget.window.locations[?(@.display == 'true')].name");
让我们用com.jayway.jsonpath.Predicate 类重写同一个谓词。注意在*'location[?]'*中使用了? 字符,暗示了要应用的谓词的位置。
@Test
public void testGetTrueDisplayLocationsWithPredicate_ThenSuccess(){
Predicate displayEnabled = new Predicate() {
@Override
public boolean apply(PredicateContext ctx) {
return ctx.item(Map.class).get("display").toString().equalsIgnoreCase("true");
}
};
List<String> locations = JsonPath.read(json, "$.widget.window.locations[?].name", displayEnabled);
Assertions.assertTrue(List.of("header", "footer").containsAll(locations));
}
注意,我们可以在一个表达式中传递多个谓词和占位符。当提供多个谓词时,它们将按顺序应用,其中占位符的数量必须与提供的谓词的数量相匹配。在下面的例子中,我们要传递两个谓词widgetEnabled和displayEnabled。
JsonPath.read(json, "$.widget.window[?].locations[?].name", widgetEnabled, displayEnabled);
5.自定义配置
JsonPathOption 枚举提供了几个选项来定制默认配置。
- Option.AS_PATH_LIST返回评价路径而不是值。
- Option.DEFAULT_PATH_LEAF_TO_NULL为缺少的节点返回
null。 - Option.ALWAYS_RETURN_LIST 即使表达式评估的是一个值,也会返回一个List。
- Option.SUPPRESS_EXCEPTIONS在运行时抑制所有异常。
- Option.REQUIRE_PROPERTIES在评估不确定的路径时,需要路径中定义的属性。
要将配置传递给JsonPath对象,请使用其using() 方法。在下面的例子中,我们正在获取一个单一的值,但它被作为一个列表返回。
@Test
public void testConfiguration_ThenSuccess(){
Configuration configuration = Configuration
.builder()
.options(ALWAYS_RETURN_LIST, SUPPRESS_EXCEPTIONS)
.build();
List<String> locations = JsonPath
.using(configuration)
.parse(json).read("$.widget.window.locations[0].name");
Assertions.assertTrue(List.of("header").containsAll(locations));
}
6.结语
在这个JsonPath教程中,我们学会了根据我们的需要来设置和配置JsonPath。我们学习了JsonPath的语法,包括记号、符号和运算符的例子。我们还经历了几个例子,通过使用谓词的过滤器从JSON文档中提取信息。
学习愉快!!
这个帖子有帮助吗?
如果你喜欢这篇文章,请告诉我们。这是我们改进的唯一方法。
有
没有