REST Assured 系列汇总 之 REST Assured 25 - 用Jackson API的ObjectMapper类创建JSON Object
关于Jackson API
Jackson API是java的高性能JSON处理器。我们利用Jackson API 可以执行serialization系列化,deserialization 反序列化,读/写一个JSON文件。
Maven 依赖:
一般尽量用最新版本的依赖来自Central Maven Repository。
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0-rc2</version>
</dependency>
注意
:当我们添加jackosn-databind依赖时,传递依赖包jackson-annotations 和jackson-core也会自动下载。
当然添加json-schema-validator依赖时,jackosn-databind,jackson-annotations 和jackson-core也会自动下载,因为json-schema-validator传递依赖jackosn-databind包。
<!-- json schema validation -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-schema-validator</artifactId>
<version>4.3.0</version>
</dependency>
ObjectMapper Class:
ObjectMapper类是Jackson API提供的最强大,我们使用最多的。目前我们只知道ObjectMapper提供读写JSON,我们将以后会了解更多功能。
我们将利用ObjectMapper来创建一个JSON Object或则ObjectNode。
我们以一个熟悉的JSON payload开始,我们将用ObjectMapper来创建它。
{
"firstname": "Jim",
"lastname": "Brown",
"totalprice": 111,
"depositpaid": true,
"additionalneeds": "Breakfast",
"bookingdates": {
"checkin": "2021-07-01",
"checkout": "2021-07-01"
}
}
上面的JSON是一个嵌套的JSON Object。一个JSON Object是根节点,包含firstname, lastname, totalprice, depositpaid,additionalneeds字段,和bookingdates 另外一个JSON Object。
创建一个 JSON Object 或Object Node
想要用Jackson创建一个JSON Object,我们需要用ObjectMapper中的createObjectNode() 方法,它将返回一个ObjectNode实例。ObjectNode 类有重写方法put(String fieldName, T fieldValue), field name是String类型,value是可以是基础类型或则是包装类等。field names必须是唯一的。如果传重复的field name,不会抛异常而是覆盖原来的值,这也类似Java中Map的put()方法。
为了将创建的JSON Object转换成String,ObjectMapper类提供**writeValueAsString()方法。如果你想要合适的JSON格式,可以用writeWithDefaultPrettyPrinter()**方法进行格式化。
例如:
// Create an object to ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
// Creating Node that maps to JSON Object structures in JSON content
ObjectNode bookingDetails = objectMapper.createObjectNode();
// It is similar to map put method. put method is overloaded to accept different types of data
// String as field value
bookingDetails.put("firstname", "Jim");
bookingDetails.put("lastname", "Brown");
// integer as field value
bookingDetails.put("totalprice", 111);
// boolean as field value
bookingDetails.put("depositpaid", true);
bookingDetails.put("additionalneeds", "Breakfast");
// Duplicate field name. Will override value
bookingDetails.put("additionalneeds", "Lunch");
// To print created json object
String createdPlainJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("Created plain JSON Object is : \n"+ createdPlainJsonObject);
输出:
Created plain JSON Object is :
{
"firstname" : "Jim",
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch"
}
创键一个嵌套的JSON Object 或Object Node
为了创建嵌套的JSON Object或者将另外一个JSON Object作为一个字段的值,我们使用set(String fieldName, JsonNode fieldValue) 或 replace(String fieldName, JsonNode fieldValue),注意不要使用put(String fieldName, JsonNode fieldValue),这个方法已经被废弃了
。
例如:
// Since requirement is to create a nested JSON Object
ObjectNode bookingDateDetails = objectMapper.createObjectNode();
bookingDateDetails.put("checkin", "2021-07-01");
bookingDateDetails.put("checkout", "2021-07-01");
// Since 2.4 , put(String fieldName, JsonNode value) is deprecated. So use either set(String fieldName, JsonNode value) or replace(String fieldName, JsonNode value)
bookingDetails.set("bookingdates", bookingDateDetails);
// To get the created json object as string. Use writerWithDefaultPrettyPrinter() for proper formatting
String createdNestedJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("Created nested JSON Object is : \n"+ createdNestedJsonObject);
输出:
Created nested JSON Object is :
{
"firstname" : "Jim",
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch",
"bookingdates" : {
"checkin" : "2021-07-01",
"checkout" : "2021-07-01"
}
}
我们将看到一些非常有用的解析JSON Object的处理方法。我们可以用这些方法做一些验证。
从JSON Object或ObjectNode中获取字段值
为了获取字段值,我们需要用get(String fieldName),返回一个JsonNode,如果传入的field name没有vlaue或则是不存在这个field name,将返回null。为了获取value的真实数据类型,我们可以用像asText()和asBoolean()方法分别得到String和boolean类型的值。注意小心当value是另外一个ObjectNode。
代码:
// We can retrieve field value by passing field name. Since it is string, use asText().
String firstName = bookingDetails.get("firstname").asText();
System.out.println("First name is : "+firstName);
// We can use asText() as well but return type will be string
boolean depositpaid = bookingDetails.get("depositpaid").asBoolean();
System.out.println("deposit paid is : "+depositpaid);
// To retrieve value of nested ObjectNode
bookingDetails.get("bookingdates").get("checkin").asText();
System.out.println("Checkin date is : "+depositpaid);
输出:
First name is : Jim
deposit paid is : true
Checkin date is : true
获取JSON Object或Object所有字段名
为了获取所有字段名,我们需要用fieldNames()方法,它将返回一个 Iteraltor< String > 想要获取ObjectNode字段个数,可以用**size()**方法。
代码:
// To get all field names
System.out.println("Count of fields in ObjectNode : "+ bookingDetails.size());
Iterator<String> allFieldNames = bookingDetails.fieldNames();
System.out.println("Fields are : ");
while(allFieldNames.hasNext())
{
System.out.println(allFieldNames.next());
}
输出:
Count of fields in ObjectNode : 6
Fields are :
firstname
lastname
totalprice
depositpaid
additionalneeds
bookingdates
获取JSON Object或ObjectNode中所有的字段值
为了获取ObjectNode中所有values,用elements() 方法,返回JsonNode的一个Iterator。
例如:
// To get all field values
Iterator<JsonNode> allFieldValues = bookingDetails.elements();
System.out.println("Fields values are : ");
while(allFieldValues.hasNext())
{
System.out.println(allFieldValues.next());
}
输出:
Fields values are :
"Jim"
"Brown"
111
true
"Lunch"
{"checkin":"2021-07-01","checkout":"2021-07-01"}
获取JSON Object或ObjectNode所有的key-value键值对
用fields() 方法获取一个JSON Object所有的字段(包括名字和值),它返回一个 Iterator < Entry < String, JsonNode > >
例如:
// To get all key-value pair
Iterator<Entry<String, JsonNode>> allFieldsAndValues = bookingDetails.fields();
System.out.println("All fields and their values are : ");
while(allFieldsAndValues.hasNext())
{
Entry<String, JsonNode> node = allFieldsAndValues.next();
System.out.println("Key is : "+node.getKey()+" and its value is : "+node.getValue());
}
输出:
All fields and their values are :
Key is : firstname and its value is : "Jim"
Key is : lastname and its value is : "Brown"
Key is : totalprice and its value is : 111
Key is : depositpaid and its value is : true
Key is : additionalneeds and its value is : "Lunch"
Key is : bookingdates and its value is : {"checkin":"2021-07-01","checkout":"2021-07
移除JSON Object或ObjectNode的一个字段
用 remove(String fieldName) 方法来移除ObjectNode中的一个字段。如果字段存在,将返回这个字段的value,否则返回null
例如:
// To remove a field
String removedFieldValue = bookingDetails.remove("firstname").asText();
System.out.println("Value of Removed field is " + removedFieldValue);
String removedJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("After removing field , JSON Object is : \n"+ removedJsonObject);
输出:
Value of Removed field is Jim
After removing field , JSON Object is :
{
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch",
"bookingdates" : {
"checkin" : "2021-07-01",
"checkout" : "2021-07-01"
}
}
更新JSON Object或ObjectNode的一个字段
如果这个字段value不是一个ObjectNode,用put() 方法来更新一个字段的value,如果这个字段的value是ObjectNode,用set() 或replace() 方法。
例如:
// To replace a field value, use put() method for non ObjectNode type and replace() or set() for ObjectNode
bookingDetails.put("firstname", "Amod");
bookingDetails.put("firstname", "Aaditya");
String updatedJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("After updating field , JSON Object is : \n"+ updatedJsonO
输出:
After updating field , JSON Object is :
{
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch",
"bookingdates" : {
"checkin" : "2021-07-01",
"checkout" : "2021-07-01"
},
"firstname" : "Aaditya"
}
完整代码
import java.util.Iterator;
import java.util.Map.Entry;
import org.testng.annotations.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
public class CreateJsonObjectUsingJacksonAPI {
@Test
public void CreatingNestedJsonObjectTest() throws JsonProcessingException
{
// Create an object to ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
// Creating Node that maps to JSON Object structures in JSON content
ObjectNode bookingDetails = objectMapper.createObjectNode();
// It is similar to map put method. put method is overloaded to accept different types of data
// String as field value
bookingDetails.put("firstname", "Jim");
bookingDetails.put("lastname", "Brown");
// integer as field value
bookingDetails.put("totalprice", 111);
// boolean as field value
bookingDetails.put("depositpaid", true);
bookingDetails.put("additionalneeds", "Breakfast");
// Duplicate field name. Will override value
bookingDetails.put("additionalneeds", "Lunch");
// To print created json object
String createdPlainJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("Created plain JSON Object is : \n"+ createdPlainJsonObject);
// Since requirement is to create a nested JSON Object
ObjectNode bookingDateDetails = objectMapper.createObjectNode();
bookingDateDetails.put("checkin", "2021-07-01");
bookingDateDetails.put("checkout", "2021-07-01");
// Since 2.4 , put(String fieldName, JsonNode value) is deprecated. So use either set(String fieldName, JsonNode value) or replace(String fieldName, JsonNode value)
bookingDetails.set("bookingdates", bookingDateDetails);
// To get the created json object as string. Use writerWithDefaultPrettyPrinter() for proper formatting
String createdNestedJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("Created nested JSON Object is : \n"+ createdNestedJsonObject);
// We can retrieve field value by passing field name. Since it is string, use asText().
String firstName = bookingDetails.get("firstname").asText();
System.out.println("First name is : "+firstName);
// We can use asText() as well but return type will be string
boolean depositpaid = bookingDetails.get("depositpaid").asBoolean();
System.out.println("deposit paid is : "+depositpaid);
// To retrieve value of nested ObjectNode
bookingDetails.get("bookingdates").get("checkin").asText();
System.out.println("Checkin date is : "+depositpaid);
// To get all field names
System.out.println("Count of fields in ObjectNode : "+ bookingDetails.size());
Iterator<String> allFieldNames = bookingDetails.fieldNames();
System.out.println("Fields are : ");
while(allFieldNames.hasNext())
{
System.out.println(allFieldNames.next());
}
// To get all field values
Iterator<JsonNode> allFieldValues = bookingDetails.elements();
System.out.println("Fields values are : ");
while(allFieldValues.hasNext())
{
System.out.println(allFieldValues.next());
}
// To get all key-value pair
Iterator<Entry<String, JsonNode>> allFieldsAndValues = bookingDetails.fields();
System.out.println("All fields and their values are : ");
while(allFieldsAndValues.hasNext())
{
Entry<String, JsonNode> node = allFieldsAndValues.next();
System.out.println("Key is : "+node.getKey()+" and its value is : "+node.getValue());
}
// To remove a field
String removedFieldValue = bookingDetails.remove("firstname").asText();
System.out.println("Value of Removed field is " + removedFieldValue);
String removedJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("After removing field , JSON Object is : \n"+ removedJsonObject);
// To replace a field value, use put() method for non ObjectNode type and replace() or set() for ObjectNode
bookingDetails.put("firstname", "Amod");
bookingDetails.put("firstname", "Aaditya");
String updatedJsonObject = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bookingDetails);
System.out.println("After updating field , JSON Object is : \n"+ updatedJsonObject);
}
}
输出:
Created plain JSON Object is :
{
"firstname" : "Jim",
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch"
}
Created nested JSON Object is :
{
"firstname" : "Jim",
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch",
"bookingdates" : {
"checkin" : "2021-07-01",
"checkout" : "2021-07-01"
}
}
First name is : Jim
deposit paid is : true
Checkin date is : true
Count of fields in ObjectNode : 6
Fields are :
firstname
lastname
totalprice
depositpaid
additionalneeds
bookingdates
Fields values are :
"Jim"
"Brown"
111
true
"Lunch"
{"checkin":"2021-07-01","checkout":"2021-07-01"}
All fields and their values are :
Key is : firstname and its value is : "Jim"
Key is : lastname and its value is : "Brown"
Key is : totalprice and its value is : 111
Key is : depositpaid and its value is : true
Key is : additionalneeds and its value is : "Lunch"
Key is : bookingdates and its value is : {"checkin":"2021-07-01","checkout":"2021-07-01"}
Value of Removed field is Jim
After removing field , JSON Object is :
{
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch",
"bookingdates" : {
"checkin" : "2021-07-01",
"checkout" : "2021-07-01"
}
}
After updating field , JSON Object is :
{
"lastname" : "Brown",
"totalprice" : 111,
"depositpaid" : true,
"additionalneeds" : "Lunch",
"bookingdates" : {
"checkin" : "2021-07-01",
"checkout" : "2021-07-01"
},
"firstname" : "Aaditya"
}