Assert Collection of JSON Objects Ignoring Order Example
1. Introduction
JavaScript Object Notation (JSON) is a text-based format for storing and transporting data. In this example, I will demonstrate JSON array equality ignore order with both Jackson and JsonAssert libraries with the following steps:
- Parse the JSON array into a collection of objects (
JsonNode
orList
ofJSONObject
). - Sort the collection.
- Assert each individual object via
JsonAssert
or assert withArrays.equals
method.
2. Setup
In this step, I will create a maven project with jsonassert, jackson-databind, and Junit5 libraries.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.zheng.demo</groupId> <artifactId>assertJsonCollection</artifactId> <version>0.0.1-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>17</release> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.11.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.11.3</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.18.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.skyscreamer/jsonassert --> <dependency> <groupId>org.skyscreamer</groupId> <artifactId>jsonassert</artifactId> <version>1.5.3</version> <scope>test</scope> </dependency> </dependencies> </project>
3. Test JSON Data
In this step, I will create a TestJsonData.java
class that includes several JSON strings. Please note that the actualJsonArray
and expectedJsonArray
have the same collection of objects. The only difference is the JSON element’s order.
TestJsonData.java
package org.zheng.demo.assertJsonCollection; public class TestJsonData { protected String maryJson = "{\"id\":1,\"name\":\"Mary\"}"; protected String terryJson = "{\"id\":2,\"name\":\"Terry\"}"; protected String terryJsonInDiffOrder = "{ \"name\":\"Terry\",\"id\":2}"; protected String actualJsonArray = "[" + maryJson + "," + terryJson + "]"; protected String expectedJsonArray = "[" + terryJsonInDiffOrder + "," + maryJson + "]"; public TestJsonData() { super(); } }
- Line 7 and 8: The
terryJson
andterryJsonInDiffOrder
JSON Object strings have the same content but the elements are ordered differently. - Line 10 and 11: the
actualJsonArray
andexpectedJsonArray
JSON Array strings have the same content but the elements are ordered differently.
4. JSON Array Equality Ignore Order
4.1 JSON Array Equality Ignore Order via Jackson
In this step, I will create a TestAssertJsonCollectionWithJackson.java
that extends from TestJsonData
and includes two tests: test_readValue_JsonNode
and test_readValue_listMap
.
test_readValue_JsonNode
– parse the JSON string as aJsonNode[]
, then assert the sorted array viajava.util.Arrays.equals
andjava.util.Arrays.deepEquals
methods.test_readValue_listMap
– parse the JSON string asList<Map>
, then assert sorted lists viaorg.junit.jupiter.api.Assertions.assertEquals
method.
TestAssertJsonCollectionWithJackson.java
package org.zheng.demo.assertJsonCollection; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class TestAssertJsonCollectionWithJackson extends TestJsonData { ObjectMapper ob = new ObjectMapper(); private JsonNode[] readJsonNodes(final String jsonArray) { JsonNode[] jsonNodeList = null; try { jsonNodeList = ob.readValue(jsonArray, JsonNode[].class); } catch (JsonProcessingException e) { e.printStackTrace(); } return jsonNodeList; } @Test void test_readValue_JsonNode() { // parse JSON into Jackson'sJsonNode JsonNode[] actualJsonNodes = readJsonNodes(actualJsonArray); JsonNode[] expectedJsonNodes = readJsonNodes(expectedJsonArray); // sort the JsonNode array Arrays.sort(actualJsonNodes, Comparator.comparingInt(jNode -> jNode.get("id").asInt())); Arrays.sort(expectedJsonNodes, Comparator.comparingInt(jNode -> jNode.get("id").asInt())); // compare the JsonNode array without any order assertTrue(Arrays.equals(actualJsonNodes, expectedJsonNodes)); assertTrue(Arrays.deepEquals(actualJsonNodes, expectedJsonNodes)); } @Test void test_readValue_listMap() throws JsonMappingException, JsonProcessingException { List<Map<String, Object>> actualListMap = ob.readValue(actualJsonArray, new TypeReference<List<Map<String, Object>>>() { }); List<Map<String, Object>> expectedListMap = ob.readValue(expectedJsonArray, new TypeReference<List<Map<String, Object>>>() { }); List<Map<String, Object>> sortedExpected = expectedListMap.stream() .sorted(Comparator.comparing(map -> (Integer) map.get("id"))).toList(); assertEquals(actualListMap, sortedExpected); } }
- Line 39, 40: parse the JSON string as
JsonNode
array for bothactualJsonArray
andexpectedJsonArray
are defined in step 3. - Line 43, 44: sort the
JsonNode
array withArrays.sort
method. - Line 47, 48: assert the
JsonNode
array withArrays.equals
andArrays.deepEquals
methods. - Line 54, 58: parse the JSON string as
List
ofMap
foractualJsonArray
andexpectedJsonArray
are defined in step 3. - Line 62: sort the
expectedListMap
based on theid
field. - Line 65: assert a collection of JSON
actualListMap
andsortedExpected
are equal.
4.2 JSON Array Equality Ignore Order via JsonAssert
In this step, I will create a TestAssertJsonCollectionWithJsonAssert.java
test class that asserts a collection of JSON objects ignoring order via JsonAssert
.
TestAssertJsonCollectionWithJsonAssert.java
package org.zheng.demo.assertJsonCollection; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.junit.jupiter.api.Test; import org.skyscreamer.jsonassert.JSONAssert; public class TestAssertJsonCollectionWithJsonAssert extends TestJsonData { private List<JSONObject> jsonArrayToSortedList(final JSONArray jsonArray) throws JSONException { List<JSONObject> sortedList = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { sortedList.add(jsonArray.getJSONObject(i)); } sortedList.sort(Comparator.comparingInt(o -> { try { return o.getInt("id"); } catch (JSONException e) { e.printStackTrace(); } return 0; })); return sortedList; } @Test void test_jsonassert_JSONObject() throws Exception { JSONArray actualArray = new JSONArray(actualJsonArray); JSONArray expectedArray = new JSONArray(expectedJsonArray); List<JSONObject> actualSortedList = jsonArrayToSortedList(actualArray); List<JSONObject> expectedSortedList = jsonArrayToSortedList(expectedArray); assertEquals(actualSortedList.size(), expectedSortedList.size()); for (int i = 0; i < expectedSortedList.size(); i++) { JSONAssert.assertEquals(expectedSortedList.get(i).toString(), actualSortedList.get(i).toString(), true); } } }
- Line 38, 39: create
JSONArray
from the JSON string variable. - Line 41, 42: convert the
JSONArray
into a sorted list ofJSONObjects
. - Line 46, 47: assert each
JSONObject
equality within the list.
5. Run Tests
Run the Junit and capture the output as Figure 1.
6. Conclusion
In this example, I created two test classes that assert a collection of JSON objects ignoring order with both Jackson
and JsonAssert
libraries. Both libraries require parsing the JSON into either an array or a list of Java objects first and then comparing the sorted array or lists.
7. Download
This was an example of a maven project that asserted a collection of JSON objects ignoring order.
You can download the full source code of this example here: Assert Collection of JSON Objects Ignoring Order Example