在做软件和网络测试的时候,经常需要对排版格式与内部结构顺序不固定的json对象进行分析对比,而json基本语法下,同样的一个json对象,字符串变化可以千变万化,json内各个层字段顺序调转,排版变化,打乱顺序的json数组+多层嵌套,等等各种因素,都会造成对比上的困难。
以下由浅及深谈谈几种方法:(一共五种方法,四和五是无缺陷方法,将json对象转换成多叉树,再对多叉树的各个父节点的子节点左右顺序进行hashCode大小排序,这样不管json顺序或者排版如何变化,最终都将生成唯一的json字符串)
一.字符串对比,外加正则方式对比,因为json字符串可变化方式太多,出错率过高略过不谈。
二.使用json库将json字符串转换成对象,这时候可以完全排除掉空格和换行等等纯排版原因造成的差异.
如需更进一步对比,需要转换为json对象后进行递归取出所有键值对,然后通过遍历map对比,缺陷是当存在同名字段或者存在json数组的时候会出现冲突的问题,这个方法适合json层数不多或者不存在同名字段的情况.
三. 使用net.sf.json包,由于net.sf.json包在构造json对象的时候,会在内部进行有序化调整,所以等价的json对象生成的hashCode是完全一致的,可以直接使用 JSONObject.hashCode()对比,而其它包如:com.google.gson包与 vertx.core.json 包无法使用该方法,顺序稍加变化就会改变hashCode.
这是库与库之间构造json对象的数据结构差异.
以下设置了两层嵌套的内部顺序不同但是等价的json字符串
String a= "{\n" +
" \"obj_1\": \"name\",\n" +
" \"field_1\": \"11\",\n" +
" \"list_1\": [\n" +
" {\n" +
" \"obj_2.1\": \"obj_2.1\",\n" +
" \"field_2.1\": \"21\"\n" +
" },\n" +
" {\n" +
" \"obj_2.2\": \"obj_2.2\",\n" +
" \"field_2.2\": \"22\"\n" +
" },\n" +
"\t\t[ \n" +
"\t\t{\n" +
" \"obj_2.3.1\": \"obj_2.3.1\",\n" +
" \"field_2.3.1\": \"231\"\n" +
" },\n" +
" {\n" +
" \"obj_2.3.2\": \"obj_2.3.2\",\n" +
" \"field_2.3.2\": \"232\"\n" +
" }\n" +
"\t\t\n" +
"\t\t]\n" +
" ]\n" +
"}";
String b="{\n" +
" \"field_1\": \"11\",\n" +
" \"obj_1\": \"name\",\n" +
" \"list_1\": [\n" +
" \n" +
" {\n" +
"\t\t \"field_2.2\": \"22\",\n" +
" \"obj_2.2\": \"obj_2.2\"\n" +
" },\n" +
"\t\t\n" +
"\t\t[ \n" +
"\t\t{\n" +
" \"obj_2.3.1\": \"obj_2.3.1\",\n&#