REST Assured 系列汇总 之 REST Assured 47 - Fetch Value From Nested JSON Array Using JsonNode – Jackson – At() Method
介绍
创建 POJO 类用来解析和获取一个 JSON 字符串中的值有时并不方便,特别针对那些非常长的,多层嵌套的 JSON。我们可以将 JSON 解析成树形结构更方便。
前提条件
前面我们已经解析过一个简单的 JSON Object , 嵌套的 JSON Object,和 JSON Array 成 JsonNode,参考如下:
Fetch Value From JSON Object Using JsonNode – Jackson – Get() & Path() Methods
Fetch Value From Nested JSON Object Using JsonNode – Jackson – At() Method
Fetch Value From JSON Array Using JsonNode – Jackson – Get() & Path() Methods
因为我们用到 Jackson API, 所以确保导入 Jackson Databind 依赖包。
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
嵌套的 JSON Array
JSON
树形结构表示 JSON Array
你可以用一个在线工具 来浏览上面的 JSON,呈现树型结构:
一个 JSON Array 可能是 JSON Objects 的集合 或 JSON arrays,如下:
[
[
{
"firstName": "Amod",
"lastName": "Mahajan",
"age": 28,
"isMarried": false,
"salary": 23456.54
},
{
"firstName": "Rahul",
"lastName": "Arora",
"age": 32,
"isMarried": true,
"salary": 33456.54
}
],
[
{
"firstName": "Amod",
"lastName": "Mahajan",
"age": 28,
"isMarried": false,
"salary": 23456.54
},
{
"firstName": "Rahul",
"lastName": "Arora",
"age": 32,
"isMarried": true,
"salary": 33456.54
}
]
]
反序列 deserialize 化嵌套的 JSON Array
我们用到 Jackson API 的 ObjectMapper 类,该类提供的 “readTree()” 方法负责将 JSON 内容 deserialization 反序列化成树形形式的JsonNode 集合
我们通过 JsonNode 类的 get() 和 path() 方法来获取值,然后转换成适合的数据类型。
我们只需用一个 index 来获取一个数组的元素,这也是基于数组的概念。
拿上面嵌套的 JSON Array为例子,如果我们想要获取第一个 JSON Object 中 “type” node 的值,可以用如下方式:
// Using get method
System.out.println(jsonTree.get(0).get("firstName").asText());
System.out.println(jsonTree.get(0).get("address").get(0).get("type").asText());
如果 JSON Object 或 JSON Array 嵌套比较深,那采用上面的语句就比较长且复杂了。我们可以用 at() 来代替,传入目标 node 的 path,类似文件 path,如下:
System.out.println(jsonTree.at("/0/firstName").asText());
System.out.println(jsonTree.at("/0/address/0/type").asText());
System.out.println(jsonTree.at("/0/address/1/type").asText());
上面的 “0” 和 “1” 代表 index,实际上,它足够智能把它解析成 index 或 key。如果 node 的 key 是一个数字,如 “0” 或 “1”,它也不会抱怨。首先,会试着把它看成 index,如果不是一个 JSON Array,然后就会把它看成是一个 node 的 key。如果这个 key 不存在,将失败。
代码
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class ParseNestedJsonArrayToReadValues {
@Test
public void parseJsonArrayToReadValues() throws JsonMappingException, JsonProcessingException
{
String jsonArray = "[\r\n" +
" {\r\n" +
" \"firstName\": \"Amod\",\r\n" +
" \"lastName\": \"Mahajan\",\r\n" +
" \"address\": [\r\n" +
" {\r\n" +
" \"type\": \"Permanent\",\r\n" +
" \"city\": \"Bengaluru\",\r\n" +
" \"state\": \"Karnataka\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"type\": \"Communication\",\r\n" +
" \"city\": \"Katihar\",\r\n" +
" \"state\": \"Bihar\"\r\n" +
" }\r\n" +
" ]\r\n" +
" },\r\n" +
" {\r\n" +
" \"firstName\": \"Animesh\",\r\n" +
" \"lastName\": \"Prashant\",\r\n" +
" \"address\": [\r\n" +
" {\r\n" +
" \"type\": \"Permanent\",\r\n" +
" \"city\": \"Delhi\",\r\n" +
" \"state\": \"Delhi\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"type\": \"Communication\",\r\n" +
" \"city\": \"Indore\",\r\n" +
" \"state\": \"MP\"\r\n" +
" }\r\n" +
" ]\r\n" +
" }\r\n" +
"]";
// Creating an instance of ObjectMapper class
ObjectMapper objectMapper = new ObjectMapper();
// Get tree representation of json
JsonNode jsonTree = objectMapper.readTree(jsonArray);
// Using get method
System.out.println(jsonTree.get(0).get("firstName").asText());
System.out.println(jsonTree.get(0).get("address").get(0).get("type").asText());
// Using at() method
// Printing details of first indexed node
System.out.println(jsonTree.at("/0/firstName").asText());
System.out.println(jsonTree.at("/0/address/0/type").asText());
System.out.println(jsonTree.at("/0/address/1/type").asText());
// Printing details of second indexed node
System.out.println(jsonTree.at("/1/firstName").asText());
System.out.println(jsonTree.at("/1/address/0/type").asText());
System.out.println(jsonTree.at("/1/address/1/type").asText());
}
}
输出
Amod
Permanent
Amod
Permanent
Communication
Animesh
Permanent
Communication
也可以试试下面的 JSON Array,其中有些 node 的 key 是数字。
[
{
"firstName": "Amod",
"lastName": "Mahajan",
"address": [
{
"0": "Permanent",
"1": "Bengaluru",
"2": "Karnataka"
},
{
"0": "Communication",
"1": "Katihar",
"2": "Bihar"
}
]
},
{
"firstName": "Animesh",
"lastName": "Prashant",
"address": [
{
"0": "Permanent",
"1": "Delhi",
"2": "Delhi"
},
{
"0": "Communication",
"1": "Indore",
"2": "MP"
}
]
}
]
下面的语句可以获取到 node 的值,能智能判断中数字是 index 还是 key 的名字。
System.out.println(jsonTree.at("/0/address/0/0").asText());
System.out.println(jsonTree.at("/0/address/1/0").asText());