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)范围内 ...
随机推荐
- linux安装windows启动盘
安装gparted
- java8新特性-默认方法
作为一个java程序猿,经常会被问基础怎么样,对于这个问题,我理解的有两方面:一是对于java基础的理解和掌握,比如JDK的相关特性:二是工作的经历,毕竟,语言编程是一门实战性质的艺术,就算掌握了千万 ...
- 根据Webservice地址,动态传入参数(Webservice代理类)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sunlib; ...
- keil 中报错和警告提示解决办法
1.warning: #1-D: last line of file ends without a newline 解决办法:在文件最后一行加入一个回车. 2.error: #134: expecte ...
- MyBatis学习日记(一):拜见小主——MyBatis
近日学习MyBatis,特将学习过程及一点心得记录于此. MyBatis为何物? MyBatis 是支持定制化SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC ...
- A Diversity-Promoting Objective Function for Neural Conversation Models论文阅读
本文来自李纪为博士的论文 A Diversity-Promoting Objective Function for Neural Conversation Models 1,概述 对于seq2seq模 ...
- Web后台快速开发框架
Web后台快速开发框架 Coldairarrow 目录 目录 第1章 目录 1 第2章 简介 3 第3章 基础准备 4 3.1 开发环境要求 4 3.2 ...
- VSCode 配置并使用less
1.安装node.js 2.安装less npm install less -g 3.安装VS插件 Easy LESS 4.编辑保存.less文件,会在对应的目录下生成对应的.css文件
- springboot项目从硬盘指定位置读取文件(获取静态资源)
方法一:继承WebMvcConfigurerAdapter类 package com.imooc.demo.config; import org.springframework.context.ann ...
- 【问题解决方案】ImportError: No module named 'pygal'
<Python编程:从入门到实践>一书,第二个项目-可视化,第四节用到pygal 安装部分用 'python -m pip install pygal==1.7' 安装,但使用时仍然报错 ...