Android 如何对 JSONObjects 的 JSON 数组进行排序

2022-09-01 18:19:32

我做了一个jsonarray的jsonobjects。现在,我需要根据 jsonobjects 中的值对 JSONArray 进行排序。以前,我对自定义对象的 ArrayList 进行排序,如下所示:

比较:

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

然后对数组列表进行排序:

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

艺术

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

但是当我像这样尝试JSONArray(JA = my jsonarray)时

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

Collections.sort 给出了一个错误:

集合类型中的方法 sort(List, Comparator) 不适用于参数 (JSONArray, ThisActicity.KreeftenComparatorNL)

有没有人知道如何对JSONArray进行排序?


答案 1

问题是JSONArray或多或少地持有JSONObjects(和其他JSONArrays),这些对象最终是字符串。将字符串完全反序列化为POJO,对其进行排序,然后放回JSON是相当沉重的。

第二个问题是JSONArray可以包含:布尔值,JSONArray,JSONObject,Number,String或JSONObject.NULL对象;即,它是混合类型,因此很难将元素转储到某种类型的列表中并对其进行排序,然后通过列表将排序后的项目传递回JSON数组。从 JSONArray 获取每个元素的通用类型的唯一特定方法是使用 Object get() 方法。当然,您所拥有的只是对象对象,如果不重新访问序列化问题,就无法对它们进行任何有意义的排序。

假设您的 JSONArray 包含同构结构的值,您可以循环访问 JSONArray,在每个方法上调用一个类型化的 get() 方法,将它们转储到 List 类型中,然后对其进行排序。如果您的JSONArray只保存“简单”类型,如字符串或数字,则相对容易。这不是精确的代码,而是像这样:

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 中数据的同质性做出一些假设。如果可能的话,根据您的情况进行调整。此外,您还需要添加异常处理等。祝您编码愉快!

根据注释进行编辑修复


答案 2

为了填满一个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;
}