REST Assured Tutorial 73 – How to ignore node/s for JSON comparison in JSONassert

Introduction

As a part of the End to End REST Assured Tutorial, in this post, we will learn to ignore specific nodes while comparing two JSON documents using the JSONassert library.

We have already learned to Compare two JSON Objects and Compare two JSON Arrays using JSONassert library as a whole.

We may not need to compare all nodes in JSON documents and need to ignore while comparing as a mismatch will fail the comparison. A real-time example might be a timestamp that may not be static and we must ignore those fields from comparison.

Did you know that I have started a YouTube channel as well and I need your support to make it successful. Please do watch content then comment, like, share, and obviously subscribe.

Required Dependency

I have used available below latest dependency of JSONassert. You can always get the latest dependency from Maven central repo.



    org.skyscreamer
    jsonassert
    1.5.0
    test

Prerequisite post

You must go through the below post to understand about JSONassert Java library, different comparing modes, and asserting JSON Objects.

Introduction To JsonAssert Library

Compare JSON Objects Using JSONassert Library

Compare JSON Arrays Using JSONassert Library

How to ignore fields from JSON from comparison?

There is no direct way to ignore fields or attributes from a JSON document from comparison. We need to use CustomComparator and explicitly we need to make an assertion pass. A sample code for achieving the same is below:-

 JSONComparator com = new CustomComparator(JSONCompareMode.LENIENT, 
 new Customization("salary", (o1, o2) -> true)); 

CustomComparator is a class and implements JSONComparator indirectly. Customization is another class. The constructor of CustomComparator takes JSONCompareMode and an array of types of Customization. If we see constructor of class Customization then you will find that it accepts a type of ValueMatcher which is an interface and contains a method equal().

// Constructor of CustomComparator
public CustomComparator(JSONCompareMode mode,  Customization... customizations) {
        super(mode);
        this.customizations = Arrays.asList(customizations);
    }

In the above code snippet, I have used Lambda expressions and anonymous inner class concepts of Java to make code shorter otherwise you may need to write a lot of code.

If you are not aware of Lambda expressions in Java then you should learn them. I see many automation testing professionals avoid them.

To ignore fields from JSON for comparison using JSONassert is nothing but explicitly passing the assertion. If we get value v1 from the first JSON document and value v2 from the second JSON document and v1 may or may not equal to v2 then we need to explicitly mark them equal or something like a proxy.

salary” in the above code snippet is a JSON Path and “o1” and “o2” are values from JSON documents and without any condition, we are returning true. This is the way of ignoring fields from comparison using JSONassert. You may also have some manipulation or condition checks like substring or a format etc.

We can pass multiple Customization references together as I said CustomComparator takes an array of types of Customization.

 JSONComparator com = new CustomComparator(JSONCompareMode.LENIENT, 
 new Customization("salary", (o1, o2) -> true),
 new Customization("age", (o1, o2) -> true)); 

We have overloaded assertEquals() method of JSONAssert class which takes JSONComparator reference.

Ignoring fields in a simple JSON object

JSON String 1

{
  "id": 1,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false,
  "salary": 123.45
}

JSON String 2

{
  "id": 1,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false,
  "salary": 125.45
}

I want to ignore the field “salary” from the comparison. Sample code is below-

Sample Code

 package IgnoringFieldsDuringComparision;

import org.json.JSONException;
import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.comparator.CustomComparator;
import org.skyscreamer.jsonassert.comparator.JSONComparator;

public class IgnoringFieldsFromSimpleJsonObjects {
 
 public static void main(String[] args) throws JSONException {
 
 String s1 = "{\r\n" + 
 "  \"id\": 1,\r\n" + 
 "  \"first_name\": \"Amod\",\r\n" + 
 "  \"last_name\": \"Mahajan\",\r\n" + 
 "  \"married\": false,\r\n" + 
 "  \"salary\": 123.45\r\n" + 
 "}";
 
 String s2 = "{\r\n" + 
 "  \"id\": 1,\r\n" + 
 "  \"first_name\": \"Amod\",\r\n" + 
 "  \"last_name\": \"Mahajan\",\r\n" + 
 "  \"married\": false,\r\n" + 
 "  \"salary\": 125.45\r\n" + 
 "}";
 
 JSONComparator com = new CustomComparator(JSONCompareMode.LENIENT, 
 new Customization("salary", (o1, o2) -> true));
 
 JSONAssert.assertEquals(s1, s2, com);
 
 }

} 

Ignoring fields in a nested JSON object

JSON Object 1

{
  "id": 1,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false,
  "salary": 123.45,
  "address":{
    "permanent" : "KA",
    "city": "Bengaluru"
  }
}

JSON Object 2

{
  "id": 1,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false,
  "salary": 123.45,
  "address":{
    "permanent" : "KA",
    "city": "Katihar"
  }
}

I want to ignore the field “city” which is inside the “address” node from the comparison. We just need to provide a correct JSON path which will be “address.city“. Sample code is below-

Sample Code

 package IgnoringFieldsDuringComparision;

