java 比较两个json对象_比较任意两个JSON串是否相等(比较对象是否相等)JAVA版

废话少说,直接入题。

在面向对象语言中,经常会比较两个对象是否相等,而比较的大多是实体类实例,也就是封装数据的那些类实例,或者是Map、List互相嵌套成的复杂数据结构。

比较对象是否相等,常见的思路是重写equals方法,但鉴于对象的种类多变,嵌套层次复杂,仅仅靠重写equals是很难实现的。

小菜的思路是可以把对象序列化,由于这些对象均是用来表达数据结构,因此可以直接转换成JSON字符串,用字符串来描述数据结构,避免实现Serializable接口。将对象序列化成字符串后,比较是否相等就相对简单了。

小菜提供的正是比较两个JSON串是否相等的方法,并不是说JSON串完全一样才叫相等,对于List(或数组)结构而言,如果仅仅是元素排列顺序不同,也是相等的。

为了保证方法的准确性,请传入标准的JSON串,也就是说key也要加双引号。用过js的童鞋可能会被误导:我在js中写的JSON,key可以不加双引号啊!实际上,你在js中写的是js语言的Object,并不是JSON,只不过它的语法和JSON非常像而已,JSON仅仅是一种字符串规范,而且真正的JSON只有一种,那就是key加了双引号的!

另外,此方法不依赖任何第三方包。

最后声明,由于数据结构复杂,小菜对这个方法不可能进行遍历性测试,所以这个方法的准确性有待考究,请谨慎使用!如有问题,欢迎反馈!

import java.util.regex.Matcher;

import java.util.regex.Pattern;

/**

* 比较两个json串是否相同

* @param j1 第一个json串(json串中不能有换行)

* @param j2 第二个json串(json串中不能有换行)

* @return 布尔型比较结果

*/

public static boolean jsonEquals(String j1,String j2){

//将json中表示list的[]替换成{}。思想:只保留层次结构,不区分类型

//这样直接替换,可能会导致某些value中的符号也被替换,但是不影响结果,因为j1、j2的变化是相对的

j1 = j1.replaceAll("\\[", "{");

j1 = j1.replaceAll("]", "}");

j2 = j2.replaceAll("\\[", "{");

j2 = j2.replaceAll("]", "}");

//将json中,字符串型的value中的{},字符替换掉,防止干扰(并没有去除key中的,因为不可能存在那样的变量名)

//未转义regex:(?<=:")(([^"]*\{[^"]*)|([^"]*\}[^"]*)|([^"]*,[^"]*))(?=")

Pattern pattern = Pattern.compile("(?<=:\")(([^\"]*\\{[^\"]*)|([^\"]*\\}[^\"]*)|([^\"]*,[^\"]*))(?=\")");

j1 = cleanStr4Special(j1, pattern.matcher(j1));

j2 = cleanStr4Special(j2, pattern.matcher(j2));

//转义字符串value中的空格

//未转义regex:"[^",]*?\s+?[^",]*?"

pattern = Pattern.compile("\"[^\",]*?\\s+?[^\",]*?\"");

j1 = cleanStr4Space(j1, pattern.matcher(j1));

j2 = cleanStr4Space(j2, pattern.matcher(j2));

//现在可以安全的全局性去掉空格

j1 = j1.replaceAll(" ", "");

j2 = j2.replaceAll(" ", "");

//调用递归方法

return compareAtom(j1,j2);

}

/**

* 比较字符串核心递归方法

* @param j1

* @param j2

* @return

*/

private static boolean compareAtom(String j1,String j2){

if(!j1.equals("?:\"?\"")){

//取出最深层原子

String a1 = j1.split("\\{",-1)[j1.split("\\{",-1).length-1].split("}",-1)[0];

String a2 = j2.split("\\{",-1)[j2.split("\\{",-1).length-1].split("}",-1)[0];

String j2_ = j2;

String a2_ = a2;

//转换成原子项

String i1[] = a1.split(",");

//在同级原子中寻找相同的原子

while(!a2.startsWith(",") &&

!a2.endsWith(",") &&

a2.indexOf(":,")<0 &&

a2.indexOf(",,")<0

){

//遍历消除

for(String s : i1){

a2_ = a2_.replace(s,"");

}

//此时a2_剩下的全是逗号,如果长度正好等于i1的长度-1,说明相等

if(a2_.length() == i1.length-1){

//相等则从j1、j2中消除,消除不能简单的替换,因为其他位置可能有相同的结构,必须从当前位置上消除

int index = 0;

index = j1.lastIndexOf("{" + a1 + "}");

j1 = j1.substring(0, index)+j1.substring(index).replace("{" + a1 + "}", "?:\"?\"");

index = j2.lastIndexOf("{" + a2 + "}");

j2 = j2.substring(0, index)+j2.substring(index).replace("{" + a2 + "}", "?:\"?\"");

//递归

return compareAtom(j1, j2);

}else{

//寻找下一个同级原子

j2_ = j2_.replace("{" + a2 + "}", "");

a2 = j2_.split("\\{",-1)[j2_.split("\\{",-1).length-1].split("}",-1)[0];

a2_ = a2;

}

}

return false;

}else{

//比较是否相同

return j1.equals(j2);

}

}

