fastjson存在乱序的问题
现象及原因通常来讲,在使用json数据格式时一般不需要要求数据有序。但凡事都有例外,针对查询时序数据这样一个场景,就必须要求服务器端返回的数据是按时间有序的,否则前端在进行数据展示时就会有问题。 数据从OpenTSDB中查询出来的时候是有序的: [{ "metrc":"cpu.usage","dps": { "123456": 12,"123457": 13,"123458": 23,"123459": 32 } }] 执行如下操作: JSONObject.parseArray(json) 结果查看对应的JSON数组中的map数据是乱序的,可能的结果如下: [{ "metrc":"cpu.usage","dps": { "123457": 13,"123456": 12,"123459": 32,"123458": 23 } }] 原本希望时序数据是按时间Key有序的,但是经过fastjson解析之后就会出现Key乱序。实际上,这个问题是fastjson本身的bug,详见:https://github.com/alibaba/fastjson/issues/660 。 解决办法如下以解析从OpenTSDB中查询返回的时序数据为例。 1.升级fastjson版本fastjson从 public static void main(String[] args) { // 模拟从OpenTSDB中查询返回的时序数据 String str = "[{"metric":"temperature","tags":{"device_id":"device-12312-14","dt_name":"dsdsdsd"},"aggregateTags":[],"dps":{"1538210186542":30,"1538210191574":83,"1538210196597":41,"1538210201624":56,"1538210206654":20,"1538210211677":25,"1538210216700":54,"1538210221740":36,"1538210226773":89,"1538210231813":8,"1538210236847":34,"1538210241882":83,"1538210246916":96,"1538210251952":42,"1538210257002":6,"1538210262038":87,"1538210267076":19,"1538210272108":44,"1538210277139":84,"1538210282176":41,"1538210287216":57,"1538210292254":26,"1538210297283":64}}]"; // 直接使用fastjson的接口实现有序解析 JSONArray array = JSONArray.parSEObject(str.getBytes(),JSONArray.class,Feature.OrderedField); System.out.println(array.getJSONObject(0).getJSONObject("dps").toJSONString()); } 实际上,追踪一下fastjson的实现源码发现,当传递参数 public JSONObject(int initialCapacity,boolean ordered){ if (ordered) { // 使用LinkedHashMap保证json对象的key是按照插入顺序有序的 map = new LinkedHashMap<String,Object>(initialCapacity); } else { map = new HashMap<String,Object>(initialCapacity); } } 2.手动排序除了可以直接通过fastjson的接口在解析时就实现有序,还可以对解析结果进行手动排序。 public static void main(String[] args) { // 模拟从OpenTSDB中查询返回的时序数据 String str = "[{"metric":"temperature","1538210297283":64}}]"; // 解析之后手动排序 JSONArray array = JSONArray.parseArray(str); System.out.println(array.toJSONString()); JSONObject json = array.getJSONObject(0); // 不传递参数Feature.OrderedField时解析得到的json对象key是无序的,本质上是一个HashMap结构 Map<String,Object> map = json.getJSONObject("dps").getInnerMap(); // 通过TreeMap对Key进行排序 map = sortMapByKey(map); JSONObject dps = new JSONObject(); dps.put("dps",map); System.out.println(dps.toJSONString()); } private static Map<String,Object> sortMapByKey(Map<String,Object> map) { if (map == null || map.isEmpty()) { return null; } Map<String,Object> sortMap = new TreeMap<String,Object>(new MapKeyComparator()); sortMap.putAll(map); return sortMap; } private static class MapKeyComparator implements Comparator<String> { @Override public int compare(String str1,String str2) { return str1.compareTo(str2); } } 【参考】 https://dzone.com/articles/hashmap-vs-treemap-vs HashMap vs. TreeMap vs. HashTable vs. LinkedHashMap (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |