web-dev-qa-db-fra.com

Android comment trier JSONArray de JSONObjects

J'ai fait un jsonarray de jsonobjects. Maintenant, je dois trier le JSONArray sur la base d'une valeur des jsonobjects. Auparavant, j'ai trié ArrayLists d'objets personnalisés comme ceci:

Comparateurs:

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);
    }
}

Et ensuite, triez l'arrayliste:

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

ou:

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

Mais quand j'essaye la même chose avec le JSONArray comme ceci (JA = mon jsonarray)

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

le Collections.sort donne une erreur: 

La méthode sort (List, Comparator) dans le type Collections n'est pas applicable pour les arguments (JSONArray, ThisActicity.KreeftenComparatorNL)

Quelqu'un sait-il comment trier le JSONArray?

20
Simon

Le problème est que JSONArray contient plus ou moins JSONObjects (et d'autres JSONArrays) qui sont finalement des chaînes. La désérialisation complète des chaînes en POJO, leur tri, puis leur restitution en JSON sont assez lourdes.

Le deuxième problème est qu'un JSONArray peut contenir: Boolean, JSONArray, JSONObject, Number, String ou l'objet JSONObject.NULL; c’est-à-dire qu’il s’agit de types mélangés, il est donc difficile de simplement vider les éléments dans une liste d’un type quelconque et de les trier, puis de passer à travers la liste en vendant les éléments triés dans le tableau JSON. Le seul moyen sûr d'obtenir un type commun de chaque élément à partir de JSONArray consiste à utiliser la méthode Object get (). Bien entendu, tout ce que vous avez est constitué d'objets Object et vous ne pourrez effectuer aucun tri significatif sans un nouvel examen de la problème de sérialisation.

En supposant que votre JSONArray contienne des valeurs structurées de manière homogène, vous pouvez parcourir le JSONArray, en appelant l’une des méthodes get () typées sur chacune d’elles, en les vidant dans un type List, puis en les triant. Si votre JSONArray contient simplement un type "simple" comme String ou numbers, cela est relativement facile. Ce n'est pas un code exact mais quelque chose comme:

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);

Bien sûr, si vous avez des objets imbriqués, cela peut devenir un peu plus compliqué. Si la ou les valeurs sur lesquelles vous souhaitez effectuer un tri en direct dans le niveau supérieur, ce n'est peut-être pas si grave ...

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

Ensuite, utilisez un comparateur comme celui-ci pour trier:

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;    
    }
}

Là encore, cela suppose certaines hypothèses quant à l'homogénéité des données de votre tableau JSON. Ajustez votre cas si possible. De plus, vous devrez ajouter la gestion de vos exceptions, etc. Bon codage!

edit corrigé en fonction des commentaires

37
speakingcode

Afin de remplir une liste Android ArrayAdapter, je devais faire cela. Voici comment je l'ai fait:

Code d'activité générant une liste à partir d'un tableau JSON:

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);

Et dans JSONUtil (mon assistant):

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

Juste pour être clair, le code ci-dessus pour le comparateur de tri n’est pas correct . Vous ne pouvez pas comparer une chaîne comme ci-dessus comme vous le pourriez dans un langage comme Ruby . Cela pourrait être écrit beaucoup plus succinctement comme suit. Sinon, la logique est bonne.

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

Un exemple avec le champ 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

Si vous souhaitez afficher les données contenues dans JSONArray, il peut être judicieux de les trier dans l'adaptateur lui-même. Par exemple, la classe ArrayAdapter<T> possède déjà les méthodes requises telles que Insert, Remove et bien sûr 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;
    }

// Mon cours de 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