it-roy-ru.com

Android как отсортировать JSONArray из JSONObjects

Я сделал jsonarray из jsonobjects. Теперь мне нужно отсортировать JSONArray на основе значения из jsonobjects. Раньше я сортировал ArrayLists пользовательских объектов следующим образом:

Компараторы:

public class KreeftenComparatorLA implements Comparator<Kreeft> {
    public int compare(Kreeft left, Kreeft right) {
        return left.latijnseNaam.compareTo(right.latijnseNaam);
    }
}
public class KreeftenComparatorNL implements Comparator<Kreeft> {
    public int compare(Kreeft left, Kreeft right) {
        return left.naam.compareTo(right.naam);
    }
}

А потом сортируй arraylist:

Collections.sort(db.lijst, new KreeftenComparatorLA());

или же:

Collections.sort(db.lijst, new KreeftenComparatorNL());

Но когда я пытаюсь сделать то же самое с JSONArray, как это (JA = мой jsonarray)

Collections.sort(JA, new KreeftenComparatorNL());

collections.sort выдает ошибку: 

Метод sort (List, Comparator) в типе Collections не применим для аргументов (JSONArray, ThisActicity.KreeftenComparatorNL)

Кто-нибудь знает, как сортировать JSONArray?

20
Simon

Проблема в том, что JSONArray более или менее содержит JSONObjects (и другие JSONArrays), которые в конечном итоге являются строками. Десериализация строк полностью в POJO, их сортировка, а затем обратно в JSON довольно тяжелая.

Вторая проблема заключается в том, что JSONArray может содержать: Boolean, JSONArray, JSONObject, Number, String или объект JSONObject.NULL; то есть это смешанные типы, что затрудняет просто сбросить элементы в список какого-либо типа и отсортировать их, а затем пройти через список, сбрасывая отсортированные элементы обратно в массив JSON. единственный определенный способ получить общий тип каждого элемента из JSONArray - использовать метод Object get (). Конечно, тогда все, что у вас есть, это объекты Object, и вы не сможете выполнить какую-либо значимую сортировку по ним без повторного рассмотрения проблема сериализации.

Предполагая, что ваш JSONArray содержит однородно структурированные значения, вы можете перебирать JSONArray, вызывая один из типизированных методов get () для каждого, сбрасывая их в тип List, а затем сортируя по нему. Если ваш JSONArray просто содержит «простой» тип, такой как String или числа, это относительно просто. Это не точный код, а что-то вроде:

List<String> jsonValues = new ArrayList<String>();
for (int i = 0; i < myJsonArray.length(); i++)
   jsonValues.add(myJsonArray.getString(i));
Collections.sort(jsonValues);
JSONArray sortedJsonArray = new JSONArray(jsonValues);

Конечно, если у вас есть вложенные объекты, это может быть немного сложнее. Если значения, которые вы хотите отсортировать в прямом эфире на верхнем уровне, это может быть не так уж плохо ...

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

Затем используйте компаратор, как этот, чтобы отсортировать:

class JSONComparator implements Comparator<JSONObject>
{

    public int compare(JSONObject a, JSONObject b)
    {
        //valA and valB could be any simple type, such as number, string, whatever
        String valA = a.get("keyOfValueToSortBy");
        String valB = b.get("keyOfValueToSortBy");

        return valA.compareTo(valB);
        //if your value is numeric:
        //if(valA > valB)
        //    return 1;
        //if(valA < valB)
        //    return -1;
        //return 0;    
    }
}

Опять же, это делает некоторые предположения о однородности данных в вашем JSONArray. Приспособьтесь к вашему случаю, если это возможно. Также вам нужно будет добавить обработку исключений и т.д. Удачного кодирования!

редактировать исправлено на основе комментариев

37
speakingcode

Чтобы заполнить список Android ArrayAdapter, мне нужно было сделать именно это. Вот как я это сделал:

Код активности для построения списка из JSONArray:

JSONArray kids = node.getJSONArray("contents");
kids = JSONUtil.sort(kids, new Comparator(){
   public int compare(Object a, Object b){
      JSONObject    ja = (JSONObject)a;
      JSONObject    jb = (JSONObject)b;
      return ja.optString("name", "").toLowerCase().compareTo(jb.optString("name", "").toLowerCase();
   }
});
// in my case I wanted the original larger object contents sorted...
node.put("contents", kids);

И в JSONUtil (мой помощник):

public static JSONArray sort(JSONArray array, Comparator c){
    List    asList = new ArrayList(array.length());
    for (int i=0; i<array.length(); i++){
      asList.add(array.opt(i));
    }
    Collections.sort(asList, c);
    JSONArray  res = new JSONArray();
    for (Object o : asList){
      res.put(o);
    }
    return res;
}
9
Tim Beres

Просто чтобы быть понятным, приведенный выше код для компаратора сортировки не верен .. Вы не можете сравнивать строки, как вы это делали выше, как в языке, подобном Ruby .. Это можно написать гораздо более кратко следующим образом. В противном случае логика звука.

Collections.sort( jsonValues, new Comparator<JSONObject>() {
    @Override
    public int compare(JSONObject a, JSONObject b) {
        String valA = new String();
        String valB = new String();

        try {
            valA = (String) a.get("keyOfValueToSortBy");
            valB = (String) b.get("keyOfValueToSortBy");
        } 
        catch (JSONException e) {
            Log.e(LOG_TAG, "JSONException in combineJSONArrays sort section", e);
        }

        return valA.compareTo(valB);
    }
});
7
Aaron Dancygier

Один пример с полем Date:

public class JsonObjectComparator implements Comparator<JSONObject> {
private final String fieldName;
private Class<? extends Comparable> fieldType;

public JsonObjectComparator(String fieldName, Class<? extends Comparable> fieldType) {
    this.fieldName = fieldName;
    this.fieldType = fieldType;
}    

@Override
public int compare(JSONObject a, JSONObject b) {
    String valA, valB;
    Comparable newInstance_valA, newInstance_valB;
    int comp = 0;
    try {
        Constructor<? extends Comparable> constructor = fieldType.getConstructor(String.class);            
        valA = a.getString(fieldName);
        valB = b.getString(fieldName);
        if (fieldType.equals(Date.class)) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
            newInstance_valA = dateFormat.parse(valA);            
            newInstance_valB = dateFormat.parse(valB);
        } else {
            newInstance_valA = constructor.newInstance(valA);            
            newInstance_valB = constructor.newInstance(valB);
        }
        comp = newInstance_valA.compareTo(newInstance_valB);
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }

    if(comp > 0)
        return 1;
    if(comp < 0)
        return -1;
    return 0;
  }

}