import org.json.JSONException;
import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.comparator.CustomComparator;
import org.skyscreamer.jsonassert.comparator.JSONComparator;

public class IgnoringFieldsFromNestedJsonObjects {
 
 public static void main(String[] args) throws JSONException {
 
 String s1 = "{\r\n" + 
 "  \"id\": 1,\r\n" + 
 "  \"first_name\": \"Amod\",\r\n" + 
 "  \"last_name\": \"Mahajan\",\r\n" + 
 "  \"married\": false,\r\n" + 
 "  \"salary\": 123.45,\r\n" + 
 "  \"address\":{\r\n" + 
 "    \"permanent\" : \"KA\",\r\n" + 
 "    \"city\": \"Bengaluru\"\r\n" + 
 "  }\r\n" + 
 "}";
 
 String s2 = "{\r\n" + 
 "  \"id\": 1,\r\n" + 
 "  \"first_name\": \"Amod\",\r\n" + 
 "  \"last_name\": \"Mahajan\",\r\n" + 
 "  \"married\": false,\r\n" + 
 "  \"salary\": 123.45,\r\n" + 
 "  \"address\":{\r\n" + 
 "    \"permanent\" : \"KA\",\r\n" + 
 "    \"city\": \"Katihar\"\r\n" + 
 "  }\r\n" + 
 "}";
 
 JSONComparator com = new CustomComparator(JSONCompareMode.LENIENT, 
 new Customization("address.city", (o1, o2) -> true));
 
 JSONAssert.assertEquals(s1, s2, com);
 
 }
} 

Ignoring fields in a simple JSON array

JSON Array 1

[{
  "id": 1,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false,
  "salary": 123.45
},
{
  "id": 2,
  "first_name": "Animesh",
  "last_name": "Prashant",
  "married": true,
  "salary": 223.45
}]

JSON Array 2

[{
  "id": 10,
  "first_name": "Amod",
  "last_name": "Mahajan",
  "married": false,
  "salary": 123.45
},
{
  "id": 2,
  "first_name": "Animesh",
  "last_name": "Prashant",
  "married": true,
  "salary": 223.45
}]

Supposed I don’t want to compare “id” for the first indexed JSON Object. So we should give JSON path as “[0].id” but it WILL NOT ignore if we pass JSONCompareMode as LENIENT. For a specific index, we should pass STRICT.

Sample Code

 package IgnoringFieldsDuringComparision;

import org.json.JSONException;
import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.comparator.CustomComparator;
import org.skyscreamer.jsonassert.comparator.JSONComparator;

public class IgnoringFieldsFromSimpleJsonArray {
 
 public static void main(String[] args) throws JSONException {
 
 String s1 = "[{\r\n" + 
 "  \"id\": 1,\r\n" + 
 "  \"first_name\": \"Amod\",\r\n" + 
 "  \"last_name\": \"Mahajan\",\r\n" + 
 "  \"married\": false,\r\n" + 
 "  \"salary\": 123.45\r\n" + 
 "},\r\n" + 
 "{\r\n" + 
 "  \"id\": 2,\r\n" + 
 "  \"first_name\": \"Animesh\",\r\n" + 
 "  \"last_name\": \"Prashant\",\r\n" + 
 "  \"married\": true,\r\n" + 
 "  \"salary\": 223.45\r\n" + 
 "}]";
 
 String s2 = "[{\r\n" + 
 "  \"id\": 10,\r\n" +       
 "  \"first_name\": \"Amod\",\r\n" + 
 "  \"last_name\": \"Mahajan\",\r\n" + 
 "  \"married\": false,\r\n" + 
 "  \"salary\": 123.45\r\n" + 
 "},\r\n" + 
 "{\r\n" + 
 "  \"id\": 2,\r\n" + 
 "  \"first_name\": \"Animesh\",\r\n" + 
 "  \"last_name\": \"Prashant\",\r\n" + 
 "  \"married\": true,\r\n" + 
 "  \"salary\": 223.45\r\n" + 
 "}]";
 
 JSONComparator com = new CustomComparator(JSONCompareMode.STRICT, 
 
 new Customization("[0].id", (o1, o2) -> true));
 
 JSONAssert.assertEquals(s1, s2, com);
 
 }

} 

If we want to ignore “id” for all indexed elements then we should pass the JSON path as “[*].id“. We can use STRICT or LENIENT mode in this case.

Ignoring fields in a nested JSON array

JSON Array 1

[
  {
    "id": 1,
    "first_name": "Amod",
    "last_name": "Mahajan",
    "married": false,
    "salary": 123.45,
    "mob": [
      {
        "type": "personal",
        "number": "1234566"
      },
      {
        "type": "business",
        "number": "987654321"
      }
    ]
  },
  {
    "id": 2,
    "first_name": "Animesh",
    "last_name": "Prashant",
    "married": true,
    "salary": 223.45,
    "mob": [
      {
        "type": "personal",
        "number": "1234566"
      },
      {
        "type": "business",
        "number": "987654321"
      }
    ]
  }
]

JSON Array 2

