JSONObject排序问题-fastjson map 排序问题(真正的实用)

时间:2021-10-02 00:51:50

今天测试了下

<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这个参数。