java json转成list对象 java的json转成string_java json 重复对象引用


我们在接口自动化测试过程中,或多或少会遇到当比较接口返回结果时,如果将结果作为一个整体的对象进行比较,假如断言失败时,那我们将会看到一大坨期望和实际结果数据,很难一眼就看出具体是因为哪一部分不一致而导致的比对失败,这也增加了我们的接口自动化维护成本。

本文主要围绕这一痛点,解决 JsonObject、JSONArray、String、Integer 对象的精确比较问题,并提供统一的Java实现方法 Compare.CompareFactory,希望对大家有所帮助。

先睹为快,让我们直接来看下效果如何,此外,文末附 Python 具体实现设计。

JSONObject 对象的一致性比对

如下,先准备两个测试数据,我们可以看到测试数据的结构还是比较复杂的,其中左侧和右侧不一致的地方共有7处,如黄色框处的位置。


java json转成list对象 java的json转成string_java json 重复对象引用_02


首先看一下,如果直接断言,我们看到的结果是什么样的。


java json转成list对象 java的json转成string_java json转成list对象_03


正如开篇所提,想要找出其中的不同,实在... 简直... 。

然后,使用 Compare.CompareFactory 方法,执行过程中的打印结果如下,我们可以看到每个节点的比较结果都非常清晰的打印出来了,并且key 的描述也是含JSON层级关系的,如 "regional.city[0]"


java json转成list对象 java的json转成string_java json 重复对象引用_04


再然后,看下 Compare.CompareFactory 方法的返回结果,我们将返回对象使用JSONObject.toJSONString 转换成字符串后,如下,resultDetail 属性记录了每个错误节点的期望和实际数据值,wrongNumber 属性统计了错误数量,清晰明了,简单直白。


java json转成list对象 java的json转成string_java json 重复对象引用_05


最后,看下代码,因为我将测试数据放到 yaml 文件中,因为其中部分代码是在加载测试数据。


java json转成list对象 java的json转成string_java json 重复对象引用_06



JSONArray 对象的一致性比对

首先,准备如下两个测试数据,其中左侧和右侧不一致的地方共有 5 处,如黄色框处的位置。


java json转成list对象 java的json转成string_java json 重复对象引用_07


然后,使用 Compare.CompareFactory 方法,执行过程中的打印结果如下:


java json转成list对象 java的json转成string_java json转成list对象_08


再然后,我们看下 Compare.CompareFactory 方法的返回结果,如下:


java json转成list对象 java的json转成string_java json转成list对象_09


最后,我们看下示例代码,因为我将测试数据放到Yaml文件中,所以其中部分代码是在加载测试数据。


java json转成list对象 java的json转成string_java jsonarray转list_10



String、Integer、Long 对象的一致性比对

String、Integer、Long 对象的比对,同样也是使用 Compare.CompareFactory 方法完成,示例代码如下:


java json转成list对象 java的json转成string_java json 重复对象引用_11


因为String、Integer、Long不存在KV映射,因此比较结果中key显示为null。如下:


java json转成list对象 java的json转成string_java json转成list对象_12


还提供了哪些特性?

肯定有小伙伴会问,在做接口返回结果的校验时,并不是全部的数据都需要一一进行比对,比如时间属性,因为每次可能返回的时间不同,但本身不影响结果的准确性,所以不需要进行比较。 那Compare.CompareFactory 方法是否不支持过滤某些属性不比较呢?——那当然是支持的咯,细心的小伙伴 Compare.CompareFactory 的有三个参数,那第三个是干嘛的呢?其实第三个参数就是描述需要过滤的属性的,如果需要过滤多个属性使用英文逗号隔开即可。


java json转成list对象 java的json转成string_java jsonarray转list_13


比如,我们将上图例子中的实际和期望结果不一致的 code、designation、hobby_id、desc 4个属性过滤掉不比较,代码如下。


java json转成list对象 java的json转成string_java json转成list对象_14


运行代码,我们可以看到比对结果中,只存在三处不一致的地方,即实现了过滤比较。


java json转成list对象 java的json转成string_java json转成list对象_15



核心源码


因涉及多个java文件,这里只能贴出核心代码,如下:

