Replace Value in JSON Using JsonPath in Java | Jayway JsonPath | Rest Assured |
#api #apitesting #java #json #jsonpath #jsonpayload
An API needs to be tested for a different set of payloads or scenarios. Most of the time, we manipulate the basic JSON payload to use for different scenarios.
For example – Suppose we have an API to create an airline with the below payload –
{
"id": 12,
"name": "Sri Lankan Airways",
"country": "Sri Lanka",
"logo": "https://upload.wikimedia.org/wikipedia/en/thumb/9/9b/Qatar_Airways_Logo.svg/sri_lanka.png",
"slogan": "From Sri Lanka",
"head_quaters": "Katunayake, Sri Lanka",
"website": "www.srilankaairways.com",
"established": "1990"
}
We may have multiple scenarios for this API such as –
- The key “id” should be an integer value.
- The key “established” should not be a future year.
We can create two different JSON payloads to handle the above two scenarios. It will be a tedious job when you have multiple scenarios. Instead, we can have a basic JSON payload and replace values of the key/s as per scenarios/requirements.
Jayway JsonPath is a Java library that can help us in achieving discussed above. We can change/replace the value of the existing key using JsonPath in a JSON document easily.
Make sure you add the latest dependency from Maven Central to your Java project. I am using the 2.8.0 version for this post. Basic knowledge of writing JsonPath is required.
Jayway JsonPath provides a method named “set(String jsonPath, T valueToBeReplaced)“. After replacing you can convert the new JSON to string or other formats. We can call the set() method multiple times in a chain. It will replace the values for all keys in case of multiple matching.
We will use below JSON document for the example –
[
{
"full name": "Everett Fritsch",
"address": {
"street": "898 Chesley View",
"city": "Zing"
},
"skills": [
"Maths",
"Science"
]
},
{
"full name": "Stacey Witting",
"address": {
"street": "993 Keebler Summit",
"city": "La Unión"
},
"skills": [
"Java",
"Python"
]
}
]
In the below example –
- We will change the “full name” of the first element of the JSON array.
- We will call multiple set() methods in a chain
- We will replace all the “full name” in the array.
@Test
public void changeValueOfKeyUsingJsonPath() {
// Replace value and converting new JSON to string
jsonObject = JsonPath.parse(jsonObject).set("$[0]['full name']", "Amod Mahajan").jsonString();
System.out.println(jsonObject);
// We can call multiple set methods in chain as below
// $ is optional
jsonObject = JsonPath.parse(jsonObject).set("[0]['full name']", "Amod Mahajan")
.set("[0].address.city", "New York")
.set("[0].skills.[1]", "History")
.jsonString();
System.out.println(jsonObject);
// will replace for all matching keys
jsonObject = JsonPath.parse(jsonObject).set("[*]['full name']", "Amod Mahajan").jsonString();
System.out.println(jsonObject);
}
[{"full name":"Amod Mahajan","address":{"street":"898 Chesley View","city":"Zing"},"skills":["Maths","Science"]},{"full name":"Stacey Witting","address":{"street":"993 Keebler Summit","city":"La Unión"},"skills":["Java","Python"]}]
[{"full name":"Amod Mahajan","address":{"street":"898 Chesley View","city":"New York"},"skills":["Maths","History"]},{"full name":"Stacey Witting","address":{"street":"993 Keebler Summit","city":"La Unión"},"skills":["Java","Python"]}]
[{"full name":"Amod Mahajan","address":{"street":"898 Chesley View","city":"New York"},"skills":["Maths","History"]},{"full name":"Amod Mahajan","address":{"street":"993 Keebler Summit","city":"La Unión"},"skills":["Java","Python"]}]
We can pass any level of nested JSON document as a value to replace a value of key in the set() method. If we have JSON as a Java object (Map in below code) then we can pass that as it is. But if the JSON is as a string then first we need to convert to Java Object using any JSON parser library like Jackson, GSON, or JSON-Simple. I have used Jackson in the below example.
@Test
public void changeToNestedValueOfKeyUsingJsonPath() throws JsonProcessingException {
// We can pass any level of nested JSON document as a value
Map < String, Object > jsonValue = new HashMap < > ();
jsonValue.put("city", "Delhi");
jsonValue.put("zip", "12345");
jsonObject = JsonPath.parse(jsonObject).set("[0].address", jsonValue).jsonString();
System.out.println(jsonObject);
// if we have json value as string then parse it to json before using
// I used Jackson databond here
String newJson = "{\"zip\":\"12345\",\"city\":\"Delhi\"}";
jsonObject = JsonPath.parse(jsonObject).set("[0].address", new ObjectMapper().readValue(newJson, Map.class)).jsonString();
System.out.println(jsonObject);
}
[{"full name":"Everett Fritsch","address":{"zip":"12345","city":"Delhi"},"skills":["Maths","Science"]},{"full name":"Stacey Witting","address":{"street":"993 Keebler Summit","city":"La Unión"},"skills":["Java","Python"]}]
[{"full name":"Everett Fritsch","address":{"zip":"12345","city":"Delhi"},"skills":["Maths","Science"]},{"full name":"Stacey Witting","address":{"street":"993 Keebler Summit","city":"La Unión"},"skills":["Java","Python"]}]
We can pass all types of valid JsonPath to replace the value of the key in JSON. Filter in JsonPath helps to find the exact value. In the below example, I will change the skills set of a person whose full name is “Everett Fritsch”.
@Test
public void changeValueOfFilteredNestedKeyUsingJsonPath() {
jsonObject = JsonPath.parse(jsonObject).set("[0][?(@['full name'] == 'Everett Fritsch')].skills", List.of("Java", "Selenium"))
.jsonString();
System.out.println(jsonObject);
}
[{"full name":"Everett Fritsch","address":{"street":"898 Chesley View","city":"Zing"},"skills":["Java","Selenium"]},{"full name":"Stacey Witting","address":{"street":"993 Keebler Summit","city":"La Unión"},"skills":["Java","Python"]}]
Thanks for reading.
