【工具】-diff工具总结--json解析-将json封装到map、list集合-json标准化输出。最全

在公司已经实习一段时间了,最近分到了一个任务是将php转java的重构项目,导师让我做稳定性检测,输入原来和现在的接口,检测两个是否一致,之前了解过postMan软件,但是特定的需求可能还有问题。感觉这个项目让我重新学习了FastJson,下面写一下工具的整理架构

  1. 前端--Vue
  2. 后端--Springboot+IDEA软件
  3. 后端:

              输入--两个除了IP不同其余相同的接口 

              输出--标准的Json

1、Controller-控制层

 @RequestMapping("/check2")
    @ResponseBody
    public Result byJsonMethod(
            @RequestParam("requestUrl") String requestUrl,
            @RequestParam("requestUrl2") String requestUrl2) {
        Date date = new Date();
        JSONObject result = new JSONObject();
        String json_string1 = diffService.getJson_String(requestUrl);
      
        JSONObject jsonObject1 = JSONObject.parseObject(json_string1);
        String json_string2 = diffService.getJson_String(requestUrl2);
        JSONObject jsonObject2 = JSONObject.parseObject(json_string2);
        // JSONObject jsonObject = new JSONObject();
        //将检查结果封装到map集合中

        JSONObject resultByJson = diffService.getResultByJson(jsonObject1, jsonObject2);
//      将两个url结果返回到前端
        if(resultByJson.getJSONObject("diff").size()>=1){

            return ResultGenerator.genOkResult(resultByJson,"两个接口返回值不一致");
        }else {

            return ResultGenerator.genOkResult(resultByJson);
        }
       
    }

(1)调用service层获取两个接口的返回结果以string返回

(2)调用service层getResultByJson检测方法,得到结果检测

(3)判断检测内容是否为空,若为空返回正确Json,否则返回具体信息。

2、Service业务层

<1>方法1:根据传入的接口去请求,获得请求结果

/**
     * 通用方法抽取-将url请求的结果变为String字符串返回
     * @param Url
     * @return
     */
    @Override
    public String getJson_String(String Url) {
        //返回结果
        String res="";
        StringBuffer buffer = new StringBuffer();
        try{
            //创建url,此处可以动态扩展,拼接
            URL url = new URL(Url);
            HttpURLConnection urlCon= (HttpURLConnection)url.openConnection();
            if(200==urlCon.getResponseCode()){
                InputStream is = urlCon.getInputStream();
                InputStreamReader isr = new InputStreamReader(is,"utf-8");
                BufferedReader br = new BufferedReader(isr);
                String str = null;
                while((str = br.readLine())!=null){
                    buffer.append(str);
                }
                br.close();
                isr.close();
                is.close();
                res = buffer.toString();
            }
        }catch(IOException e){
            System.out.println("访问不成功");
        }

        return res;

    }

在这个方法后期可以根据参数自己进行拼接-接口请求,此方法对应Controller层第一层。

