Android如何对JSONObjects的JSONArray进行排序

Posted

技术标签:

【中文标题】Android如何对JSONObjects的JSONArray进行排序【英文标题】:Android how to sort JSONArray of JSONObjects 【发布时间】:2012-10-05 18:54:52 【问题描述】:

我已经创建了一个 jsonarray 的 jsonobjects。现在我需要根据来自 jsonobjects 的值对 JSONArray 进行排序。以前我像这样对自定义对象的 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 给出错误:

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

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

【问题讨论】:

可能被***.com/questions/4833084/…欺骗 考虑一下:如果您可以在构建 JsonArray 之前进行排序,请执行此操作。您也可以稍后在 javascript 中对其进行排序。我认为从 JsonArray 构建一个列表,对列表进行排序,然后重建 JsonArray 非常糟糕:) 【参考方案1】:

问题在于 JSONArray 或多或少包含最终是字符串的 JSONObject(和其他 JSONArray)。将字符串完全反序列化为 POJO,对它们进行排序,然后返回 JSON 相当繁重。

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

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

编辑 基于 cmets 修复

【讨论】:

这个例子很接近,但它不能编译。由于 Java 没有运算符重载,因此您无法以这种方式比较字符串。该示例应返回 valA.compareTo(valB)。 但我想一个普通的 java 开发人员可以做到,没有谷歌或这个 实际上,我在想,如果我们需要排序是为了能够比较 JSonArrays,那么应该有一种有效的方法来使用它们的哈希值来做到这一点......虽然没有尝试过,对人类来说,生成的顺序似乎是随机的。【参考方案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;

【讨论】:

也许在适配器本身中这样做:***.com/a/32213875/383761【参考方案3】:

只是为了清楚上面的排序比较器代码是不正确的。 您无法像在 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);
    
);

【讨论】:

你不能直接返回 valA.compareTo(valB) 吗?【参考方案4】:

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

【讨论】:

【参考方案5】:

如果您要显示包含在JSONArray 中的数据,那么在适配器本身中对其进行排序可能是有意义的。比如ArrayAdapter&lt;T&gt;类已经有了InsertRemove、当然还有Sort等必要的方法。

adapter.sort(new Comparator<JSONObject>()

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

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

    

);

【讨论】:

【参考方案6】:
//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;
    

【讨论】:

以上是关于Android如何对JSONObjects的JSONArray进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Retrofit2 处理嵌套 JsonObjects 的动态字段

如何获取根据 JAVA 中的用户选择而变化的 JsonObjects?

如何从 JSchema/ Map JsonObjects 获取父对象名称到新父对象

在 Java 中合并(Concat)多个 JSONObjects

流式写入 Json

Android POJO 类检查特定键是不是包含 Boolean 或 arraylist 值