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.