<2>根据传入的结果,进行检查,以下为第一次使用的将json封装到Map、list集合等

    /**
     * 将请求的URL变成Json格式传入,输出<错误1:具体位置>这种map集合的格式
     * @param json
     * @return map
     */
    @Override
    public Map<String, String> getResultByJson(String json,String json2) {
//        0.方法返回结果
        Map<String, String> resultMap = new HashMap<String, String>();
//        1、分解第一层
        int i = 1;
        Map<String, Object> map1 = JSONObject.parseObject(json, Map.class);
        Object ss = JSONObject.parseObject(json);
        Map<String, Object> map2 = JSONObject.parseObject(json2, Map.class);
        for (String key : map1.keySet()) {
            // 根据每次得到的map1集合中的key,map2.contains()方法判断是否含有key,
            if (map2.keySet().contains(key)) {
//                如果含有则利用equals方法判断value的值是否相等
//              如果有相同的key,判断是否有嵌套情况或者再次复杂的情况
//                (1)key对应的为数组,数组中嵌套json。
//                (2)key对应的为json。
//                (3)key对应的为json,json再次嵌套数组-json
                resultMap = generalMethod(map1.get(key), map2.get(key), i,resultMap);
                /*
                int status = diffTools.verificationBykey(map1.get(key));

                int status2 = diffTools.verificationBykey(map2.get(key));
//              两种URL虽然key相等,但是对应的value类型不想等,例如一个是数组,另一个是json
                if(status!= status2){
                    resultMap.put("第"+i+"处error","key对应的value类型不一致");
                    continue;
                }
//                两种URL类型相等,都是嵌套了一个数组,需要继续进行解析
                if (status==1){
//                    JSONArray jsonArray1 = JSONArray.parseArray(map1.get(key).toString());
//                    JSONArray jsonArray2 = JSONArray.parseArray(map1.get(key).toString());
//                    将数组结果封装到list<String>集合中
                    List<Object> listString1 = JSONArray.parseArray(map1.get(key).toString(), Object.class);
                    List<Object> listString2 = JSONArray.parseArray(map2.get(key).toString(), Object.class);

                    for (Object arrString1:listString1) {


                    }



                }
//                两种URL类型相等,都是嵌套了一个json,需要继续进行解析
                if(status==2){
                    Map<String, Object> map12 = JSONObject.parseObject(map1.get(key).toString(), Map.class);
                    Map<String, Object> map13 = JSONObject.parseObject(map2.get(key).toString(), Map.class);
                }
//                两种URL类型相等,都是普通的键值对,可以直接判断
                if (status==3){
                    boolean result_value = map1.get(key).equals(map2.get(key));
                    if(result_value==false){
                        resultMap.put("第"+i+"错误","key:"+key+"对应的value不同");
                    }

                }
/*
//                try {
//                    map1.get(key).toString();
//                } catch (Exception e) {
//
//                }
//                if (map1.get(key).equals(map2.get(key))) {
//                    两个json对应的key-value都相等
//                    System.out.println("");
//
//                } else {//添加错误的返回值
//
//                    String s1 = "url1中的key:" + key + "对应的值:" + map1.get(key) + "和在url2不相等!";
//
//                    System.out.println("不相同的地方为值不想等:url1中的key:" + key + "对应的值:" + map1.get(key) + "和在url2返回结果不想等!");
//                }*/
            } else {
                String s2 = "url1中的key:" + key + "在url2不存在";
                resultMap.put(key+"出现错误", s2);
            }
        }
        return resultMap;
    }

    /**
     * 迭代判断公用方法
     * @param o1
     * @param o2
     * @param i
     * @param resultMap
     * @return
     */
    public Map<String,String> generalMethod(Object o1,Object o2,int i,Map resultMap) {
        int status = diffTools.verificationBykey(o1);
        int status2 = diffTools.verificationBykey(o2);
//              两种URL虽然key相等,但是对应的value类型不想等,例如一个是数组,另一个是json
        if (status != status2) {
            resultMap.put("第" + i + "层error", "key对应的value类型不一致");
        }
//                两种URL类型相等,都是嵌套了一个数组,需要继续进行解析
        if (status == 1) {
//      JSONArray jsonArray1 = JSONArray.parseArray(map1.get(key).toString());
//      JSONArray jsonArray2 = JSONArray.parseArray(map1.get(key).toString());
//      将数组结果封装到list<String>集合中
            List<Object> listString1 = JSONArray.parseArray(o1.toString(), Object.class);
            List<Object> listString2 = JSONArray.parseArray(o2.toString(), Object.class);
            if (listString1.size() != listString2.size()) {
                resultMap.put("第" + i + "层error", "长度不一致");
                return resultMap;
            }
            for (int j = 0; j < listString1.size(); j++) {
                resultMap=generalMethod(listString1.get(j), listString2.get(j), i+1,resultMap);
            }
        }
//                两种URL类型相等,都是嵌套了一个json,需要继续进行解析
        if (status == 2) {
            Map<String, Object> map12 = JSONObject.parseObject(o1.toString(), Map.class);
            Map<String, Object> map13 = JSONObject.parseObject(o2.toString(), Map.class);
            if (map12.size() != map13.size()) {
                resultMap.put("第" + i + "层error", "长度不一致");
                return resultMap;
            }
            for (String key : map12.keySet()) {
                // 根据每次得到的map1集合中的key,map2.contains()方法判断是否含有key,
                i++;
                if (map13.keySet().contains(key)) {
                    resultMap = generalMethod(map12.get(key), map13.get(key), i+1,resultMap);
                } else {
                    resultMap.put("", "key不包含");
                }
            }
        }
//      两种URL类型相等,都是普通的键值对,可以直接判断
        if (status == 3) {
            boolean result_value = o1.equals(o2);
            if (result_value == false) {
                resultMap.put("第" + i + "错误", "key对应的value不同");

            }

        }
        return resultMap;
    }

后期对以上处理方式进行了修改,采用了直接使用Json判断,省去了转成map等集合的开销,但是Json转成map等集合仍有值得学习的地方,这里进行保留。

