'How can I sort JSONArray by multiple criteria using Java?

Imagine you have a JSON file with information about users (including their emails (stored in String), rating (stored in int) etc). Mine looks like this:

{"data": [{"user": "[email protected]", "rating": 3, "disabled": true},
{"user": "[email protected]", "rating": 14, "disabled": false},
{"user": "[email protected]", "rating": 14, "disabled": true},
{"user": "[email protected]", "rating": 25, "disabled": true}]}

The goal is to sort this list by multiple criteria. The sorting criteria are also a part of a JSON file:

{"sort_by": ["rating", "user"]}

In our case the list should be sorted first by rating and then by user names (in case some users have the same rating).

I already created JSONArrays from both lists and managed to sort users by email. My sort() method looks like this:

private void sort() {
        JSONArray sortedJsonArray = new JSONArray();

        List<JSONObject> jsonValues = new ArrayList<>();
        for (int i = 0; i < data.length(); i++) {
            jsonValues.add(data.getJSONObject(i));
        }

        Collections.sort(jsonValues, new Comparator<>() {
            private String key = sort_by_array.get(0).toString();

            @Override
            public int compare(JSONObject a, JSONObject b) {
                String valA = a.get(key).toString();
                String valB = b.get(key).toString();
                return valA.compareTo(valB);
            }
        });

        for (int i = 0; i < data.length(); i++) {
            sortedJsonArray.put(jsonValues.get(i));
        }

        data = sortedJsonArray;
    }

It works for sorting by Email, but doesn't work for sorting by int values, even when I try to turn them into String. Also it obviously doesn't work for sorting by multiple criteria.

What should I change in my code so that it sorts the list correctly at least by one criteria which can be String/Integer or Boolean value? Thank you in advance.



Solution 1:[1]

Implement a comparator class like this:

class KeyComparator implements Comparator<JSONObject> {

    private final String key;

    public KeyComparator(String key) {
        this.key = key;
    }

    @Override
    public int compare(JSONObject o1, JSONObject o2) {
        Comparable v1 = (Comparable) o1.get(key);
        Comparable v2 = (Comparable) o2.get(key);
        return v1.compareTo(v2);
    }
}

Build a composite comparator like this:

Comparator<JSONObject> comparator = new KeyComparator(sort_by_array.get(0).toString());
for (int i = 1; i < sort_by_array.size(); i++) {
    comparator = comparator.thenComparing(new KeyComparator(sort_by_array.get(i).toString()));
}

Then Collections.sort(jsonValues, comparator) should be good to go.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user4851