Core Java

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 or List of JSONObject).
  • Sort the collection.
  • Assert each individual object via JsonAssert or assert with Arrays.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 and terryJsonInDiffOrder JSON Object strings have the same content but the elements are ordered differently.
  • Line 10 and 11: the actualJsonArray and expectedJsonArray 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 a JsonNode[], then assert the sorted array via java.util.Arrays.equals and java.util.Arrays.deepEquals methods.
  • test_readValue_listMap – parse the JSON string as List<Map>, then assert sorted lists via org.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 both actualJsonArray and expectedJsonArray are defined in step 3.
  • Line 43, 44: sort the JsonNode array with Arrays.sort method.
  • Line 47, 48: assert the JsonNode array with Arrays.equals and Arrays.deepEquals methods.
  • Line 54, 58: parse the JSON string as List of Map for actualJsonArray and expectedJsonArray are defined in step 3.
  • Line 62: sort the expectedListMap based on the id field.
  • Line 65: assert a collection of JSON actualListMap and sortedExpected 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 of JSONObjects.
  • Line 46, 47: assert each JSONObject equality within the list.

5. Run Tests

Run the Junit and capture the output as Figure 1.

json array equality ignore order tests
Figure 1. Junit Test Results

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.

Download
You can download the full source code of this example here: Assert Collection of JSON Objects Ignoring Order Example

Mary Zheng

Mary graduated from the Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She worked as a lead Software Engineer where she led and worked with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button