<3>由于Json中嵌套的类型多种多样,包括null、jsonArray、JsonObject等,所以需要判断key对应的value所属的数据类型。抽取为utils工具类

public int verificationBykey(Object value){
        //获取第一个字符
        if(value==null){
            return 0;
        }
        String ac  = value==null?"null":value.toString();

        char a = ac.charAt(0);

        switch (a){
//          开头[,表示嵌套了一个数组
            case '[':
                return 1;
//          开头为{,表示嵌套的是一个JsonObject对象
            case '{':
                return 2;
//          开头为",表示普通值并没有嵌套过程
            default:
                 return 3;

        }

    }

通过以上判断可以处理时采用迭代递归的方法判断Json中是否有嵌套的类型,以及嵌套了什么类型,然后在判断。所以这一步很重要。

<4>封装集合提升为使用JsonObject直接处理方法

/**
     * 使用json方法,不使用map--通用属性的抽取
     * @param o1
     * @param o2
     * @param i
     * @param resultJson
     * @return
     */
    @Override
    public JSONObject generalMethod(Object o1, Object o2, int i, int j,JSONObject resultJson,String original_key) {
        int status  = diffTools.verificationBykey(o1);
        int status2 = diffTools.verificationBykey(o2);
//              两种URL虽然key相等,但是对应的value类型不想等,例如一个是数组,另一个是json
        if (status != status2) {
            resultJson.put(++j+"", "在" + i + "层错误,"+original_key+"对应的值类型不一致。value1:"+o1+";value2:"+o2);
        }
//                两种URL类型相等,都是嵌套了一个数组,需要继续进行解析
        if (status == 1) {
            JSONArray jsonArray1 = JSONArray.parseArray(o1.toString());
            JSONArray jsonArray2 = JSONArray.parseArray(o2.toString());
            if (jsonArray1.size() != jsonArray2.size()) {
                resultJson.put(++j+"", "在"+i+"层错误,结构不一致");
                return resultJson;
            }
            for (int k = 0; k < jsonArray1.size(); k++) {
                //数组不当做嵌套关系,平级关系,所以这里i不在+1。所以key也不需要传入复合状态。
                resultJson=generalMethod(jsonArray1.get(k), jsonArray2.get(k), i,j,resultJson,original_key);
            }
        }
//                两种URL类型相等,都是嵌套了一个json,需要继续进行解析
        if (status == 2) {
            JSONObject jsonObject1 = JSONObject.parseObject(o1.toString());
            JSONObject jsonObject2 = JSONObject.parseObject(o2.toString());

            if (jsonObject1.size() != jsonObject2.size()) {
                resultJson.put(++j+"", "在" + i + "层错误,结构不一致");
                return resultJson;
            }
            for (String key : jsonObject1.keySet()) {
                // 根据每次得到的map1集合中的key,map2.contains()方法判断是否含有key,
                if (jsonObject2.keySet().contains(key)) {
                    resultJson = generalMethod(jsonObject1.get(key), jsonObject2.get(key), i+1,j,resultJson,original_key+":"+key);
                } else {
                    resultJson.put(++j+"", "第" + i + "层错误,接口1中的key:" + key + "  在接口2结果中不存在");
                }
            }
        }
//      两种URL类型相等,都是普通的键值对,可以直接判断
        if (status == 3) {
            boolean result_value = o1.equals(o2);
            if (result_value == false) {
                //考虑如何更友好的显示到前端
                resultJson.put(++j+"-"+original_key,"在" + i + "层错误,"+original_key+"对应的value不同。value1:"+o1+"。value2:"+o2);

                //resultJson.put(original_key,"对应的值不一致");
            }
        }
        return resultJson;
    }

    /**
     *  Json方式-----遍历第一层
     * @param json1
     * @param json2
     * @return
     */
    @Override
    public JSONObject getResultByJson(JSONObject json1, JSONObject json2) {
        //        0.方法返回结果
        JSONObject resultJson = new JSONObject();
        JSONObject resultJson_final = new JSONObject();

        resultJson_final.put("data_api_1",json1);
        resultJson_final.put("data_api_2",json2);
//        1、分解第一层
        int i = 0;
        int j = 1;
        if(json1.size()!=json2.size()){
            resultJson.put(j+"","在"+i+"层错误,二者体系结构不同");
            resultJson_final.put("diff",resultJson);
            return resultJson_final;
        }
        for (String key : json1.keySet()) {
            // 根据每次得到的key,map2.contains()方法判断是否含有key,
            if (json2.keySet().contains(key)) {
                resultJson = generalMethod(json1.get(key), json2.get(key), i+1,j,resultJson,key);
            } else {
                resultJson.put(j+"", "在"+i+"层错误,接口1中的key:" + key + "在接口2不存在");
            }
        }
         resultJson_final.put("diff",resultJson);
        return resultJson_final;
    }

