Json串排序
最近遇到个很烦人的问题。我现在做的业务有一部分是把之前app
服务端的.net接口转译java接口。但是有些之前的接口,一个接口干上十几件事情,返回的json
串长达五六几百行。着实看的就让人头大。但是如果返回的json串和原来的对不上,那app
客户端就无法正常显示,人工去对比那是耗时耗力。所以我就想找一个程序,能把json
串格式化好,然后按字段名称排好序,在逐行进行对比,就能很快就能找出不同比人工要快无数倍。找了半天也没法发现合适的。于是只好自己写一个。这个工具主要的思路是,将json
串格式化并根据key
值排好序,理论上相同的字段都排在相同的位置,然后根据这个去逐行进行比较,如果不相同就标为红色。如果相同就不变,试用了下,效果还不错,所以拿出来分享,希望大家都不用加班。哈哈
其中遇到一个坑fastjson
中带的字段排序总不能很好的解决我的问题,排序总有问题。所以我就自己写了一段方法进行排序。
private Map<String, Object> sortField(Map<String, Object> map){
//new 一个排序的Map 在构造方法中传入比较器
Map<String, Object> treeMap = new TreeMap<>(new MapComparator());
for (Map.Entry<String, Object> entry : map.entrySet()){
Object value = entry.getValue();
//去掉空和空字符串
if (value == null || (value instanceof String && StringUtils.isBlank((String) value))){
continue;
}
//判断是不是 JSONObject 如果是转化成TreeMap
if (value instanceof JSONObject){
//JSONObject 覆写了toString 所有可以直接调用toString
treeMap.put(entry.getKey(), sortField(JSON.parseObject(value.toString(), Map.class)));
//判断是不是 JSONArray
}
else if (value instanceof JSONArray){
//如果是 强转成 JSONArray 并且遍历它
JSONArray jsonArray = (JSONArray) value;
List<Object> list = new ArrayList<>(jsonArray.size());
for (Object object : jsonArray){
//判断里面的是否是 JSONObject 如果是转化成TreeMap
if (object instanceof JSONObject){
object = sortField(JSON.parseObject(object.toString(), Map.class));
}
//其他基础类型直接放进去
list.add(object);
}
//list 排序方便比较
list.sort(new ListComparator());
treeMap.put(entry.getKey(), list);
}
else {
//其他基础类型直接放进去
treeMap.put(entry.getKey(), value);
}
}
return treeMap;
}
class MapComparator implements Comparator<String> {
@Override
public int compare(String str1, String str2) {
return str1.compareTo(str2);
}
}
class ListComparator implements Comparator<Object> {
@Override
public int compare(Object o1, Object o2) {
//因为这里面不是基础类型就是Map 或者他们的 map的toString方法被复写过 会把所有的key和value组合拼接成字符串
//比如 map.put("key":"value"); toString 会变成 {"key":"value"}
String str1 = o1.toString();
String str2 = o2.toString();
//获得其字符串长度
Integer length1= str1.length();
Integer length2 = str2.length();
//先比较其长度
int i = length1.compareTo(length2);
//如果长度相同 在比较实际字符串
if (i == ){
return str1.compareTo(str2);
}
return i;
}
}
该方法接受一个由json
串转化成的map
。
Map<String, Object> treeMap = sortField(JSON.parseObject(json, Map.class));
fastjson属性排序问题,使用JSONObject.parseObject
fastjson
中,如果需要得到有序的属性排列,有两种方案
Map pramMap = JSONObject.parseObject(reqParams, TreeMap.class);
String serial = JSON.toJSONString(pramMap, SerializerFeature.SortField)
上面这段代码得到的字符串字段就是有序的,但是这段代码有个前提,那就是paramMap
必须是TreeMap
才可以,如果paramMap
是HashMap
,则SerializerFeature.SortField
是不起任何鸟用的,
但是上面代码还有个缺陷,那就是如果属性里面套属性,这个时候第二次的属性的顺序依然是乱的,所以就出现了第二种方案:
Map pramMap = JSONObject.parseObject(reqParams, Feature.OrderedField);
String serial = JSON.toJSONString(pramMap);
这种方案的优势就是解决上面的属性是对象,对象里面的属性顺序问题,因为第一步代码做完之后得到的Map
是有序的jsonObject
对象,然后把这个对象toJSONString
后得到的字符串属性不管多少层属性,都是有序的。