废话少说,直接入题。

在面向对象语言中,经常会比较两个对象是否相等,而比较的大多是实体类实例,也就是封装数据的那些类实例,或者是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;
}

比较任意两个JSON串是否相等(比较对象是否相等)JAVA版的更多相关文章

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

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

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

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

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

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

  4. [原创] C# dynamic拼接Json串

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

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

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

  6. 用Newtonsoft将json串转为对象的方法(详解)

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

  7. Json串的字段如果和类中字段不一致,如何映射、转换?

    Json串是我们现在经常会遇到的一种描述对象的字符串格式.在用Java语言开发的功能中,也经常需要做Json串与Java对象之间的转换. fastjson就是经常用来做Json串与Java对象之间的转 ...

  8. [MVC_Json序列化]Json字符串反序列化成C#对象

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

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

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

随机推荐

  1. 提示框(UIAlertController)的使用。

    添加出现在屏幕中间的提示框(也就是之前的UIAlertView): UIAlertController * av = [UIAlertController alertControllerWithTit ...

  2. VS2013中,RDLC设置数据源和参数的界面

    今天打开RDLC文件设置参数和数据源时,始终找不到那个窗口,原来那个窗口叫“报表数据”,在“视图”菜单的最下面! 另外:要在当前窗口时打开的RDLC文件时,视图下面才有该选项!!! 参考:http:/ ...

  3. Selenium2+python自动化18-加载Firefox配置

    前言 有小伙伴在用脚本启动浏览器时候发现原来下载的插件不见了,无法用firebug在打开的页面上继续定位页面元素,调试起来不方便 . 加载浏览器配置,需要用FirefoxProfile(profile ...

  4. Correspondence / ˏkɔris'pɔndәns / dictionary10-800.doc

    I have taken courses in office administration, typing,reports and correspondence writing. Correspond ...

  5. JSON基本用法

    JSON基本用法 2016-08-10 16:42:19   JSON的全称是“JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,独立于语 ...

  6. 将Discuz.net 集成到asp.net

    1,将bbs文件夹拷贝到网站的根目录下: 2,将bbs里面的bin目录,config目录,cache目录,DNT.config文件拷贝到网站根目录下: 3,修改网站web.config文件,在http ...

  7. poj 2551 Ones

    本题的想法很简单,就是模拟手算乘法.不一样的是,需要控制输出的结果:每一位都是由1构成的整数. 代码如下: #include <iostream> using namespace std; ...

  8. Java 读取Properties配置文件

    1.img_url.properties imgurl=http://10.1.19.65:8090 2.Test.java InputStream inputStream = this.getCla ...

  9. ycsb-命令及参数-与生成的负载类型相关

    loadbin/ycsb load mydb -P workloads/workloada -p "mydb.host=127.0.0.1" -p "mydb.port= ...

  10. Linux内核实现中断和中断处理(一)

    Linux实现中断处理 内核是怎么知道应用程序要调用系统调用的呢?或者说应用程序怎么通知系统内核自己需要执行一个系统调用,这是通过软中断实现的,通过引发一个异常来促使系统切换到内核态去执行异常处理程序 ...