/**

* json字符串特殊字符清理辅助方法

* @param j 需要清理的json字符串

* @param matcher 正则表达式匹配对象

* @return 净化的json串

*/

private static String cleanStr4Special(String j,Matcher matcher){

String group = "";

String groupNew = "";

while(matcher.find()){

group = matcher.group();

groupNew = group.replaceAll("\\{", "A");

groupNew = groupNew.replaceAll("}", "B");

groupNew = groupNew.replaceAll(",", "C");

j = j.replace(group, groupNew);

}

return j;

}

/**

* json串字符串类型的value中的空格清理辅助方法

* @param j 需要清理的json字符串

* @param matcher 正则表达式匹配对象

* @return 净化的json串

*/

private static String cleanStr4Space(String j,Matcher matcher){

String group = "";

String groupNew = "";

while(matcher.find()){

group = matcher.group();

groupNew = group.replaceAll(" ", "S");

j = j.replace(group, groupNew);

}

return j;

}

9-2、大型项目的接口自动化实践记录----递归判断两个json串是否相等

1.已知json串构成的情况下判断 先构造一下场景,假设已经把各个数据都移除掉不对比的字段 图1 预期.实际结果,复杂接口返回多层嵌套json时,同下 图2 预期.实际结果值为:{child_json ...

类对象序列化为json串,json串反序列化为类对象

1.类对象序列化为json串: 方法一: class P(object): def __init__(self,name,age,sex): self.name=name self.age=age s ...

python实现比对两个json串的方法

记录瞬间 前段时间为了解决一些实际问题,引出了要对json字符串进行比对的需求. 觉得有意义,作以简单记录. # 比对数据 def compare_data(set_key, src_data, ds ...

&lbrack;原创&rsqb; C&num; dynamic拼接Json串

using Newtonsoft.Json; 之前拼接两个json串,是用的这样的代码 , json1.Length - ); json2 = json2.Insert(json2 - , tmp); ...

Java开发笔记(一百零八)JSON串的定义和解析

前面提到URL尾巴支持添加请求参数,具体格式形如“参数A名称=A参数值&参数B名称=B参数值”,可是这种格式只能传递简单的键值对信息,不能传递结构化数据,也无法传递数组形式的参数,因而它不适用 ...

用Newtonsoft将json串转为对象的方法&lpar;详解&rpar;

首先,将json串转为一个JObject对象: JObject jo = (JObject)JsonConvert.DeserializeObject(CurrentSelectedItemReq) ...

&lbrack;MVC&lowbar;Json序列化&rsqb;Json字符串反序列化成C&num;对象

上一篇中有Json序列化相关问题得到了解决. 那么结果集为Json串时,如何将Json串转成C#对象呢? 现举例说明: -现有如下字符串数据 string k = "{\"ring ...

spring入门(七)【springMVC返回json串】

现在多数的应用为了提高交互性多使用异步刷新,即在不刷新整个页面的情况下,只刷新局部,局部刷新用得最多就是ajax,ajax和后台进行交互的数据格式使用的最多的是JSON,这里简单描述,在springm ...

关于遍历javascript 中的json串浏览器输出的结果不统一的情况

我们在做项目的时候经常会用到javascript的json. 首先说一下javascript的json串是什么,json串属于javascript的一个对象,有键和值对应的对象. 一般的格式是: a ...

随机推荐

CodeForces 743B Chloe and the sequence &lpar;递归&rpar;

题意:给定n和k,求第n个序列中第k个数是多少,序列是这样构造,原来只有1,然后再copy一遍放在到后面再在中间放上一个没有出现过的最小整数,就变成了 121,下次就成了1213121. 析:很明显是 ...

Codeforces Round &num;360 &lpar;Div&period; 1&rpar; D&period; Dividing Kingdom II 并查集求奇偶元环

D. Dividing Kingdom II   Long time ago, there was a great kingdom and it was being ruled by The Grea ...

jsp分页

UEP-标签

这里的标签都是常用不好理解的: formatfunc="showFormatNumer" 显示数字在页面上 ockedcolumnnum="6" 几列是不动的 ...

9&period; Fizz Buzz 问题

Description Given number n. Print number from 1 to n. But: when number is divided by 3, print " ...

C&num; 判断一个文本文件的编码格式(转载)

文件的字符集在Windows下有两种,一种是ANSI,一种Unicode.对于Unicode,Windows支持了它的三种编码方式,一种是小尾编码(Unicode),一种是大尾编码(BigEndian ...

把一个List&lt&semi;T&gt&semi;的数据复制至另一个List&lt&semi;T&gt&semi;

把一个数据集List复制至到另一个数据集List. 方法一,可以使用循环,然后把每一个T添加至另一个集合中去: public void ListDemo() { , ...

Mybatis标签bind用法

Mybatis使用bind元素进行模糊查询,不用在乎数据库是mysql还是oracle从而提高可移植性 使用bind元素传递多个参数 public List findSt ...

bash 定时任务

time1=$(date +%s -d '2014-01-13 22:46:05') for((;;)) do time2=$(date +%s) time3=$((time1 - time2)) ] ...

ReentrantLock与synchronized

1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O ...


版权声明:本文为weixin_39785858原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。