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从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存在乱序的问题的更多相关文章
- fastjson序列化乱序问题
1.初始化为有序json对象 JSONObject jsonOrdered= new JSONObject(true); 2.将String对象转换过程中,不要调整顺序 JSONObject json ...
- FastJson乱序问题
1.初始化为有序json对象 JSONObject jsonOrdered= new JSONObject(true); 2.将String对象转换过程中,不要调整顺序 JSONObject json ...
- fast json 乱序问题解决过程
解决问题:保存到redis中的jsonstring在转回jsonObject的时候乱序: 解决方案:https://inlhx.iteye.com/blog/2312512 解决过程: 1 看fast ...
- 由乱序播放说开了去-数组的打乱算法Fisher–Yates Shuffle
之前用HTML5的Audio API写了个音乐频谱效果,再之后又加了个播放列表就成了个简单的播放器,其中弄了个功能是'Shuffle'也就是一般播放器都有的列表打乱功能,或者理解为随机播放. 但我觉得 ...
- iOS之数组的排序(升序、降序及乱序)
#pragma mark -- 数组排序方法(升序) - (void)arraySortASC{ //数组排序 //定义一个数字数组 NSArray *array = @[@(3),@(4),@(2) ...
- volatile关键字及编译器指令乱序总结
本文简单介绍volatile关键字的使用,进而引出编译期间内存乱序的问题,并介绍了有效防止编译器内存乱序所带来的问题的解决方法,文中简单提了下CPU指令乱序的现象,但并没有深入讨论. 以下是我搭建的博 ...
- Fisher-Yates 乱序算法
这两篇博客[1][2]的模式是我心仪的一种科技博客的方式,提供源代码,显示运行图形结果,通俗地介绍理论原理. 直接把结论摘录下来吧. 随机算法如果写成如下形式 randomIndex = random ...
- TCP协议下大数据传输IOCP乱序问题
毕业后稀里糊涂的闭门造车了两年,自己的独立博客也写了两年,各种乱七八糟,最近准备把自己博客废了,现在来看了下这两年写的对我来说略微有点意义的文章只此一篇,转载过来以作留念. 写的很肤浅且凌乱,请见谅. ...
- 疯狂位图之——位图生成12GB无重复随机乱序大整数集
上一篇讲述了用位图实现无重复数据的排序,排序算法一下就写好了,想弄个大点数据测试一下,因为小数据在内存中快排已经很快. 一.生成的数据集要求 1.数据为0--2147483647(2^31-1)范围内 ...
随机推荐
- ORA-04030: out of process memory when trying to allocate 152 bytes (Logminer LCR c,krvtadc)
今天使用LogMiner找回误更新的数据时,查询v$logmnr_contents时,遇到了"ORA-04030: out of process memory when trying to ...
- 虚拟机安装windows7 VMware12 安装window7
闲来无事就来搞虚拟机装操作系统!期间出现很多错误,分享一下 一.安装虚拟机 二.准备安装的镜像文件 我下载的是windows7纯净版 深度技术里面下载的(http://www.xitongzhijia ...
- ThreadLocal<T>学习总结
public class ThreadLocalTest { /** * @param * @Author: xdj * @Date: 2019/4/12 10:16 * @Description: ...
- [原创]一款小巧、灵活的Java多线程爬虫框架(AiPa)
1.简介 AiPa 是一款小巧,灵活,扩展性高的多线程爬虫框架. AiPa 依赖当下最简单的HTML解析器Jsoup. AiPa 只需要使用者提供网址集合,即可在多线程下自动爬取,并对一些异常进行处理 ...
- 腾讯通信云服务端使用心得,腾讯云IM
腾讯通信云服务端使用心得 1.腾讯通信服务入口并创建应用 方便使用保留url地址 : https://cloud.tencent.com/product/im 注册账号腾讯云账号->通过审核 ...
- Map the Debris 轨道周期
返回一个数组,其内容是把原数组中对应元素的平均海拔转换成其对应的轨道周期. 原数组中会包含格式化的对象内容,像这样 {name: 'name', avgAlt: avgAlt}. 至于轨道周期怎么求, ...
- NW.js使用及打包
简介 NW.js (原名 node-webkit)是一个结合了 Chromium 和 node.js 的应用运行时,通过它可以用 HTML 和 JavaScript 编写原生应用程序.它还允许开发者从 ...
- JS confirm或alert对话框中的换行
如题. alert.confirm对话框的换行可以使用回车符或换行符:\n,\r 也可以使用回车符或换行符对应的unicode编码:\u000a,\u000d,这是等效的. //确认信息 var co ...
- NodeJs之定时器与队列
NodeJs之定时器与队列 一,介绍与需求 1.1,介绍 定时任务(node-schedule),是针对Node.js的一种灵活的cron-like和not-cron-like作业调度程序.它允许您使 ...
- Linux下Nginx配置阿里云 SSL证书实现HTTPS访问
这篇文章主要介绍了nginx配置ssl证书实现https访问的示例 1.服务器系统:Centos 2. 阿里云申请SSL证书 选择“免费版DV SSL”,点击立即购买: 下载证书 列表中找到已签发的证 ...