java set diff_JAVA 实现json diff

使用java实现复杂结构多层级的json diff

主要思路:遍历json,根据key排序,判断json element类型,如果是jsonArray的话,转成list并排序,并循环验证list中的每个json element是否相等

package service.utils;

import com.google.gson.*;

import org.slf4j.*;

import org.testng.Assert;

import java.util.*;

public class JsonDiffUtil {

private static final JsonParser parser = new JsonParser();

private static final Gson gson = new Gson();

//默认是忽略值比较

private boolean diffValue = false;

private static final Logger logger = LoggerFactory.getLogger(JsonDiffUtil.class);

public JsonDiffUtil(){};

public JsonDiffUtil(boolean diffValue){

this.diffValue = diffValue;

}

/*

* 验证两个json字符串结构是否一致,正反两次比较

*/

public void diff(String exceptJson,String actualJson){

Assert.assertTrue(equals(exceptJson, actualJson));

Assert.assertTrue(equals(actualJson, exceptJson));

}

/**

* 比较两个json字符串是否

*/

public boolean equals(String exceptJson, String actualJson) {

if(exceptJson.equals(actualJson)){

return true;

}

//json String 转 JsonElement

JsonElement exceptJsonElement = parser.parse(exceptJson);

JsonElement actualJsonElement = parser.parse(actualJson);

//按key排序

sort(exceptJsonElement);

sort(actualJsonElement);

return equals(exceptJsonElement, actualJsonElement);

}

private boolean equals(JsonElement except, JsonElement actual) {

if (except.isJsonObject()) {

return equals(except.getAsJsonObject(), actual.getAsJsonObject());

} else if (except.isJsonArray() ) {

return equals(except.getAsJsonArray(), actual.getAsJsonArray());

} else if (except.isJsonPrimitive()) {

return equals(except.getAsJsonPrimitive(), actual.getAsJsonPrimitive());

} else {

logger.info("except= {},actual= {}",except,actual);

return false;

}

}

private boolean equals(JsonObject except, JsonObject actual) {

Set exceptSet = except.keySet();

for (String key : exceptSet) {

JsonElement exceptValue = except.get(key);

JsonElement actualValue = actual.get(key);

if(actualValue == null){

logger.error("not found key:"+key);

return false;

}

if (exceptValue.isJsonArray() && exceptValue.getAsJsonArray().size() != actualValue.getAsJsonArray().size()) {

logger.error("JSON Array size not equal,key is {}",key);

return false;

}

boolean flag = equals(exceptValue, actualValue);

if(!flag){

if(exceptValue.isJsonPrimitive()){

if (diffValue) {

logger.error("value not equal,key is {}, except value is {}, actual value is {}",key,exceptValue,actualValue);

}

else {

logger.error("not found key:"+key);

}

}

return false;

}

}

return true;

}

private boolean equals(JsonArray exceptArray, JsonArray actualArray) {

List exceptList = toSortedList(exceptArray);

List actaulList = toSortedList(actualArray);

for (int i = 0; i < exceptList.size(); i++) {

if (!equals(exceptList.get(i), actaulList.get(i))) {

return false;

}

}

return true;

}

private boolean equals(JsonPrimitive except, JsonPrimitive actual) {

if(!diffValue){

return actual != null;

}

return except.equals(actual);

}

private List toSortedList(JsonArray array) {

List list = new ArrayList<>();

array.forEach(list::add);

list.sort(Comparator.comparing(gson::toJson));

return list;

}

/*

* 根据json key排序

*/

public static void sort(JsonElement je) {

if (je.isJsonNull()) {

return;

}

if (je.isJsonPrimitive()) {

return;

}

if (je.isJsonArray()) {

JsonArray array = je.getAsJsonArray();

Iterator it = array.iterator();

while (it.hasNext()) {

sort(it.next());

}

return;

}

if (je.isJsonObject()) {

Map tm = new TreeMap(getComparator());

for (Map.Entry en : je.getAsJsonObject().entrySet()) {

tm.put(en.getKey(), en.getValue());

}

for (Map.Entry en : tm.entrySet()) {

je.getAsJsonObject().remove(en.getKey());

je.getAsJsonObject().add(en.getKey(), en.getValue());

sort(en.getValue());

}

return;

}

}

private static Comparator getComparator() {

return String::compareTo;

}

}

用到的依赖包

org.testng

testng

6.9.8

com.google.code.gson

gson

2.8.5

org.slf4j

slf4j-log4j12

1.7.25

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值