[
  {
    "id": 1,
    "first_name": "Amod",
    "last_name": "Mahajan",
    "married": false,
    "salary": 123.45,
    "mob": [
      {
        "type": "personal",
        "number": "1234566"
      },
      {
        "type": "business",
        "number": "34545646"
      }
    ]
  },
  {
    "id": 2,
    "first_name": "Animesh",
    "last_name": "Prashant",
    "married": true,
    "salary": 223.45,
    "mob": [
      {
        "type": "personal",
        "number": "1234566"
      },
      {
        "type": "business",
        "number": "987654321"
      }
    ]
  }
]

Suppose I would like to ignore the second mobile number of the first indexed element. We need to use JSON Path as “[0].mob[1].number“.

Sample Code

 package IgnoringFieldsDuringComparision;

import org.json.JSONException;
import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.comparator.CustomComparator;
import org.skyscreamer.jsonassert.comparator.JSONComparator;

public class IgnoringFieldsFromNestedJsonArray {
 
 public static void main(String[] args) throws JSONException {
 
 String s1 = "[\r\n" + 
 "  {\r\n" + 
 "    \"id\": 1,\r\n" + 
 "    \"first_name\": \"Amod\",\r\n" + 
 "    \"last_name\": \"Mahajan\",\r\n" + 
 "    \"married\": false,\r\n" + 
 "    \"salary\": 123.45,\r\n" + 
 "    \"mob\": [\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"personal\",\r\n" + 
 "        \"number\": \"1234566\"\r\n" + 
 "      },\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"business\",\r\n" + 
 "        \"number\": \"987654321\"\r\n" + 
 "      }\r\n" + 
 "    ]\r\n" + 
 "  },\r\n" + 
 "  {\r\n" + 
 "    \"id\": 2,\r\n" + 
 "    \"first_name\": \"Animesh\",\r\n" + 
 "    \"last_name\": \"Prashant\",\r\n" + 
 "    \"married\": true,\r\n" + 
 "    \"salary\": 223.45,\r\n" + 
 "    \"mob\": [\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"personal\",\r\n" + 
 "        \"number\": \"1234566\"\r\n" + 
 "      },\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"business\",\r\n" + 
 "        \"number\": \"987654321\"\r\n" + 
 "      }\r\n" + 
 "    ]\r\n" + 
 "  }\r\n" + 
 "]";
 
 String s2 = "[\r\n" + 
 "  {\r\n" + 
 "    \"id\": 1,\r\n" + 
 "    \"first_name\": \"Amod\",\r\n" + 
 "    \"last_name\": \"Mahajan\",\r\n" + 
 "    \"married\": false,\r\n" + 
 "    \"salary\": 123.45,\r\n" + 
 "    \"mob\": [\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"personal\",\r\n" + 
 "        \"number\": \"1234566\"\r\n" + 
 "      },\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"business\",\r\n" + 
 "        \"number\": \"34545646\"\r\n" + 
 "      }\r\n" + 
 "    ]\r\n" + 
 "  },\r\n" + 
 "  {\r\n" + 
 "    \"id\": 2,\r\n" + 
 "    \"first_name\": \"Animesh\",\r\n" + 
 "    \"last_name\": \"Prashant\",\r\n" + 
 "    \"married\": true,\r\n" + 
 "    \"salary\": 223.45,\r\n" + 
 "    \"mob\": [\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"personal\",\r\n" + 
 "        \"number\": \"1234566\"\r\n" + 
 "      },\r\n" + 
 "      {\r\n" + 
 "        \"type\": \"business\",\r\n" + 
 "        \"number\": \"987654321\"\r\n" + 
 "      }\r\n" + 
 "    ]\r\n" + 
 "  }\r\n" + 
 "]";
 
 System.out.println(s1);
 System.out.println(s2);
 JSONComparator com = new CustomComparator(JSONCompareMode.STRICT, 
 new Customization("[0].mob[1].number", (o1, o2) -> true));
 
 JSONAssert.assertEquals(s1, s2, com);
 
 }

} 

Note – There is a problem with the above approach. Tests will fail if any ignored element is not found in JSON objects to be compared. We will see the solution to that in the next post.

You can clone the git repo consisting above examples from here.

You can subscribe to my YouTube channel RetargetCommon to learn from video tutorials.

If you have any doubt, feel free to comment below.
If you like my posts, please like, comment, share and subscribe.
#ThanksForReading
#HappyLearning

Find all Selenium related posts here, all API manual and automation related posts here, and find frequently asked Java Programs here.

Many other topics you can navigate through the menu.

3 thoughts on “REST Assured Tutorial 73 – How to ignore node/s for JSON comparison in JSONassert”

  1. nice ,suppose

    I have a JSON string Expected:

    {
    “id” : “1234567”
    “balance” : “123”
    }

    and I converted above into JSON object and trying to validate this with output JSON Actual:

    {
    “id” : “1234567”
    “balance” : “123.00”
    }

    when I am using JSONAssert.assertequal(“incorrect json”,actual,expected,false);

    this is failing with following error expected 123 and got 123.00 though both are same from end user perspective.

    I am using JAVA and reading both JSON as String.

    appreciate your help

Leave a Reply

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