Introduction
In our previous post, we explored Data-Driven Testing in REST Assured, learning how to run tests with multiple data sets. Now, we’ll dive into Serialization and Deserialization, key concepts for converting Java objects to JSON (serialization) and JSON to Java objects (deserialization) in API testing. This guide is designed for beginners and experienced developers, providing clear explanations and practical examples to master these processes in REST Assured.
Key Point: Serialization and deserialization simplify API testing by allowing you to work with Java objects instead of raw JSON, improving code readability and reducing errors.
What are Serialization and Deserialization?
Serialization is the process of converting a Java object into a format like JSON or XML to send as an API request body. For example, converting a Java User
object to a JSON payload for a POST request.
Deserialization is the reverse process, converting a JSON or XML response into a Java object for easier validation or processing. For instance, parsing a JSON response into a User
object to check its fields.
REST Assured leverages libraries like Jackson or Gson for serialization and deserialization, making it seamless to work with Java objects in API tests.
Setting Up Serialization and Deserialization
To enable serialization and deserialization, include a JSON processing library like Jackson in your project. We’ll use the public API https://jsonplaceholder.typicode.com
for examples.
Ensure your pom.xml
includes the necessary dependencies:
io.rest-assured
rest-assured
5.4.0
test
org.junit.jupiter
junit-jupiter
5.10.2
test
org.hamcrest
hamcrest
2.2
test
com.fasterxml.jackson.core
jackson-databind
2.15.2
test
Jackson’s jackson-databind
library handles JSON serialization and deserialization automatically in REST Assured.
Serialization: Converting Java Objects to JSON
Serialization allows you to send a Java object as a JSON request body, reducing manual JSON string creation.
Example: Serializing a Java Object for a POST Request
Create a Java class and use it as the request body for a POST request.
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
// Java class for serialization
class Post {
private String title;
private String body;
private int userId;
// Constructor
public Post(String title, String body, int userId) {
this.title = title;
this.body = body;
this.userId = userId;
}
// Getters and setters
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
}
public class SerializationTest {
@Test
public void testSerializePost() {
RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
Post post = new Post("Test Post", "This is a test post", 1);
given()
.contentType("application/json")
.body(post)
.when()
.post("/posts")
.then()
.statusCode(201)
.body("title", equalTo("Test Post"))
.body("userId", equalTo(1));
}
}
Explanation:
Post
: A Java class representing the JSON structure with fieldstitle
,body
, anduserId
.body(post)
: REST Assured uses Jackson to serialize thePost
object to JSON.contentType("application/json")
: Ensures the request body is sent as JSON.- The test validates the response to confirm the serialized data was sent correctly.
Important: Ensure the Java class fields match the API’s expected JSON structure, including field names and data types, to avoid serialization errors.
Deserialization: Converting JSON to Java Objects
Deserialization converts a JSON response into a Java object, allowing you to access its fields programmatically.
Example: Deserializing a GET Response
Use the same Post
class to deserialize a GET response.
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.junit.jupiter.api.Assertions.*;
// Java class for deserialization (same as above)
class Post {
private int id;
private String title;
private String body;
private int userId;
// Getters and setters
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
}
public class DeserializationTest {
@Test
public void testDeserializeGet() {
RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
Response response = given()
.when()
.get("/posts/1")
.then()
.statusCode(200)
.extract().response();
Post post = response.as(Post.class);
// Validate deserialized object
assertEquals(1, post.getId());
assertEquals(1, post.getUserId());
assertNotNull(post.getTitle());
assertNotNull(post.getBody());
System.out.println("Post Title: " + post.getTitle());
}
}
Explanation:
response.as(Post.class)
: Deserializes the JSON response into aPost
object using Jackson.assertEquals
: Validates the deserialized object’s fields.Post
class now includes anid
field to match the response JSON structure.
Pro Tip: Deserialization makes response validation more robust by allowing you to use Java’s type safety and object-oriented features.
Combining Serialization and Deserialization
Combine both processes in a single test to create and retrieve a resource.
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.junit.jupiter.api.Assertions.*;
// Java class for serialization and deserialization
class Post {
private int id;
private String title;
private String body;
private int userId;
// Constructor for serialization
public Post(String title, String body, int userId) {
this.title = title;
this.body = body;
this.userId = userId;
}
// Getters and setters
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
}
public class SerializeDeserializeTest {
@Test
public void testSerializeAndDeserialize() {
RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
// Serialization: Create a post
Post postToCreate = new Post("Test Post", "Test Body", 1);
Post createdPost = given()
.contentType("application/json")
.body(postToCreate)
.when()
.post("/posts")
.then()
.statusCode(201)
.extract().as(Post.class);
// Validate deserialized response
assertEquals("Test Post", createdPost.getTitle());
assertEquals(1, createdPost.getUserId());
assertNotNull(createdPost.getId());
// Deserialization: Retrieve and validate the same post
Post retrievedPost = given()
.pathParam("postId", createdPost.getId())
.when()
.get("/posts/{postId}")
.then()
.statusCode(200)
.extract().as(Post.class);
assertEquals(createdPost.getTitle(), retrievedPost.getTitle());
}
}
Explanation:
body(postToCreate)
: Serializes thePost
object for the POST request.extract().as(Post.class)
: Deserializes the response into aPost
object.- The test creates a post, validates the response, retrieves it, and confirms consistency.
Using Request Specification
Use a Request Specification to centralize common settings for serialization and deserialization tests.
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.junit.jupiter.api.Assertions.*;
// Java class (same as above)
class Post {
private int id;
private String title;
private String body;
private int userId;
public Post(String title, String body, int userId) {
this.title = title;
this.body = body;
this.userId = userId;
}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
}
public class SpecSerializationTest {
private static RequestSpecification requestSpec;
@BeforeAll
public static void setup() {
requestSpec = new RequestSpecBuilder()
.setBaseUri("https://jsonplaceholder.typicode.com")
.setContentType("application/json")
.addHeader("Accept", "application/json")
.build();
}
@Test
public void testSerializeWithSpec() {
Post post = new Post("Test Post", "Test Body", 1);
Post createdPost = given()
.spec(requestSpec)
.body(post)
.when()
.post("/posts")
.then()
.statusCode(201)
.extract().as(Post.class);
assertEquals("Test Post", createdPost.getTitle());
assertEquals(1, createdPost.getUserId());
}
}
Explanation:
requestSpec
: Sets the base URI, content type, and accept header.spec(requestSpec)
: Applies the specification for consistent serialization.
Pro Tip: Use Request Specifications to streamline serialization and deserialization tests, ensuring consistent headers and settings.
Tips for Beginners
- Match Class Structure: Ensure Java class fields match the JSON structure exactly, including names and types.
- Use Annotations: For complex JSON mappings, use Jackson annotations like
@JsonProperty
to map JSON fields to Java fields with different names. - Validate Responses: Always validate deserialized objects to ensure correct data mapping.
- Enable Logging: Use
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails()
to debug serialization or deserialization issues.
Troubleshooting Tip: If serialization/deserialization fails, check for mismatched field names, missing getters/setters, or incorrect data types. Use logging to inspect the JSON payload and response.
What’s Next?
In the next post, we’ll cover File Upload and Download, exploring how to handle file operations in REST Assured for API testing. Stay tuned for more hands-on examples!