public static void main(String[] args) throws JSONException {        
    JSONObject o1 = new JSONObject();
    o1.put("key1", "26-06-2014");
    JSONObject o2 = new JSONObject();
    o2.put("key1", "30-11-2011");
    JSONObject o3 = new JSONObject();
    o3.put("key1", "15-07-2014");

    JsonObjectComparator comparator = new JsonObjectComparator("key1", Date.class);
    List<JSONObject> l = new ArrayList<>();
    l.add(o1);
    l.add(o2);
    l.add(o3);

    Collections.sort(l, comparator);
 }
1
Alex

Если вы собираетесь отображать данные, содержащиеся в JSONArray, возможно, имеет смысл отсортировать их в самом адаптере. Например, класс ArrayAdapter<T> уже имеет необходимые методы, такие как Insert, Remove и, конечно, Sort.

adapter.sort(new Comparator<JSONObject>(){

    @Override
    public int compare(JSONObject arg0, JSONObject arg1) {

        return arg0.optString("SortField", "").compareTo(arg1.optString("SortField","")) ;

    }

});
1
Hugh Jeffner
//My script
 //HEADER add final variables
    private final int TYPE_STRING = 1;
    private final int TYPE_INT = 2;
    private final int TYPE_DUBLE = 3;


//METHOD GET SORT JSONARRAY
public JSONArray  getSortJSONArray()
{
 JSONArray  json = new JSONArray  ([{"carid":"957502","vin":"XXXXX","carbrand":"CADILLAC","carmodel":"CTS","carname":"CADILLAC CTS седан CTS PERFORMANC 2.0L AWD AK4 2 4WD  AT-6 276 (Л.С.)","carmodificationname":" седан CTS PERFORMANC 2.0L AWD AK4 2 4WD  AT-6 276 (Л.С.)","carcolorname":"Opulent Blue Metallic - ярко-синий металлик","price":"3410000","rgb":"","volumereal":"2,00","power":"276"},{"carid":"957502","vin":"XXXXX","carbrand":"CADILLAC","carmodel":"CTS","carname":"CADILLAC CTS седан CTS PERFORMANC 2.0L AWD AK4 2 4WD  AT-6 276 (Л.С.)","carmodificationname":" седан CTS PERFORMANC 2.0L AWD AK4 2 4WD  AT-6 276 (Л.С.)","carcolorname":"Opulent Blue Metallic - ярко-синий металлик","price":"3460000","rgb":"","volumereal":"1,00","power":"272"}]");

 /*halper - My halper */
   JSONArray sorJsonArray = halper.sort(json, getComparator("power",TYPE_INT));
   return sorJsonArray;
}

private Comparator getComparator(final String tagJSON,final int type)
    {
        Comparator c =  new Comparator()
        {
            public int compare(Object a, Object b)
            {


                try
                {
                    JSONObject    ja = (JSONObject)a;
                    JSONObject    jb = (JSONObject)b;

                    switch (type)
                    {
                        case TYPE_STRING:// String
                          return ja.optString(tagJSON, "")
                                                .toLowerCase()
                                                .compareTo(jb.optString(tagJSON, "").toLowerCase());
                        case TYPE_INT:// int
                            int valA =  ja.getInt(tagJSON);
                            int valB =  jb.getInt(tagJSON);
                            if(valA > valB)
                                return 1;
                            if(valA < valB)
                                return -1;

                        case TYPE_DUBLE:// double
                            String v1 = ja.getString(tagJSON).replace(",",".");
                            String v2 = jb.getString(tagJSON).replace(",",".");

                            double valAd = new Double(v1);// ja.getDouble(tagJSON);
                            double valBd = new Double(v2);//  jb.getDouble(tagJSON);
                            if(valAd > valBd)
                                return 1;
                            if(valAd < valBd)
                                return -1;

                    }
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
                return 0;
            }
        };

        return c;
    }

// Мой класс Halper

public class Halpe {
    public void Halpe(){}

    public static JSONArray sort(JSONArray array, Comparator c)
    {
        List    asList = new ArrayList(array.length());
        for (int i=0; i<array.length(); i++){
            asList.add(array.opt(i));
        }
        Collections.sort(asList, c);
        JSONArray  res = new JSONArray();
        for (Object o : asList){
            res.put(o);
        }
        return res;
    }}
0
Aleksandr K