top of page

Welcome
to NumpyNinja Blogs

NumpyNinja: Blogs. Demystifying Tech,

One Blog at a Time.
Millions of views. 

Clean API Automation: Leveraging POJOs for Dynamic JSON Payloads in RestAssured

Jun 6
5 min read

In the world of API testing, handling dynamic request payloads and responses might be the most challenging part. As application scale, managing complex JSON payloads can quickly become messy. 


Hardcoded JSON strings inside your automation scripts lack flexibility, are error-prone and become difficult to maintain as the framework grows.

If you are still building your JSON payloads using hardcoded strings, you are losing a battle against the framework scalability.

//Hardcoded JSON (Hard to understand)
String info = "{\"programName\":\"Java\",
\"programDescription\":\"Core Java\",
\"status\":\"Active}";

This approach lacks flexibility and is incredibly difficult to maintain.Let's look at a cleaner and more powerful approach using POJO (Plain Old Java Objects) and Jackson. which are considered as the secret weapon for clean and maintainable API automation.


What is POJO?


A POJO (Plain Old Java Object) is a simple Java class used to represent structured data. In API automation, POJOs are commonly used to map JSON request and response payloads to Java objects. This class contains all the keys as nodes and provides getters and setters to add the abstraction layer.

//Using POJO : Structured and readable

ProgramRequest programRequest = new ProgramRequest();
programRequest.setProgramName(“CoreJava”);
programRequest.setProgramDescription(“Basic”);
programRequest.setProgramStatus(“Active”);

Advantages of the POJO Design Pattern

  • Seamless Conversions

  • Enhance Code Readability

  • High Reusability


The Mapping Engine: Jackson’s ObjectMapper


The Jackson ObjectMapper is the engine behind the POJO approach. It handles the critical mapping transition across your framework using two automated workflows:

  1. Serialization is the process of converting a Java Object into JSON string.

  2. Deserialization is the process of converting a JSON string back into a java Object.


To integrate this seamlessly within a Maven automation project, ensure you have added the required Jackson API dependency in your pom.xml file.

<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>2.17.0</version>
</dependency>

From JSON to POJO : A Practical Example

Lets inspect a JSON sample

{
“programName” : “Java”,
“programDescription” : “Advanced Batch. Should have a knowledge of basic java”,
“programStatus” : “Active”
}

Here in the above data, the keys are programName, programDescription and programStatus. To represent this data in our automation framework, we map each JSON key to a Java variable with its corresponding data type:

The POJO class contains all the keys as nodes and provides getters and setters to add the abstraction layer.


Steps to create POJO class of above JSON data


  1. Need to identify variable of POJO class

programName - String

programDescription - String

programStatus - String


  1. Declare variables in class as private so that they cant be manipulated outside the class.

private String programName;

private String programName;

     private String programDescription;

     private String programStatus;


  1. Add getter and setter method to retrieve and set the value for each variables 

Here is our completed POJO class implementation

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class ProgramRequest {
	private String programName;
	private String programDescription;
	private String programStatus;

	public String getProgramName() {
       return programName;
   	}
	public void setProgramName(String programName) {
		this.programName = programName;
	}
	public String getProgramDescription() {
  		return programDescription;
	}
 	public void setProgramDescription(String programDescription) {
		this.programDescription = programDescription;
	}
	public String getProgramStatus() {
		return programStatus;
	}
 	public void setProgramStatus(String programStatus) {
 		this.programStatus = programStatus;
	}
}

Here we created the object representation of the json data. And now from any page, we can create the object of this class and we can convert that object to json data and the json data can be converted into java object which we call serialisation and deserialisation.


Framework Pro-Tip: Adding @JsonIgnoreProperties(ignoreUnknown = true) at the class Level is an industry best practice. If your application backend changes unexpectedly and returns additional nodes in the payload, Jackson will gracefully skip them instead of throwing an execution error.


Implementing Basic Serialization


Once the blueprint data is defined, you can now easily initialize instances of the object directly inside your step definition file to convert the objects to JSON strings.

import com.fasterxml.jackson.databind.ObjectMapper;