(1)首先判断体系结构是否相同。

(2)若体系结构相同,判断Json格式是哪一种类型:

           key:value ||   key:jsonArray   ||  key:JsonObject

如果是第一种普通键值对形式则直接判断value是否相等,若是后两者需要递归进行判断,直到遇到普通键值对,然后向上返回逐步判断。

3、标准化返回结果

最后将数据标准化输出,创建了两个类

(1)返回的实体类

package com.web.response;

import com.alibaba.fastjson.JSON;

public class Result {
    /**
     * 状态码
     */
    private final Integer code;
    /**
     * 消息
     */
    private final String msg;
    /**
     * 数据内容,比如列表,实体
     */
    private final Object data;
   // private final Object data_api;
    //private final Object data_api2;

    private Result(final Builder builder) {
        this.code = builder.code;
        this.msg = builder.msg;
        this.data = builder.data;
       // this.data_api = builder.data_api;
        //this.data_api2 = builder.data_api2;
    }

    public static class Builder {
        private final Integer code;
        private String msg;
        private Object data;
        private Object data_api;
        private Object data_api2;

        public Builder(final Integer code) {
            this.code = code;
        }

        public Builder msg(final String msg) {
            this.msg = msg;
            return this;
        }
        public Builder data(final Object data) {
            this.data = data;
            return this;
        }
        public Builder data_api(final Object data_api) {
            this.data_api = data_api;
            return this;
        }
        public Builder data_api2(final Object data_api2) {
            this.data_api2 = data_api2;
            return this;
        }

        public Result build() {
            return new Result(this);
        }
    }

    public Integer getCode() {
        return this.code;
    }

    public String getMsg() {
        return this.msg;
    }

    public Object getData() {
        return this.data;
    }



    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}

(2)根据各种情况,封装对应的Result返回对象

package com.web.response;

import org.springframework.http.HttpStatus;

public class ResultGenerator {private static final String DEFAULT_OK_MESSAGE = "OK";
    private static final String DEFAULT_UNAUTHORIZED_MESSAGE = "Need authorized";
    private static final String DEFAULT_METHOD_NOT_ALLOWED_MESSAGE = "Request method incorrect";

    public static Result genOkResult() {
        return new Result.Builder(HttpStatus.OK.value()).msg(DEFAULT_OK_MESSAGE).build();
    }

    public static Result genOkResult(final Object data) {
        return new Result
                .Builder(HttpStatus.OK.value())
                .msg(DEFAULT_OK_MESSAGE)
                .data(data)
                .build();
    }
    public static Result genOkResult(final Object data,String msg) {
        return new Result
                .Builder(HttpStatus.OK.value())
                .msg(msg)
                .data(data)
                .build();
    }
    public static Result genOkResult(final Object data,final Object data_api1,Object data_api2) {
        return new Result
                .Builder(HttpStatus.OK.value())
                .msg(DEFAULT_OK_MESSAGE)
                .data(data)
                .data_api(data_api1)
                .data_api2(data_api2)
                .build();
    }

    public static Result genFailedResult(final String msg) {
        return new Result
                .Builder(HttpStatus.BAD_REQUEST.value())
                .msg(msg)
                .build();
    }

    public static Result genMethodErrorResult() {
        return new Result
                .Builder(HttpStatus.METHOD_NOT_ALLOWED.value())
                .msg(DEFAULT_METHOD_NOT_ALLOWED_MESSAGE)
                .build();
    }

    public static Result genUnauthorizedResult() {
        return new Result
                .Builder(HttpStatus.UNAUTHORIZED.value())
                .msg(DEFAULT_UNAUTHORIZED_MESSAGE)
                .build();
    }

    public static Result genUnauthorizedResult(final String msg) {
        return new Result
                .Builder(HttpStatus.UNAUTHORIZED.value())
                .msg(msg)
                .build();
    }

    public static Result genInternalServerErrorResult(final String url) {
        return new Result
                .Builder(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg("API [" + url + "] internal server error. Please call engineer to debug.")
                .build();
    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值