REST Assured 43 - Get All Keys From A Nested JSON Object

REST Assured 系列汇总 之 REST Assured 43 - Get All Keys From A Nested JSON Object

介绍

我们可能会得到一个嵌套的 JSON Object,它可能还是动态的。一个动态的响应包括很多键值对。例如:一张商务舱机票的福利肯定比一张经济舱机票的多。如果我们有一个 API 订购机票,显然会得到不同的 JSON 响应。JSON 作为 request body也一样。

总之,你需要从一个普通的或嵌套的 JSON Object中得到所有的键值。

前提条件

Required Java Library

因为我们用到 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>

Simple JSON Object

JSON Object

{
    
    
  "firstName": "Animesh",
  "lastName": "Prashant"
}

利用 Java MAP

我们可以将一个 JSON Object 反序列化 deserialization 成 Java Map,我们就很容易得到所有的键值对。

import java.util.Map;
import java.util.Set;
 
import org.junit.Test;
 
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
 
public class GetAllKeysFromJsonObject {
    
    
 
	@Test
	public void getAllKeysFromJsonObjectUsingMap() throws JsonMappingException, JsonProcessingException {
    
    
 
		String jsonObject = "{\r\n" + "  \"firstName\": \"Animesh\",\r\n" + "  \"lastName\": \"Prashant\"\r\n" + "}";
		ObjectMapper objectMapper = new ObjectMapper();
		// Deserializing into a Map
		Map<String, String> parsedJsonObject = objectMapper.readValue(jsonObject,
				new TypeReference<Map<String, String>>() {
    
    
				});
		// Get all keys
		Set<String> allKeys = parsedJsonObject.keySet();
		System.out.println("All keys are : ");
		allKeys.stream().forEach(k -> System.out.println(k));
 
	}
 
}

输出:

All keys are : 
firstName
lastName

利用 JSONNode:

需要用到一个方法 “ObjectMapper” 类提供的 “readTree()”,这个方法将 JSON 内容反序列化 deserialization 成一系列 JsonNode 组成的树形结构。JsonNode 是所有 JSON nodes的一个基类,基于 Jackson 实现的 JSON Tree 模块。好比 XML DOM Trees 中的 DOM nodes。

import java.util.Iterator;
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 GetAllKeysFromJsonObject {
    
    
 
	@Test
	public void getAllKeysFromJsonObjectUsingObjectMapper() throws JsonMappingException, JsonProcessingException
	{
    
    
		
		String jsonObject = "{\r\n" + 
				"  \"firstName\": \"Animesh\",\r\n" + 
				"  \"lastName\": \"Prashant\"\r\n" + 
				"}";
		ObjectMapper objectMapper = new ObjectMapper();
		// Converting JSON Object string to JsonNode
		JsonNode parsedJsonObject = objectMapper.readTree(jsonObject);
		// Get all fields or keys
		Iterator<String> allKeys= parsedJsonObject.fieldNames();
		System.out.println("All keys are : ");
		allKeys.forEachRemaining(k -> System.out.println(k));
	}
}

输出:

All keys are : 
firstName
lastName

Nested JSON Object

JSON Object:

{
    
    
  "firstName": "Animesh",
  "lastName": "Prashant",
  "address": {
    
    
    "city": "Katihar",
    "State": "Bihar"
  }
}

如果我们用上面的逻辑从嵌套的 JSON Object里获取所有键值,我们将拿不到 “city” 和 “state” 键值。所以,我们需要额外的逻辑判断键的值是否是一个 JSON Object,如果是,我们要从键的值里获取子键值。

使用 Map
当我们反序列化 deserialize 一个 JSON Object 成 Map时,其实它是 LinkedHashMap 的一个实例,所以我们直接用 LinkedHashMap 取代 Map。

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
 
import org.junit.Test;
 
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
 
public class GetAllKeysFromJsonObject {
    
    
 
	@Test
	public void getAllKeysFromNestedJsonObjectUsingMap() throws JsonMappingException, JsonProcessingException
	{
    
    
		
		String jsonObject = "{\r\n" + 
				"  \"firstName\": \"Animesh\",\r\n" + 
				"  \"lastName\": \"Prashant\",\r\n" + 
				"  \"address\": {\r\n" + 
				"    \"city\": \"Katihar\",\r\n" + 
				"    \"State\": \"Bihar\"\r\n" + 
				"  }\r\n" + 
				"}";
		ObjectMapper objectMapper = new ObjectMapper();
		// Deserialize into Map
		Map<String,Object> parsedJsonObject = objectMapper.readValue(jsonObject, new TypeReference<Map<String, Object>>(){
    
    });
		// Get all keys
		Set<String> allKeys = parsedJsonObject.keySet();
		// Iterate keys
		allKeys.stream().forEach(key -> {
    
    
			Object value = parsedJsonObject.get(key);
			// If value is a String. You may need to add more if value is of different types
			if(value instanceof String)
				System.out.println(key);
			// If value is another JSON Object which will be LinkedHashMap. You can see this while debugging
			else if(value instanceof LinkedHashMap<?, ?>)
			{
    
    
				@SuppressWarnings("unchecked")
				Set<String> allKeysOfNestedJsonObject  = ((LinkedHashMap<String, ?>)value).keySet();
				allKeysOfNestedJsonObject.stream().forEach(k->System.out.println(k));
			}
		});
		
	}
}

输出:

firstName
lastName
city
State

使用 JsonNode

import java.util.Iterator;
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;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
 
public class GetAllKeysFromJsonObject {
    
    
 
	@Test
	public void getAllKeysFromNestedJsonObjectUsingJsonNode() throws JsonMappingException, JsonProcessingException
	{
    
    
			String jsonObject = "{\r\n" + 
					"  \"firstName\": \"Animesh\",\r\n" + 
					"  \"lastName\": \"Prashant\",\r\n" + 
					"  \"address\": {\r\n" + 
					"    \"city\": \"Katihar\",\r\n" + 
					"    \"State\": \"Bihar\"\r\n" + 
					"  }\r\n" + 
					"}";
			ObjectMapper objectMapper = new ObjectMapper();
			JsonNode parsedJsonObject = objectMapper.readTree(jsonObject);
			Iterator<String> allKeys= parsedJsonObject.fieldNames();
			allKeys.forEachRemaining(k -> {
    
    
				Object value = parsedJsonObject.get(k);
				// TextNode can be related to String from previous example
				// You may need to add IntNode or BooleanNode for different types of values
				if(value instanceof TextNode)
					System.out.println(k);
				// ObjectNode can be related to LinkedHashMap from previous example
				else if(value instanceof ObjectNode)
				{
    
    
					Iterator<String> keyss = ((ObjectNode)value).fieldNames();
					keyss.forEachRemaining(ke -> System.out.println(ke));
				}
		
		});
		
	
	}
	
}

输出:

firstName
lastName
city
State

Guess you like

Origin blog.csdn.net/wumingxiaoyao/article/details/120364594