it-swarm.com.de

Android, wie JSONArray von JSONObjects sortiert wird

Ich habe ein Jsonarray von Jsonobjects gemacht. Jetzt muss ich den JSONArray nach einem Wert aus den Jsonobjects sortieren. Früher habe ich ArrayLists von benutzerdefinierten Objekten wie folgt sortiert:

Komparatoren:

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

Und dann sortieren Sie die Arrayliste:

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

oder:

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

Aber wenn ich dasselbe mit dem JSONArray probiere (JA = mein Jsonarray)

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

die Collections.sort gibt einen Fehler aus: 

Die Methode sort (List, Comparator) im Typ Collections ist für die Argumente (JSONArray, ThisActicity.KreeftenComparatorNL) nicht anwendbar.

Weiß jemand, wie man den JSONArray ordnet?

20
Simon

Das Problem ist, dass JSONArray mehr oder weniger JSONObjects (und andere JSONArrays) enthält, die letztendlich Zeichenfolgen sind. Das Deserialisieren der Strings vollständig in POJOs, das Sortieren dieser und dann wieder in JSON, ist ziemlich schwer.

Das zweite Problem ist, dass ein JSONArray Folgendes enthalten kann: Boolean, JSONArray, JSONObject, Number, String oder das JSONObject.NULL-Objekt; Das heißt, es handelt sich um gemischte Typen, wodurch es schwierig wird, die Elemente einfach in eine Liste eines bestimmten Typs zu sortieren und zu sortieren. Anschließend werden die sortierten Elemente der Liste zurück in das JSON-Array geschickt. Die einzige sichere Methode, um einen allgemeinen Typ jedes Elements aus dem JSONArray zu erhalten, ist die Object-Methode get (). Natürlich haben Sie nur Object-Objekte und können keine sinnvollen Sortierungen für sie durchführen, ohne die Serialisierungsproblem.

Wenn Sie davon ausgehen, dass Ihr JSONArray homogen strukturierte Werte enthält, können Sie das JSONArray durchlaufen, eine der typisierten get () -Methoden für jede Methode aufrufen, sie in einen List-Typ speichern und danach sortieren. Wenn Ihr JSONArray nur einen einfachen Typ wie String oder Zahlen enthält, ist dies relativ einfach. Dies ist kein exakter Code, aber so etwas wie:

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

Wenn Sie Objekte verschachtelt haben, kann dies natürlich etwas schwieriger werden. Wenn der Wert, den Sie sortieren möchten, live in der obersten Ebene ist, kann es nicht so schlimm sein ...

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

Dann verwenden Sie einen Komparator wie diesen zum Sortieren:

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

Dies macht wiederum einige Annahmen über die Homogenität der Daten in Ihrem JSONArray. Passen Sie, falls möglich, Ihren Fall an. Außerdem müssen Sie Ihre Ausnahmebehandlung hinzufügen. Glückliche Codierung!

edit behoben, basierend auf Kommentaren

37
speakingcode

Um eine Android-Liste ArrayAdapter aufzufüllen, musste ich genau das tun. So habe ich es gemacht:

Aktivitätscode zum Erstellen einer Liste aus einem 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);

Und in JSONUtil (mein Helfer):

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

Um nur klar zu sein, der obige Code für den Sortiervergleicher ist nicht korrekt .. Sie können einen String nicht wie oben vergleichen, wie Sie dies in einer Sprache wie Ruby tun könnten. Ansonsten ist die Logik solide.

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

Ein Beispiel mit dem Feld 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

Wenn Sie die in JSONArray enthaltenen Daten anzeigen möchten, kann es sinnvoll sein, sie im Adapter selbst zu sortieren. Beispielsweise verfügt die Klasse ArrayAdapter<T> bereits über die erforderlichen Methoden wie Insert, Remove und natürlich 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;
    }

// Meine Halper-Klasse

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