2012-10-15 15 views
18

Ich habe ein jsonarray von jsonobjects gemacht. Jetzt muss ich das JSONArray auf Basis eines Wertes aus den Jsonobjekten sortieren. Früher sortiert I Arraylisten von benutzerdefinierten Objekte wie folgt aus:Android, wie man JSONArray von JSONObjects sortiert

Vergleicher:

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 die Arraylist sortieren:

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

oder:

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

Aber wenn ich versuche, die Das gleiche mit dem JSONArray wie folgt (JA = my jsonarray)

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

der Collections.sort gibt einen Fehler:

The method sort(List, Comparator) in the type Collections is not applicable for the arguments (JSONArray, ThisActicity.KreeftenComparatorNL)

Weiß jemand, wie die JSONArray zu sortieren?

+0

möglich Betrogene von http://stackoverflow.com/questions/4833084/is-there-any-easy-way-to-sort- a-jsonarray-von-objekten-by-ein-attribut-in-android? rq = 1 – petey

+0

Betrachten Sie dies: Wenn Sie sortieren können, bevor Sie das JsonArray erstellen, tun Sie das. Sie können es später auch im JavaScript sortieren. Ich denke, eine Liste aus dem JsonArray aufzubauen, die Liste zu sortieren, dann das JsonArray neu aufzubauen ist ziemlich schrecklich :) –

Antwort

34

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

Das zweite Problem ist, dass ein JSONArray enthalten kann: Boolean, JSONArray, JSONObject, Number, String oder das JSONObject.NULL-Objekt; d. h. es sind gemischte Typen, was es schwierig macht, die Elemente einfach in eine Liste eines Typs abzulegen und diese zu sortieren, dann durch die Liste zu gehen, um sortierte Objekte zurück in das JSON-Array zu werfen. Der einzige sichere Weg, um einen gemeinsamen Typ jedes Elements aus dem JSONArray zu erhalten, ist die Verwendung der Object get() -Methode. Natürlich haben Sie nur Objektobjekte und können keine sinnvolle Sortierung an ihnen vornehmen, ohne das Objekt erneut zu durchsuchen Serialisierungsproblem.

Angenommen, Ihr JSONArray enthält homogen strukturierte Werte. Sie könnten das JSONArray durchlaufen, indem Sie eine der typisierten get() -Methoden aufrufen, sie in einen List-Typ ablegen und danach sortieren. Wenn Ihr JSONArray nur einen "einfachen" Typ wie String oder Zahlen enthält, ist das relativ einfach. Dies ist nicht richtig Code, sondern 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); 

Natürlich, wenn Sie Objekte verschachtelt haben diese ein wenig schwieriger zu bekommen. Wenn der Wert (e) Sie leben in der obersten Ebene sortieren möchten, kann es nicht soo schlecht ...

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

Dann einen Komparator wie folgt verwenden zu 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;  
    } 
} 

Wieder , das macht einige Annahmen über die Homogenität der Daten in Ihrem JSONArray. Passen Sie, wenn möglich, an Ihren Fall an. Außerdem müssen Sie Ihre Ausnahmebehandlung hinzufügen, usw. Happy Coding!

bearbeiten feste basierend auf Kommentare

+0

update line Collections.sort (jsonValues); –

+2

Dieses Beispiel ist nah, aber es kompiliert nicht. Sie können Strings auf diese Weise nicht vergleichen, da Java keine Operatorüberladung aufweist. Das Beispiel sollte valA.compareTo (valB) zurückgeben. – SoWeLie

8

nur klar über den Code zu sein für die Art Komparator nicht korrekt ist. Sie können die Zeichenfolge nicht wie oben beschrieben vergleichen, wie in einer Sprache wie Ruby. Dies könnte viel kürzer wie folgt geschrieben werden. 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); 
    } 
}); 
+1

Könnten Sie nicht einfach valA.compareTo (valB) zurückgeben? – SoWeLie

+1

Ja, Sie haben Recht, wenn ... die Rückkehr unnötig ist. –

8

Um eine Android-Liste ArrayAdapter zu füllen, musste ich genau dies tun. Dies ist, wie ich es tat:

Aktivitätscode eine Liste von einem JSONArray Gebäude:

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

Vielleicht tun dies in den Adapter selbst: http://StackOverflow.com/a/32213875/383761 –

1

Ein Beispiel mit Date Feld:

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

Wenn Sie die in der JSONArray enthaltenen Daten dann anzeigen möchten Es kann sinnvoll sein, es im Adapter selbst zu sortieren. Zum Beispiel hat die Klasse ArrayAdapter<T> bereits die erforderlichen Verfahren 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","")) ; 

    } 

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