共计 7630 个字符,预计需要花费 20 分钟才能阅读完成。
背景
在开发中有时候会遇到两个 Json 对象要比对内容是否一致的问题,比如如下两个 JSON,只是部分顺序打乱
{ | |
"code": "19N3L08", | |
"code1": "3110100252", | |
"code2": "TX3110-014-160097", | |
"code3": "3100", | |
"code4": "3110", | |
"code5": "LEHY-MRL-II", | |
"msgList": [ | |
{ | |
"message": "B32053A20", | |
"message1": "TSXB3200", | |
"message2": "B320" | |
}, | |
{ | |
"message": "B33053A20", | |
"message1": "TSXB3300", | |
"message2": "B330" | |
} | |
] | |
} |
{ | |
"code4": "3110", | |
"code2": "TX3110-014-160097", | |
"code1": "3110100252", | |
"code": "19N3L08", | |
"code3": "3100", | |
"code5": "LEHY-MRL-II", | |
"msgList": [ | |
{ | |
"message": "B33053A20", | |
"message1": "TSXB3300", | |
"message2": "B330" | |
}, | |
{ | |
"message": "B33053A20", | |
"message1": "TSXB3300", | |
"message2": "B330" | |
} | |
] | |
} |
主要思路
1. 使用反射获取到 Result.class 的所有 get 方法,循环遍历比对两个对象,如果对象的内容相等则返回 true
private boolean checkEleInfoEqual2(Result strJson, Result tarJson) { | |
boolean result = true; | |
try {for (Field field : Result.class.getDeclaredFields()) {String name = field.getName(); | |
Method m = Result.class.getMethod("get" + upperCase1th(name)); | |
if ((m.invoke(strJson) instanceof String) && !strEquals((String) m.invoke(strJson), (String) m.invoke(tarJson))) {result = false;} | |
} | |
result = result && listEquals(strJson.getMsgList(), tarJson.getMsgList()); | |
} catch (Exception e) { | |
result = false; | |
e.printStackTrace();} | |
System.out.println(result); | |
return result; | |
} |
2. 重写 Result.class 和 Msg.class 中的 equals 方法,如果对象的内容相等,则返回 true
重写了 equals 方法后,可以直接将两个 Result 对象使用 equals 方法进行判断对象的内容相等,对于对象中的 List 结构则可以使用 List 的 contains 方法判断对象是否在 List 中,原理是在 contains 方法在 ArrayList 中通过 indexOf 比对数据,indexOf 中遍历数组使用重写过的 equals 方法判断。
public boolean contains(Object o) {return indexOf(o) >= 0; | |
} | |
public int indexOf(Object o) {if (o == null) {for (int i = 0; i < size; i++) | |
if (elementData[i]==null) | |
return i; | |
} else {for (int i = 0; i < size; i++) | |
if (o.equals(elementData[i])) | |
return i; | |
} | |
return -1; | |
} |
BeanEqual
package com.example.json; | |
import com.alibaba.fastjson.JSONObject; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.util.List; | |
/** | |
* @Description: | |
* @author: wei.wang | |
* @since: 2019/11/13 15:36 | |
* @history: 1.2019/11/13 created by wei.wang | |
*/ | |
public class BeanEqual { | |
private static String strJson = "{\n" + | |
"\"code\": \"19N3L08\",\n" + | |
"\"code1\": \"3110100252\",\n" + | |
"\"code2\": \"TX3110-014-160097\",\n" + | |
"\"code3\": \"3100\",\n" + | |
"\"code4\": \"3110\",\n" + | |
"\"code5\": \"LEHY-MRL-II\",\n" + | |
"\"msgList\": [\n" + | |
"{\n" + | |
"\"message\": \"B32053A20\",\n" + | |
"\"message1\": \"TSXB3200\",\n" + | |
"\"message2\": \"B320\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"B33053A20\",\n" + | |
"\"message1\": \"TSXB3300\",\n" + | |
"\"message2\": \"B330\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"B37053A2019\",\n" + | |
"\"message1\": \"TSXB37002\",\n" + | |
"\"message2\": \"B370\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"F31053A20\",\n" + | |
"\"message1\": \"TSXF3100\",\n" + | |
"\"message2\": \"F310\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"F31053A20\",\n" + | |
"\"message1\": \"TSXF3100\",\n" + | |
"\"message2\": \"F380\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"F31053A20\",\n" + | |
"\"message1\": \"TSXF3100\",\n" + | |
"\"message2\": \"F300\"\n" + | |
"}\n" + | |
"]\n" + | |
"}"; | |
private static String tarJson = "{\n" + | |
"\"code4\": \"3110\",\n" + | |
"\"code2\": \"TX3110-014-160097\",\n" + | |
"\"code1\": \"3110100252\",\n" + | |
"\"code\": \"19N3L08\",\n" + | |
"\"code3\": \"3100\",\n" + | |
"\"code5\": \"LEHY-MRL-II\",\n" + | |
"\"msgList\": [\n" + | |
"\t {\n" + | |
"\"message\": \"B33053A20\",\n" + | |
"\"message1\": \"TSXB3300\",\n" + | |
"\"message2\": \"B330\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"B37053A2019\",\n" + | |
"\"message1\": \"TSXB37002\",\n" + | |
"\"message2\": \"B370\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"F31053A20\",\n" + | |
"\"message1\": \"TSXF3100\",\n" + | |
"\"message2\": \"F300\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"B32053A20\",\n" + | |
"\"message1\": \"TSXB3200\",\n" + | |
"\"message2\": \"B320\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"F31053A20\",\n" + | |
"\"message1\": \"TSXF3100\",\n" + | |
"\"message2\": \"F310\"\n" + | |
"},\n" + | |
"{\n" + | |
"\"message\": \"F31053A20\",\n" + | |
"\"message1\": \"TSXF3100\",\n" + | |
"\"message2\": \"F380\"\n" + | |
"}\n" + | |
"]\n" + | |
"}"; | |
public static void main(String[] args) { | |
// 将获取到的 JSON 转为 Result 对象 | |
Result r1 = JSONObject.parseObject(strJson, Result.class); | |
Result r2 = JSONObject.parseObject(tarJson, Result.class); | |
System.out.println(strJson); | |
System.out.println(tarJson); | |
BeanEqual test = new BeanEqual(); | |
test.checkEleInfoEqual2(r1, r2); | |
} | |
public static boolean listEquals(List<Msg> l1, List<Msg> l2) { | |
boolean result = true; | |
if (l1.size() != l2.size()) { | |
result = false; | |
System.out.println("行数据量不一致"); | |
} | |
for (Msg msg : l1) {if (!l2.contains(msg)) { | |
result = false; | |
System.out.println(msg.getMessage() + "数据不一致"); | |
} else {l2.remove(msg); | |
} | |
} | |
if (l2.size() > 0) {result = false;} | |
return result; | |
} | |
/** | |
* 重写 equals 方法 | |
* | |
* @param strJson | |
* @param tarJson | |
*/ | |
private void checkEleInfoEqual(Result strJson, Result tarJson) {System.out.println(strJson.equals(tarJson)); | |
} | |
/** | |
* 反射获取值 | |
* | |
* @param strJson | |
* @param tarJson | |
*/ | |
private boolean checkEleInfoEqual2(Result strJson, Result tarJson) { | |
boolean result = true; | |
try {for (Field field : Result.class.getDeclaredFields()) {String name = field.getName(); | |
Method m = Result.class.getMethod("get" + upperCase1th(name)); | |
if ((m.invoke(strJson) instanceof String) && !strEquals((String) m.invoke(strJson), (String) m.invoke(tarJson))) {result = false;} | |
} | |
result = result && listEquals(strJson.getMsgList(), tarJson.getMsgList()); | |
} catch (Exception e) { | |
result = false; | |
e.printStackTrace();} | |
System.out.println(result); | |
return result; | |
} | |
/** | |
* 首字符大写 | |
* | |
* @param str | |
* @return | |
*/ | |
public static String upperCase1th(String str) {return str.substring(0, 1).toUpperCase() + str.substring(1); | |
} | |
/** | |
* 字符串相等 | |
* | |
* @param str | |
* @param tar | |
* @return | |
*/ | |
public static boolean strEquals(String str, String tar) { | |
// 都为空,或者都不为空且相等,数字判断 | |
if (isStrEmpty(str) && isStrEmpty(tar) || (!isStrEmpty(str) && !isStrEmpty(tar) && (str.equals(tar) || numberEqual(str, tar)))) {return true;} | |
return false; | |
} | |
/** | |
* 字符是否为空 | |
* | |
* @param str | |
* @return | |
*/ | |
public static boolean isStrEmpty(String str) {return str == null || str.trim().length() == 0;} | |
/** | |
* 校验数字相等 2.0 2.00 2 | |
* | |
* @param str | |
* @param tar | |
* @return | |
*/ | |
public static boolean numberEqual(String str, String tar) { | |
try {double strNum = Double.valueOf(str); | |
double tarNum = Double.valueOf(tar); | |
return strNum == tarNum; | |
} catch (Exception e) { | |
// 如果抛出异常,返回 False | |
return false; | |
} | |
} | |
} |
Msg
package com.example.json; | |
/** | |
* @Description: | |
* @author: wei.wang | |
* @since: 2019/11/13 15:33 | |
* @history: 1.2019/11/13 created by wei.wang | |
*/ | |
public class Msg { | |
private String message; | |
private String message1; | |
private String message2; | |
public String getMessage() {return message;} | |
public void setMessage(String message) {this.message = message;} | |
public String getMessage1() {return message1;} | |
public void setMessage1(String message1) {this.message1 = message1;} | |
public String getMessage2() {return message2;} | |
public void setMessage2(String message2) {this.message2 = message2;} | |
@Override | |
public boolean equals(Object obj) {return BeanEqual.strEquals(message, ((Msg) obj).getMessage()) && | |
BeanEqual.strEquals(message1, ((Msg) obj).getMessage1()) && | |
BeanEqual.strEquals(message2, ((Msg) obj).getMessage2()); | |
} | |
} |
Result
package com.example.json; | |
import java.util.List; | |
/** | |
* @Description: | |
* @author: wei.wang | |
* @since: 2019/11/13 15:33 | |
* @history: 1.2019/11/13 created by wei.wang | |
*/ | |
public class Result { | |
private String code; | |
private String code1; | |
private String code2; | |
private String code3; | |
private String code4; | |
private String code5; | |
private List<Msg> msgList; | |
public String getCode() {return code;} | |
public void setCode(String code) {this.code = code;} | |
public String getCode1() {return code1;} | |
public void setCode1(String code1) {this.code1 = code1;} | |
public String getCode2() {return code2;} | |
public void setCode2(String code2) {this.code2 = code2;} | |
public String getCode3() {return code3;} | |
public void setCode3(String code3) {this.code3 = code3;} | |
public String getCode4() {return code4;} | |
public void setCode4(String code4) {this.code4 = code4;} | |
public String getCode5() {return code5;} | |
public void setCode5(String code5) {this.code5 = code5;} | |
public List<Msg> getMsgList() {return msgList;} | |
public void setMsgList(List<Msg> msgList) {this.msgList = msgList;} | |
// 重写 Result 的 equals 方法,如果内容相等则返回 true | |
@Override | |
public boolean equals(Object obj) {return BeanEqual.strEquals(code, ((Result) obj).getCode()) && | |
BeanEqual.strEquals(code1, ((Result) obj).getCode1()) && | |
BeanEqual.strEquals(code2, ((Result) obj).getCode2()) && | |
BeanEqual.strEquals(code3, ((Result) obj).getCode3()) && | |
BeanEqual.strEquals(code4, ((Result) obj).getCode4()) && | |
BeanEqual.strEquals(code5, ((Result) obj).getCode5()) && | |
BeanEqual.listEquals(msgList, ((Result) obj).getMsgList()); | |
} | |
} |
正文完
发表至: java
2019-11-13