Skip to content

Commit 85c771b

Browse files
committed
Added support for previously unsupported edge cases:
+ Non-strict checking of arrays of arrays + Non-strict checking of arrays of simple and complex types combined + Non-strict checking of arrays of complex types that have no common identifier
1 parent 810b593 commit 85c771b

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

src/main/java/org/skyscreamer/jsonassert/JSONCompare.java

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,9 @@ else if (actualCount.get(o) != expectedCount.get(o)) {
155155
else if (allJSONObjects(expected)) {
156156
String uniqueKey = findUniqueKey(expected);
157157
if (uniqueKey == null) {
158-
throw new IllegalArgumentException("Non-strict checking of an array of objects without a common simple " +
159-
"field is not supported. ([{id:1,a:3},{id:2,b:4}] is ok, [{dog:\"fido\"},{cat:\"fluffy\"}] is not)");
158+
// An expensive last resort
159+
recursivelyCompareJSONArray(key, expected, actual, mode, result);
160+
return;
160161
}
161162
Map<Object, JSONObject> expectedValueMap = arrayOfJsonObjectToMap(expected, uniqueKey);
162163
Map<Object, JSONObject> actualValueMap = arrayOfJsonObjectToMap(actual, uniqueKey);
@@ -176,11 +177,53 @@ else if (allJSONObjects(expected)) {
176177
}
177178
}
178179
else if (allJSONArrays(expected)) {
179-
throw new IllegalArgumentException("Non-strict checking of arrays of arrays (e.g. [[1,2],[3,4]]) is not supported.");
180+
// An expensive last resort
181+
recursivelyCompareJSONArray(key, expected, actual, mode, result);
182+
return;
180183
}
181184
else {
182-
throw new IllegalArgumentException("A mixture of simple values, objects, and arrays (e.g. [1,2,{a:\"b\"},[]]) " +
183-
"are not supported in non-strict mode.");
185+
// An expensive last resort
186+
recursivelyCompareJSONArray(key, expected, actual, mode, result);
187+
return;
188+
}
189+
}
190+
191+
// This is expensive (O(n^2) -- yuck), but may be the only resort for some cases with loose array ordering, and no
192+
// easy way to uniquely identify each element.
193+
private static void recursivelyCompareJSONArray(String key, JSONArray expected, JSONArray actual,
194+
JSONCompareMode mode, JSONCompareResult result) throws JSONException {
195+
Set<Integer> matched = new HashSet<Integer>();
196+
for(int i = 0 ; i < actual.length() ; ++i) {
197+
Object actualElement = actual.get(i);
198+
boolean matchFound = false;
199+
for(int j = 0 ; j < expected.length() ; ++j) {
200+
if (matched.contains(j) || !actual.get(i).getClass().equals(expected.get(j).getClass())) {
201+
continue;
202+
}
203+
if (actualElement instanceof JSONObject) {
204+
if (compareJSON((JSONObject)actualElement, (JSONObject)expected.get(j), mode).passed()) {
205+
matched.add(j);
206+
matchFound = true;
207+
break;
208+
}
209+
}
210+
else if (actualElement instanceof JSONArray) {
211+
if (compareJSON((JSONArray)actualElement, (JSONArray)expected.get(j), mode).passed()) {
212+
matched.add(j);
213+
matchFound = true;
214+
break;
215+
}
216+
}
217+
else if (actualElement.equals(expected.get(j))) {
218+
matched.add(j);
219+
matchFound = true;
220+
break;
221+
}
222+
}
223+
if (!matchFound) {
224+
result.fail("Could not find match for element " + actualElement);
225+
return;
226+
}
184227
}
185228
}
186229

src/test/java/org/skyscreamer/jsonassert/JSONAssertTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,12 @@ public void testComplexMixedStrictArray() throws JSONException {
8383
testPass("{stuff:[{pet:\"cat\"},{car:\"Ford\"}]}", "{stuff:[{pet:\"cat\"},{car:\"Ford\"}]}", true);
8484
}
8585

86-
@Test(expected = IllegalArgumentException.class)
86+
@Test
8787
public void testComplexMixedArray() throws JSONException {
8888
testPass("{stuff:[{pet:\"cat\"},{car:\"Ford\"}]}", "{stuff:[{pet:\"cat\"},{car:\"Ford\"}]}", false);
8989
}
9090

91-
@Test(expected = IllegalArgumentException.class)
91+
@Test
9292
public void testComplexArrayNoUniqueID() throws JSONException {
9393
testPass("{stuff:[{address:{addr1:\"123 Main\"}}, {address:{addr1:\"234 Broad\"}}]}",
9494
"{stuff:[{address:{addr1:\"123 Main\"}}, {address:{addr1:\"234 Broad\"}}]}",
@@ -100,7 +100,7 @@ public void testSimpleAndComplexStrictArray() throws JSONException {
100100
testPass("{stuff:[123,{a:\"b\"}]}", "{stuff:[123,{a:\"b\"}]}", true);
101101
}
102102

103-
@Test(expected = IllegalArgumentException.class)
103+
@Test
104104
public void testSimpleAndComplexArray() throws JSONException {
105105
testPass("{stuff:[123,{a:\"b\"}]}", "{stuff:[123,{a:\"b\"}]}", false);
106106
}
@@ -130,7 +130,7 @@ public void testArrayOfArraysStrict() throws JSONException {
130130
testFail("{id:1,stuff:[[1,2],[2,3],[3,4],[]]}", "{id:1,stuff:[[1,2],[2,3],[],[3,4]]}", true);
131131
}
132132

133-
@Test(expected = IllegalArgumentException.class)
133+
@Test
134134
public void testArrayOfArrays() throws JSONException {
135135
testPass("{id:1,stuff:[[4,3],[3,2],[],[1,2]]}", "{id:1,stuff:[[1,2],[2,3],[],[3,4]]}", false);
136136
}

0 commit comments

Comments
 (0)