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 –

  1. The key “id” should be an integer value.
  2. 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 –

  1. We will change the “full name” of the first element of the JSON array.
  2. We will call multiple set() methods in a chain
  3. 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.