import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List;  import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONArray; import org.apache.commons.lang3.StringUtils;  public class Compare {     private static BaseResult baseResult;      /**      * @Description: 更新结果,错误数量计数      * @Param: [parameter]      * @Author:       * @DateTimeFormat: 2020/3/8      */     private static void updateBaseResult(ResultDetail resultDetail) {         // 错误数量统计         baseResult.setWrongNumber(baseResult.getWrongNumber() + 1);          // 填充 RetValue 错误内容         if (baseResult.getResultDetail() == null) {             ArrayList resultDetailArrayList = new ArrayList();             resultDetailArrayList.add(resultDetail);             baseResult.setResultDetail(resultDetailArrayList);         } else {             baseResult.getResultDetail().add(resultDetail);         }     }      /**      * @Description: 字符串比较      * @Param: [parameter]      * @return: void      * @Author: YJiang      * @DateTimeFormat: 2020/3/8      */     private static void compareJson(String actualString, String expectString, String key, String prefix , String ignore) {         boolean status = false;         if (StringUtils.isNotBlank(ignore)) {             List listIgnore = Arrays.asList(ignore.split(","));             status = listIgnore.contains(key);         }         if (!status) {             if (!actualString.equals(expectString)) {                 ResultDetail resultDetail = new ResultDetail(prefix, actualString, expectString, "Value Not Equal");                 updateBaseResult(resultDetail);                 System.out.println(                         "033[1;31m" + "【fail】Key:" + prefix + "     actualJson:" + actualString + "     expectJson:" + expectString + "033[m");              } else {                 System.out.println(                         "033[1;94m" + "【success】Key:" + prefix + "     actualJson:" + actualString + "     expectJson:" + expectString + "033[m");             }         }     }      /**      * @Description: JSONObject 比较      * @Param: [parameter]      * @return: void      * @Author: YJiang      * @DateTimeFormat: 2020/3/8      */     private static void compareJson(JSONObject actualJson, JSONObject expectJson, String key,String prefix, String ignore) {         if (StringUtils.isBlank(prefix)){             prefix = "";         }else {             prefix = prefix + ".";         }          for (String s : expectJson.keySet()) {             key = s;             compareJson(actualJson.get(key), expectJson.get(key), key, prefix + key, ignore);         }     }      /**      * @Description: JSONArray 比较      * @Param: [parameter]      * @return: void      * @Author: YJiang      * @DateTimeFormat: 2020/3/8      */     private static void compareJson(JSONArray actualJsonArray, JSONArray expectJsonArray, String key,String prefix, String ignore) {         if (actualJsonArray != null && expectJsonArray != null) {             if (actualJsonArray.size() == expectJsonArray.size()) {                 Iterator iteratorActualJsonArray = actualJsonArray.iterator();                 if (StringUtils.isBlank(prefix)){                     prefix = "";                 }                 int num = 0;                 for (Object o : expectJsonArray) {                     compareJson(iteratorActualJsonArray.next(), o, key,prefix+"["+num+"]", ignore);                     num ++;                  }             } else {                 ResultDetail resultDetail = new ResultDetail(prefix, actualJsonArray, expectJsonArray, "Length Not Equal");                 updateBaseResult(resultDetail);             }         } else {             if (actualJsonArray == null && expectJsonArray == null) {                 ResultDetail resultDetail = new ResultDetail(prefix, "在 actualJsonArray 中不存在",                     "在 expectJsonArray 中不存在",                     "Both Not Exist");                 updateBaseResult(resultDetail);             } else if (actualJsonArray == null) {                 ResultDetail resultDetail = new ResultDetail(prefix, "在 actualJsonArray 中不存在", expectJsonArray,                     "Other Exist");                 updateBaseResult(resultDetail);             } else {                 ResultDetail resultDetail = new ResultDetail(prefix, actualJsonArray, "在 expectJsonArray 中不存在",                         "Other Exist");                 updateBaseResult(resultDetail);             }         }      }     /**      * @Description: Object 比较      * @Param: [parameter]      * @return: void      * @Author: YJiang      * @DateTimeFormat: 2020/3/8      */     private static void compareJson(Object actualJson, Object expectJson, String key,String prefix, String ignore) {         if (actualJson != null && expectJson != null) {             if (actualJson instanceof JSONObject) {                 compareJson((JSONObject)actualJson, (JSONObject)expectJson, key,prefix, ignore);             } else if (actualJson instanceof JSONArray) {                 compareJson((JSONArray)actualJson, (JSONArray)expectJson, key,prefix, ignore);             } else if (actualJson instanceof String) {                 try {                     String actualJsonToStr = actualJson.toString();                     String expectJsonToStr = expectJson.toString();                     compareJson(actualJsonToStr, expectJsonToStr, key,prefix, ignore);                  } catch (Exception e) {                     ResultDetail resultDetail = new ResultDetail(prefix, actualJson, expectJson, "String 转换发生异常 Key");                     updateBaseResult(resultDetail);                     e.printStackTrace();                 }              } else {                 compareJson(actualJson.toString(), expectJson.toString(), key,prefix, ignore);             }         } else {             if (actualJson == null && expectJson == null) {                 ResultDetail resultDetail = new ResultDetail(prefix, "在actualJson中不存在", "在expectJson中不存在",                     "Both Not Exist");                 updateBaseResult(resultDetail);             } else if (actualJson == null) {                 ResultDetail resultDetail = new ResultDetail(prefix, "在actualJson中不存在", expectJson, "Other Exist");                 updateBaseResult(resultDetail);             } else{                 ResultDetail resultDetail = new ResultDetail(prefix, actualJson, "在expectJson中不存在", "Not Exist");                 updateBaseResult(resultDetail);             }          }      }      /** 非线性安全      * @Description: CompareFactory      * @Param: [parameter]      * @return: void      * @Author: YJiang      * @DateTimeFormat: 2020/3/8      */     public static  BaseResult CompareFactory(T actual, T expect, String ignore) {          Compare.baseResult = new BaseResult();         Compare.compareJson(actual, expect, null,null, ignore);          return Compare.baseResult;     }  }

对了,之前写过JSON 一致性比对的Python实现,有兴趣的同学可以看一下哦 。

Json数据灵活的一致性校验的整体设计与具体实现