今天测试了下
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<!--<version>1.1.36</version>-->
<version>1.2.29</version>
</dependency>
1.1.36 A版本 和1.2.29 B版本 这2个版本的,其实影响还挺大的。首先我们这边是使用这个玩意排序的,对排序的结果进行RSA加密。但是如果fastjson版本不一致的话,
@org.junit.Test
public void test(){
JSONObject jsonObject = new JSONObject();
jsonObject.put("a","1");
jsonObject.put("b","2");
jsonObject.put("d","3");
jsonObject.put("c","4");
//String s2=JSONObject.toJSONString(jsonObject,SerializerFeature.SortField.MapSortField);
String s2=JSONObject.toJSONString(jsonObject);
logger.info("--"+s2);
}
上面这个demo:
如果是A版本的话:输出的结果是:
{“a”:”1”,”b”:”2”,”c”:”4”,”d”:”3”}
如果是B版本的结果是:
{“d”:”3”,”b”:”2”,”c”:”4”,”a”:”1”}
这样就有一个问题,如果我们依赖这个顺序(比如这个结果进行加密,请求放和服务方不是一个版本的)解密就失败了。
先说下原因:JSONObject 依赖MapSerializer这类来处理:有一段这样的代码(高版本的)
Map<?, ?> map = (Map<?, ?>) object;
final int mapSortFieldMask = SerializerFeature.MapSortField.mask;
if ((out.features & mapSortFieldMask) != 0 || (features & mapSortFieldMask) != 0) {
if ((!(map instanceof SortedMap)) && !(map instanceof LinkedHashMap)) {
try {
map = new TreeMap(map);
} catch (Exception ex) {
// skip
}
}
}
也就是你必须有SerializerFeature.MapSortField 这个参数才可以使用TreeMap(这个默认是按照key进行排序的).
这个是低版本的:
Map<?, ?> map = (Map<?, ?>) object;
if (out.isEnabled(SerializerFeature.SortField)) {
if ((!(map instanceof SortedMap)) && !(map instanceof LinkedHashMap)) {
try {
map = new TreeMap(map);
} catch (Exception ex) {
// skip
}
}
}
A版本的根本没有验证这个参数,直接使用TreeMap。说道这里基本大家就知道怎么解决了。
思路1:直接指定TreeMap如下:
JSONObject jsonObject = new JSONObject(new TreeMap<String, Object>());
这个也是大部分网上建议的。不过我看好多人还有自己写了这块的逻辑。
思路2:指定参数项
JSONObject.toJSONString(jsonObject,SerializerFeature.SortField.MapSortField)
提示:低版本的没有SerializerFeature.SortField.MapSortField这个参数。