import io.cucumber.java.en.*;
Public class ProgramSteps{
Private final ObjectMapper mapper = new ObjectMapper();

@Given(“Admin creates POST request for program using {string}”)
public void create_program_request(String key) {
ProgramRequest request = new ProgramRequest();

request.setProgramName(“Java”);
request.setProgramDescription(“Advanced Java. Should have completed Basic Java course”);
request.setProgramStatus(“Active”);

// Convert the ProgramRequest class to json payload as string
String programRequestJson = mapper.writeValueAsString(request)
//This ‘programRequestJson’ string can now be passed directly to RestAssured’s body
}
}

While initializing values manually via set method works well for a standalone validations, robust test suites require assertions against multiple data variations(e.g. Empty validations, negative tests).


Going Dynamic: Decoupling and Externalizing Test Data


To prevent step definition file from becoming cluttered with repetitive setters, we can decouple our test to separate test data(like program.json file) stored in your src/test/resources directory.

//program.json
{
 "validProgram": {
   "programName": "Java",
   "programDescription": "Should have Basic Java knowledge",
   "programStatus": "Active"
 },
 "MissingProgramName": {
   "programName": "",
   "programDescription": "API1 Automation",
   "programStatus": "Active"
 },
 "InActiveProgram": {
   "programName": "Biology",
   "programDescription": "API Automation",
   "programStatus": "InActive"
 },
 "MissingProgramStatus": {
   "programName": "SeleniumJava",
   "programDescription": "API1 Automation",
   "programStatus": ""
 }
}

To read test data in an organized way, we create a TestDataReader utility that handles all the work of fetching data from files. Rather than cluttering your step definitions with boilerplate file readers, you can extract a clean node structure using a simple line of code, leaving the TestDataReader in utility to manage the file interaction tasks behind the scenes.


For example, rather than doing this everywhere:

JsonNode node = mapper.readTree(file);

You can do:

JsonNode node = TestDataReader.getTestData(“program”,”validProgram”)

This keeps the test code clean as the TestDataReader handles all the data-reading logic behind the scene.

public class ProgramSteps {
private Response response;
private final TestContext context;
private final ObjectMapper mapper = new ObjectMapper();
public ProgramSteps(TestContext context) {
  this.context = context;
}
ProgramRequest request;

@Given("Admin creates POST request for program using {string}")
	public void create_program_request(String key) {
	JsonNode node = TestDataReader.getTestData("program", key);
	request = mapper.convertValue(node, ProgramRequest.class);
	}
}

Behind the Scenes: The Data Flow Explained


If you look closely at the code above, you might wonder: “Where is the serialization happening if we only see the mapper converting JSON into a Java object?” The answer is that two conversion processes take place behind the scenes: deserialization and serialization.


1. The Deserialization Phase (Our Code)


First, the TestDataReader reads data from the JSON file and returns it as a JsonNode. Internally, this is done using Jackson's readTree() method.

Then, mapper.convertValue(node, ProgramRequest.class) converts the JsonNode into the ProgramRequest POJO. At this point, the JSON test data has been converted into a Java object or ProgramRequest object that can be used throughout the framework.


2. The Serialization Phase (RestAssured's Code)


You don't need to write a second mapper line to convert your POJO back into a JSON string for the API. When you pass your populated POJO object straight into RestAssured's body method:

//Java
RestAssured.given()
   .contentType("application/json")
   .body(request) // <--- RestAssured handles serialization here!

RestAssured automatically calls Jackson under the hood, serializes your Java object back into a clean JSON string, and transmits it over the network to the endpoint.


Conclusion


By leveraging POJOs, Jackson and external test data, you can build API automation frameworks that are cleaner and more maintainable. Keeping test data from test code makes the framework easier to reuse. Serialization and deserialization automatically convert data between Java objects and JSON strings, making the code cleaner and simpler.


 
 

+1 (302) 200-8320

NumPy_Ninja_Logo (1).png

Numpy Ninja Inc. 8 The Grn Ste A Dover, DE 19901

© Copyright 2025 by Numpy Ninja Inc.

  • Twitter
  • LinkedIn
bottom of page