首先,我們舉個例子來對兩個Json格式進行比較
第一個Json格式:
{"singleway":[],"multiway":{"channelSlave":[{"name":"aa1","channel0name":"dd1","id":"1111111113"},{"name":"aa2","channel0name":"dd1","id":"1111111112"}],"channelMaster":{"name":"aa","channel0name":"dd","id":"1111111111"}}}
第二Json格式:
{"singleway":[],"multiway":{"channelSlave":[{"name":"aa2","channel0name":"dd1","id":"1111111112"},{"name":"aa1","channel0name":"dd1","id":"1111111113"}],"channelMaster":{"name":"bb","channel0name":"dd","id":"1111111111"}}}
由此我們可以看到,兩個Json格式的不同點在於 channelSlave作為key的值中,兩個{} 內的順序是不同的,channelMaster中的name字段的值是不同的。
此時我們來對兩個Json格式進行比較,規則為:channelSlave中的值不同,我們可以看做是不影響整體的內容,則可認為是等價的,channelMaster中的name字段值不同,則
兩個Json為不同。
首先我們隊這個Json格式進行轉化,轉化為Map<String,Object> Object = List<Object> or Map<String,Object>
代碼如下:
1、定義靜態工具類 ,解析Json格式數據為指定類型
public static <T> T readJsonToObject(String jsonString, TypeReference<T> tr) {
ObjectMapper objectMapper = new ObjectMapper();
if (jsonString == null || "".equals(jsonString)) {
return null;
} else {
try {
return (T) objectMapper.readValue(jsonString, tr);
} catch (Exception e) {
logger.debug("json error:" + e);
}
}
return null;
}
2、調用工具類,對Json進行解析,解析為Map<String,Object>格式數據
String jsonData = "{\"singleway\":[],\"multiway\":{\"channelSlave\":[{\"name\":\"aa1\",\"channel0name\":\"dd1\",\"id\":\"1111111113\"},{\"name\":\"aa1\",\"channel0name\":\"dd1\",\"id\":\"1111111112\"}],\"channelMaster\":{\"name\":\"aa\",\"channel0name\":\"dd\",\"id\":\"1111111111\"}}}";
Map<String, Object> requestMap = JsonUtils.readJsonToObject(jsonData, new TypeReference<Map<String, Object>>() {
});
3、定義Map比較的工具類,通過google的guava表達是中的 Maps.difference(map1,map2)方法進行比較,單此方法可比較正常的Map和String內容,對於List方式的比較,同時進行了數值和list內容順序的比較,顯然不符合我們的匹配規則,所以我們要對這個方法配合List的containAll方法進一步做封裝。代碼如下:
public static boolean compareMap(Map<String, Object> leftMap, Map<String, Object> rightMap) {
MapDifference<String, Object> difference = Maps.difference(leftMap, rightMap);
//獲取所有不同點
Map<String, MapDifference.ValueDifference<Object>> differenceMap = difference.entriesDiffering();
Iterator diffIterator = differenceMap.entrySet().iterator();
if (diffIterator.hasNext()) {
Map.Entry entry = (java.util.Map.Entry) diffIterator.next();
MapDifference.ValueDifference<Object> valueDifference = (MapDifference.ValueDifference<Object>) entry.getValue();
System.out.println("left: " + valueDifference.leftValue());
System.out.println("right: " + valueDifference.rightValue());
//處理結果是否為map,則遞歸執行比較規則
if (valueDifference.leftValue() instanceof Map && valueDifference.rightValue() instanceof Map) {
boolean equal = compareMap((Map<String, Object>) valueDifference.leftValue(), (Map<String, Object>) valueDifference.rightValue());
if (!equal) {
return false;
}
}
//如果處理結果為list,則通過list方式處理 - 若list中值相同,但是順序不同,則認為兩個list相同
if (valueDifference.leftValue() instanceof List && valueDifference.rightValue() instanceof List) {
boolean equal = ((List) valueDifference.leftValue()).containsAll((List) valueDifference.rightValue());
if (!equal) {
return false;
}
}
//如果處理最終結果為字符串,則停止比較
if (valueDifference.leftValue() instanceof String && valueDifference.rightValue() instanceof String){
return false;
}
}
//若B中有A中不存在的值,則認為不同
Map<String, Object> onlyOnRightMap = difference.entriesOnlyOnRight();
if (onlyOnRightMap != null && !onlyOnRightMap.isEmpty()){
return false;
}
return true;
}
由此可間接性的比較兩個Json的一致性。
代碼中需要引入Jar包,本實例通過maven構建,則地址如下:
<properties>
<jackson.version>2.7.2</jackson.version>
</properties>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>