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

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"
    ]
  }
]

Example 1 – Replace the value of a key using JsonPath

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);
}

Output

[{"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"]}]

Example 2 – Replace with nested JSON value for a key using JsonPath

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);
}

Output

[{"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"]}]

Example 3 – Replace with value for a key using JsonPath with a filter condition

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);
}

Output

[{"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.

Leave a Reply

Your email address will not be published. Required fields are marked *