1

I've got 2 JSONArray full of integers.

I want to compare them for equal content without regard for order.

So:

[1, 2] == [1, 2] TRUE [1, 2] == [2, 1] TRUE

JSONArray has

public boolean equals(Object o) 

but it returns FALSE for [1, 2] == [2, 1]

So, I rolled my own:

public boolean isEqual(JSONArray inputJsonArray, 
                       JSONArray outputJsonArray) throws JSONException{
    boolean equal=true, done;
    int idx = 0;      

    if (inputJsonArray.length() == outputJsonArray.length()){

        //make sure all elements in input array are in output array
        done=false;
        while (!done){
            if(idx >= inputJsonArray.length()){
               done=true;
            }
            else if (isIntInJsonArray(outputJsonArray,
                                      inputJsonArray.getInt(idx)) == false){
                     equal = false;
                     done=true;
            }
            else{
                     idx ++;
            }

        }

        if (equal){

            //make sure all elements in output array are in input array
            done=false;
            while (!done){
                  if (idx >= outputJsonArray.length()){
                       done=true;
                  }
                  else if (isIntInJsonArray(inputJsonArray,
                                         outputJsonArray.getInt(idx)) == false){

                            equal = false;
                            done=true;
                  }
                  else{
                            idx++;
                  }

            }          
        }           
    }
    else{
            equal = false;
    }

    return equal;

}

Basically, I check if both JSONArrays are the same length. If they are then I make sure every element in the outputJsonArray is in the inputJsonArray and vice versa. The workhorse method that does this is:

private boolean isIntInJsonArray(JSONArray inputJsonArray, int mInt) throws JSONException{
    boolean found=false, done=false;
    int idx = 0;

    while (!done){
            if(idx >= inputJsonArray.length()){
               done=true;
            }
            else if (inputJsonArray.getInt(idx) == mInt){
               found = true;
               done=true;
            }
            else{
               idx ++;
            }              
    }

    return(found);
 }   

This strikes me like an awful lot of code. Does anyone know if there is a simpler way to do this?

user1126515
  • 1,133
  • 3
  • 17
  • 34

1 Answers1

0

Convert the arrays to JSONObject then use its equals method.

JSONArray arr1 = new JSONArray();
JSONArray arr2 = new JSONArray();

arr1.put(1);
arr1.put(2);
arr1.put(3);
arr1.put(4);
arr1.put(5);

arr2.put(2);
arr2.put(1);
arr2.put(3);
arr2.put(5);
arr2.put(4);

JSONObject o1 = arr1.toJSONObject(arr1);
JSONObject o2 = arr2.toJSONObject(arr2);

System.out.println(o1.equals(o2)); //true

Looking at the source code of JSONObject, it is using its underlying map to check equality.

@Override
public boolean equals(Object obj) {
   if (obj instanceof JSONObject) {
      return myHashMap.equals(((JSONObject)obj).myHashMap);
   } else {
      return false;
   }
}

The equals implementation of underlying map is disregarding the order of its content

public boolean equals(Object o) {
    if (o == this)
        return true;

    if (!(o instanceof Map))
        return false;
    Map<K,V> m = (Map<K,V>) o;
    if (m.size() != size())
        return false;

    try {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        while (i.hasNext()) {
            Entry<K,V> e = i.next();
            K key = e.getKey();
            V value = e.getValue();
            if (value == null) {
                if (!(m.get(key)==null && m.containsKey(key)))
                    return false;
            } else {
                if (!value.equals(m.get(key)))
                    return false;
            }
        }
    } catch (ClassCastException unused) {
        return false;
    } catch (NullPointerException unused) {
        return false;
    }

    return true;
}
Bnrdo
  • 5,325
  • 3
  • 35
  • 63
  • This doesn't scale for codehaus jettison JSONArrays and JSONObjects that have interior arrays and objects. I ended up using the wink apache project to easily compare objects after the org.json changes in the AWS libs. How does one compare deep JSON objects using the codehaus jettison lib? – John Estess Oct 24 '16 at 04:06