@@ -181,7 +181,7 @@ else if (actualCount.get(o) != expectedCount.get(o)) {
181181 }
182182 else if (allJSONObjects (expected )) {
183183 String uniqueKey = findUniqueKey (expected );
184- if (uniqueKey == null ) {
184+ if (uniqueKey == null || ! isUsableAsUniqueKey ( uniqueKey , actual ) ) {
185185 // An expensive last resort
186186 recursivelyCompareJSONArray (key , expected , actual , mode , result );
187187 return ;
@@ -268,31 +268,37 @@ private static String findUniqueKey(JSONArray expected) throws JSONException {
268268 // Find a unique key for the object (id, name, whatever)
269269 JSONObject o = (JSONObject )expected .get (0 ); // There's at least one at this point
270270 for (String candidate : getKeys (o )) {
271- Object candidateValue = o .get (candidate );
272- if (isSimpleValue (candidateValue )) {
273- Set <Object > seenValues = new HashSet <Object >();
274- seenValues .add (candidateValue );
275- boolean isUsableKey = true ;
276- for (int i = 1 ; i < expected .length () ; ++i ) {
277- JSONObject other = (JSONObject )expected .get (i );
278- if (!other .has (candidate )) {
279- isUsableKey = false ;
280- break ;
281- }
282- Object comparisonValue = other .get (candidate );
283- if (!isSimpleValue (comparisonValue ) || seenValues .contains (comparisonValue )) {
284- isUsableKey = false ;
285- break ;
271+ if (isUsableAsUniqueKey (candidate , expected )) return candidate ;
272+ }
273+ // No usable unique key :-(
274+ return null ;
275+ }
276+
277+ /**
278+ * {@code candidate} is usable as a unique key if every element in the
279+ * {@code array} is a JSONObject having that key, and no two values are the same.
280+ */
281+ private static boolean isUsableAsUniqueKey (String candidate , JSONArray array ) throws JSONException {
282+ Set <Object > seenValues = new HashSet <Object >();
283+ for (int i = 0 ; i < array .length () ; i ++) {
284+ Object item = array .get (i );
285+ if (item instanceof JSONObject ) {
286+ JSONObject o = (JSONObject ) item ;
287+ if (o .has (candidate )) {
288+ Object value = o .get (candidate );
289+ if (isSimpleValue (value ) && !seenValues .contains (value )) {
290+ seenValues .add (value );
291+ } else {
292+ return false ;
286293 }
287- seenValues .add (comparisonValue );
288- }
289- if (isUsableKey ) {
290- return candidate ;
294+ } else {
295+ return false ;
291296 }
297+ } else {
298+ return false ;
292299 }
293300 }
294- // No usable unique key :-(
295- return null ;
301+ return true ;
296302 }
297303
298304 private static List <Object > jsonArrayToList (JSONArray expected ) throws JSONException {
0 commit comments