解析特殊结构的JSON

一般来说JSON的Key是已知的,如下所示:

{
    "results": [
           {
            "id": 1,
            "name": "wangyuwei",
            "sexuality": "male"
        },
        {
            "id": 2,
            "name": "JeasonWong",
            "sexuality": "female"
        }
    ]
}

这样的JSON太容易解析了,但是有性能上的缺点,比如”id”,”name”,”sexuality”这些Key一直重复出现,一定程度上成为了冗余数据,那么问题来了,如何解决呢?参考以下JSON格式。

{
    data: {
        snapshot: {
            fields: [
                "open_px",
                "high_px",
                "low_px"
            ],
            600570.SS: [
                47.08,
                48.38,
                45.88
            ],
            000001.SZ: [
                11.02,
                11.12,
                10.88
            ]
        }
    }
}

这种JSON格式并不是很常见,但是我认为性能确实很强悍的。没有多余的Key,除了”fields”外,其余的Key都不是事先知道的,而”fields”里的Value确是与”fields”同级Key的Value一一对应,成为这些Value的Key。多么好的一个想法!

那么问题来了,对于这种未知Key的JSON数组我们该如何下手呢?

虽然不知道Key,但我们可以使用Iterator遍历一遍就行了。

JSONObject jsonObj = new JSONObject(json).getJSONObject("data").getJSONObject("snapshot");
Iterator keyIter = jsonObj.keys();

这样一来,所有的Key都拿到了,但这个时候我们只拿到了最外层的Key,即”fields”,”600570.SS”,”000001.SZ”,而”fileds”里的Value还没取出,这些Value即将作为”600570.SS”,”000001.SZ”中Value的Key了(前面已经说了,又啰嗦一遍:))

List list = new ArrayList();
JSONArray fields = jsonObj.getJSONArray("fields");
for (int i = 0; i < fields.length(); i++) {
    list.add(i, fields.getString(i));
}

现在”fields”中的Value全都取出来放到了list里。接着就是遍历刚才的keyIter了。

while (keyIter.hasNext()) {
    String keys = (String) keyIter.next();
    JSONArray jsonArray = jsonObj.getJSONArray(keys);
    Map map = new HashMap();
    if (keys.equals("fields")) {
        continue;
    } else {
        for (int i = 0; i < jsonArray.length(); i++) {
            map.put(list.get(i), jsonArray.get(i));
        }
        HSStockEntity hsStockEntity = new HSStockEntity();
        hsStockEntity.setSymbol(keys);
        hsStockEntity.setOpen_px(Double.parseDouble(map.get("open_px").toString()));
        hsStockEntity.setHigh_px(Double.parseDouble(map.get("high_px").toString()));
        hsStockEntity.setLow_px(Double.parseDouble(map.get("low_px").toString()));
        listEntity.add(hsStockEntity);
    }
}

从以上代码可以看到,我按照keyIter的顺序拿到”600570.SS”,”000001.SZ”中的Value,然后把他们放到了map里,map的Key是”fields”的Value,而map的Value则是”600570.SS”或”000001.SZ”对应的Value。

HSStockEntity我的一个Model,这样最后能把所有的hsStockEntity都放在listEntity的集合中了。

需要特别注意的一点是keyIter取到的Key并一定与你看到的顺序是一样的,也就是”fields”,”600570.SS”,”000001.SZ”三个的顺序是不一定的,那么假如你的JSON数据源必须要按照一定的顺序显示,那你就得需要自己写一下Comparator了。比如我这里对high_px进行降序排序,如果相等时根据symbol再排。

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
Collections.sort(listEntity, new Comparator<HSStockEntity>() {
    @Override
    public int compare(HSStockEntity entity, HSStockEntity t1) {
        if ((float) entity.getHigh_px() - (float) t1.getHigh_px() ==0) {
            return entity.getSymbol().compareTo(t1.getSymbol());
           } else if ((float) entity.getHigh_px() - (float) t1.getHigh_px() > 0) {;
           if (isRise) return -1;
            return 1;
         } else {
              if (isRise) return 1;
                  return -1;
            }
        }
});

这样以来,对这种特殊结构的JSON解析就完成了。