分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

fastjson存在乱序的问题

发布时间:2023-09-06 02:16责任编辑:苏小强关键词:jsjson

现象及原因

通常来讲,在使用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从1.2.3版本开始,在解析json对象时可以指定Feature.OrderedField参数,这样解析的结果就不会乱序。

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的实现源码发现,当传递参数Feature.OrderedField时,底层正是使用LinkedHashMap来实现Key有序的(LinkedHashMap是按插入顺序排序):

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\",\"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}}]"; ???// 解析之后手动排序 ???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

fastjson存在乱序的问题

原文地址:https://www.cnblogs.com/nuccch/p/9729781.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved