当前位置: 首页 > news >正文

HashMap实现通用的Request和Response及解析非标准JSON

通过HashMap实现通用response和request、自建map转JSON工具类

一、前言

​ 还是一样的,不想听笔者叨叨的点击右侧目录跳转到代码部分,自取完对你有帮助的点个免费的收藏和赞吧,咱就是说!因为畅捷通的开放平台的某个API他的输入参数在文档中是固定的,但是他的输出参数直接就是个Object,完事里面输出出来还是一堆数据,笔者原来也没有尝试自己搭建自己的通用类型的response和request,头大啊,提交总部希望总部开发支持,最后想了想总部上次也没说什么,直接回了个”无脚本“,还是自己弄出来的,干脆自己弄吧!然后就给捣鼓了半天捣鼓出来了;

​ 其实其中最难弄的就是解析JSON工具类,字符分割真麻烦,最后还好给弄出来了,废话少叙,一起看看代码吧!

二、先实现具体的一个业务接口

1111111

首先其实我是通过新建了个通用报表的一个类型,由简入难,先写出一个具体的再去给他改成通用的,因为访问的畅捷通开放平台的API接口其实是一样的,只是可以通过RequestBody的调整去获取不同报表的参数;

这个的代码如下:

/**
     * 获取收发存汇总表
     *
     * @param username
     * @param password
     * @param map
     * @return
     * @throws ChanjetApiException
     */
    @ApiOperation(value = "获取收发存汇总表", httpMethod = "POST")
    @PostMapping("/report/SaleDeliveryDetail")
    public SaleDeliveryDetailReportResponse getSaleDeliveryDetailReport(@RequestHeader("username") String username, @RequestHeader("password") String password, @RequestBody LinkedHashMap<String, Object> map) throws ChanjetApiException {
        Object request = map.get("request");
        SaleDeliveryDetailReportRequest saleDeliveryDetailReportRequest = new SaleDeliveryDetailReportRequest();
        saleDeliveryDetailReportRequest.setAppKey(appKey);
        saleDeliveryDetailReportRequest.setAppSecret(appSecret);
        saleDeliveryDetailReportRequest.setOpenToken(accessToken);
        saleDeliveryDetailReportRequest.setRequestUri("/tplus/api/v2/reportQuery/GetReportData");
        saleDeliveryDetailReportRequest.setBizContent(new SaleDeliveryDetailReportContent(RequestParserUtils.parseRequest(request)));
        return chanjetClient.execute(saleDeliveryDetailReportRequest);
    }

主要还是要关注转换类,要将他转化类转换为对应的畅捷通对应API的入参标准的Object:

package com.chanjet.magic.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.chanjet.magic.dto.ReportGroupItem;
import com.chanjet.magic.dto.ReportOpenApiRequest;
import com.chanjet.magic.dto.ReportSearchItem;

import java.util.ArrayList;
import java.util.List;
/**
 * ClassName: RequestParserUtils
 * Package: com.chanjet.magic.utils
 * Description: 将json字符串转换为标准JSON字符串,将取到的map格式的json数据串塞入对应的实体类中,这样再用实体类去塞入对应的Content中去;
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 12:19
 * @Version 1.0.0
 */
public class RequestParserUtils {

    public static ReportOpenApiRequest parseRequest(Object request) {
        try {
            String json = convertToJson(request.toString());
            System.out.println("JSON 内容: " + json);
            JSONObject requestJson = JSON.parseObject(json);

            ReportOpenApiRequest data = new ReportOpenApiRequest();
            data.setReportName(requestJson.getString("ReportName"));
            data.setPageIndex(requestJson.getString("PageIndex"));
            data.setPageSize(requestJson.getString("PageSize"));
            data.setReportTableColNames(requestJson.getString("ReportTableColNames"));

            // 处理 SearchItems
            JSONArray searchItemsArray = requestJson.getJSONArray("SearchItems");
            if (searchItemsArray != null) {
                for (int i = 0; i < searchItemsArray.size(); i++) {
                    JSONObject searchItemJson = searchItemsArray.getJSONObject(i);
                    ReportSearchItem searchItem = new ReportSearchItem();
                    searchItem.setColumnName(searchItemJson.getString("ColumnName"));
                    searchItem.setBeginDefault(searchItemJson.getString("BeginDefault"));
                    searchItem.setBeginDefaultText(searchItemJson.getString("BeginDefaultText"));
                    searchItem.setEndDefault(searchItemJson.getString("EndDefault"));
                    searchItem.setEndDefaultText(searchItemJson.getString("EndDefaultText"));
                    data.getSearchItems().add(searchItem);
                }
            }

            // 处理 GroupItems
            JSONArray groupItemsArray = requestJson.getJSONArray("GroupItems");
            if (groupItemsArray != null) {
                for (int i = 0; i < groupItemsArray.size(); i++) {
                    JSONObject groupItemJson = groupItemsArray.getJSONObject(i);
                    ReportGroupItem groupItem = new ReportGroupItem();
                    groupItem.setColumnName(groupItemJson.getString("ColumnName"));
                    groupItem.setIsGroup(groupItemJson.getBoolean("isGroup"));
                    groupItem.setGrpFieldType(groupItemJson.getString("grpFieldType"));
                    groupItem.setDateFieldGrpStyle(groupItemJson.getString("dateFieldGrpStyle"));
                    groupItem.setCanHorizontalLayout(groupItemJson.getBoolean("canHorizontalLayout"));
                    groupItem.setIsHorizontalLayout(groupItemJson.getBoolean("isHorizontalLayout"));
                    data.getGroupItems().add(groupItem);
                }
            }

            return data;
        } catch (Exception e) {
            System.err.println("解析错误: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    public static String convertToJson(String input) {
        input = input.trim();
        if (input.startsWith("{") && input.endsWith("}")) {
            input = input.substring(1, input.length() - 1);
        }
        JSONObject resultJson = new JSONObject();
        String[] keyValuePairs = splitKeyValuePairs(input);
        for (String pair : keyValuePairs) {
            int index = pair.indexOf("=");
            if (index == -1) {
                continue;
            }
            String key = pair.substring(0, index).trim();
            String value = pair.substring(index + 1).trim();

            if (value.startsWith("[") && value.endsWith("]")) {
                JSONArray list = new JSONArray();
                String[] items = splitListItems(value.substring(1, value.length() - 1));
                for (String item : items) {
                    list.add(parseNestedObject(item));
                }
                resultJson.put(key, list);
            } else {
                resultJson.put(key, value);
            }
        }

        return resultJson.toJSONString();
    }

    private static String[] splitKeyValuePairs(String input) {
        List<String> pairs = new ArrayList<>();
        int start = 0;
        int depth = 0;
        boolean inArray = false;
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c == '[') {
                inArray = true;
                depth++;
            } else if (c == ']') {
                inArray = false;
                depth--;
            } else if (c == '{') {
                depth++;
            } else if (c == '}') {
                depth--;
            } else if (c == ',' && depth == 0 &&!inArray) {
                // 特殊处理 ReportTableColNames,避免被逗号分割
                if (input.substring(start, i).trim().startsWith("ReportTableColNames")) {
                    continue;
                }
                pairs.add(input.substring(start, i).trim());
                start = i + 1;
            }
        }
        pairs.add(input.substring(start).trim());
        return pairs.toArray(new String[0]);
    }

    private static String[] splitListItems(String input) {
        List<String> items = new ArrayList<>();
        int start = 0;
        int depth = 0;
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c == '{') {
                if (depth == 0) {
                    start = i;
                }
                depth++;
            } else if (c == '}') {
                depth--;
                if (depth == 0) {
                    items.add(input.substring(start, i + 1));
                }
            }
        }
        return items.toArray(new String[0]);
    }

    private static JSONObject parseNestedObject(String input) {
        JSONObject obj = new JSONObject();
        String[] pairs = splitKeyValuePairs(input.substring(1, input.length() - 1));
        for (String pair : pairs) {
            int index = pair.indexOf("=");
            if (index == -1) {
                continue;
            }
            String key = pair.substring(0, index).trim();
            String value = pair.substring(index + 1).trim();
            obj.put(key, value);
        }
        return obj;
    }
}

中间的主要方法parseRequest返回的类型就是一个实体类,复杂的也可以去遍历塞入数据:

下面是对应的参数实体类:

package com.chanjet.magic.dto;

import java.util.ArrayList;
import java.util.List;

/**
 * ClassName: ReportOpenApiRequest
 * Package: com.chanjet.magic.dto
 * Description:
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 10:17
 * @Version 1.0.0
 */
public class ReportOpenApiRequest {

    private String ReportName;

    private String planName;

    private String PageIndex;

    private String PageSize;

    private List<ReportSearchItem> SearchItems = new ArrayList<>();

    private String  ReportTableColNames;

    private List<ReportGroupItem> GroupItems = new ArrayList<>();

    private String levelDisplay;

    public String getReportName() {
        return ReportName;
    }

    public void setReportName(String reportName) {
        ReportName = reportName;
    }

    public String getLevelDisplay() {
        return levelDisplay;
    }

    public void setLevelDisplay(String levelDisplay) {
        this.levelDisplay = levelDisplay;
    }

    public List<ReportGroupItem> getGroupItems() {
        return GroupItems;
    }

    public void setGroupItems(List<ReportGroupItem> groupItems) {
        GroupItems = groupItems;
    }

    public String getReportTableColNames() {
        return ReportTableColNames;
    }

    public void setReportTableColNames(String reportTableColNames) {
        ReportTableColNames = reportTableColNames;
    }

    public List<ReportSearchItem> getSearchItems() {
        return SearchItems;
    }

    public void setSearchItems(List<ReportSearchItem> searchItems) {
        SearchItems = searchItems;
    }

    public String getPageSize() {
        return PageSize;
    }

    public void setPageSize(String pageSize) {
        PageSize = pageSize;
    }

    public String getPageIndex() {
        return PageIndex;
    }

    public void setPageIndex(String pageIndex) {
        PageIndex = pageIndex;
    }

    public String getPlanName() {
        return planName;
    }

    public void setPlanName(String planName) {
        this.planName = planName;
    }

    @Override
    public String toString() {
        return "ReportOpenApiRequest{" +
                "ReportName='" + ReportName + '\'' +
                ", planName='" + planName + '\'' +
                ", PageIndex='" + PageIndex + '\'' +
                ", PageSize='" + PageSize + '\'' +
                ", SearchItems=" + SearchItems +
                ", ReportTableColNames='" + ReportTableColNames + '\'' +
                ", GroupItems=" + GroupItems +
                ", levelDisplay='" + levelDisplay + '\'' +
                '}';
    }
}

这个实体类里又有两个实体类的列表,我们也不要忘记给加上:

分别是ReportSearchItem:

package com.chanjet.magic.dto;

/**
 * ClassName: ReportSearchItem
 * Package: com.chanjet.magic.dto
 * Description:
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 9:22
 * @Version 1.0.0
 */
public class ReportSearchItem {
    private String ColumnName;
    private String BeginDefault;
    private String BeginDefaultText;
    private String EndDefault;
    private String EndDefaultText;

    // Getters 和 Setters
    public String getColumnName() {
        return ColumnName;
    }

    public void setColumnName(String columnName) {
        ColumnName = columnName;
    }

    public String getBeginDefault() {
        return BeginDefault;
    }

    public void setBeginDefault(String beginDefault) {
        BeginDefault = beginDefault;
    }

    public String getBeginDefaultText() {
        return BeginDefaultText;
    }

    public void setBeginDefaultText(String beginDefaultText) {
        BeginDefaultText = beginDefaultText;
    }

    public String getEndDefault() {
        return EndDefault;
    }

    public void setEndDefault(String endDefault) {
        EndDefault = endDefault;
    }

    public String getEndDefaultText() {
        return EndDefaultText;
    }

    public void setEndDefaultText(String endDefaultText) {
        EndDefaultText = endDefaultText;
    }
}

还有ReportGroupItem:

package com.chanjet.magic.dto;

/**
 * ClassName: ReportGroupItem
 * Package: com.chanjet.magic.dto
 * Description:
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 9:22
 * @Version 1.0.0
 */
public class ReportGroupItem {
    private Boolean isGroup;
    private String ColumnName;
    private String grpFieldType;
    private String dateFieldGrpStyle;
    private Boolean canHorizontalLayout;
    private Boolean isHorizontalLayout;

    // Getters 和 Setters
    public Boolean getIsGroup() {
        return isGroup;
    }

    public void setIsGroup(Boolean isGroup) {
        this.isGroup = isGroup;
    }

    public String getColumnName() {
        return ColumnName;
    }

    public void setColumnName(String columnName) {
        ColumnName = columnName;
    }

    public String getGrpFieldType() {
        return grpFieldType;
    }

    public void setGrpFieldType(String grpFieldType) {
        this.grpFieldType = grpFieldType;
    }

    public String getDateFieldGrpStyle() {
        return dateFieldGrpStyle;
    }

    public void setDateFieldGrpStyle(String dateFieldGrpStyle) {
        this.dateFieldGrpStyle = dateFieldGrpStyle;
    }

    public Boolean getCanHorizontalLayout() {
        return canHorizontalLayout;
    }

    public void setCanHorizontalLayout(Boolean canHorizontalLayout) {
        this.canHorizontalLayout = canHorizontalLayout;
    }

    public Boolean getIsHorizontalLayout() {
        return isHorizontalLayout;
    }

    public void setIsHorizontalLayout(Boolean isHorizontalLayout) {
        this.isHorizontalLayout = isHorizontalLayout;
    }
}

然后这边弄完就要确定Content的类,也就是RequestBody中的数据,代码如下所示:

package com.chanjet.magic.request.content;

import com.chanjet.magic.dto.ReportOpenApiRequest;
import com.chanjet.openapi.sdk.java.AbstractChanjetContent;

import java.util.Objects;

/**
 * ClassName: SaleDeliveryDetailReportContent
 * Package: com.chanjet.magic.request.content
 * Description:
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 10:16
 * @Version 1.0.0
 */
public class SaleDeliveryDetailReportContent extends AbstractChanjetContent {
    private static final long serialVersionUID = -5126668713954209528L;

    private ReportOpenApiRequest request;

    public SaleDeliveryDetailReportContent() {
    }

    public SaleDeliveryDetailReportContent(ReportOpenApiRequest request) {
        this.request = request;
    }

    public ReportOpenApiRequest getRequest() {
        return request;
    }

    public void setRequest(ReportOpenApiRequest request) {
        this.request = request;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof SaleDeliveryDetailReportContent)) return false;
        SaleDeliveryDetailReportContent that = (SaleDeliveryDetailReportContent) o;
        return Objects.equals(request, that.request);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(request);
    }

    @Override
    public String toString() {
        return "SaleDeliveryDetailReportContent{" +
                "request=" + request +
                '}';
    }

    public static SaleDeliveryDetailReportContentBuilder builder() { return SaleDeliveryDetailReportContent.builder(); }

    public static class SaleDeliveryDetailReportContentBuilder {
        private ReportOpenApiRequest request;

        SaleDeliveryDetailReportContentBuilder() {
        }

        public SaleDeliveryDetailReportContentBuilder request(ReportOpenApiRequest request) {
            this.request = request;
            return this;
        }

        public SaleDeliveryDetailReportContent build() {
            return new SaleDeliveryDetailReportContent(request);
        }

        @Override
        public String toString() {
            return "SaleDeliveryDetailReportContentBuilder{" +
                    "request=" + request +
                    '}';
        }
    }
}

弄完这个,request部分的数据就可以了,Response按照我之前的那种建立一个Response用于接收数据就可以了,可以看我往期文章;

三、修改具体业务实现通用

其实前面关于RequestBody赋值是类似的,就是修改了Controller层里面的东西,然后接收对象当时想着,反正response都是继承一个抽象类的(AbstractChanjetResponse),然后这个抽象类就是实现了两个接口(ChanjetResponse、Serializable),那我直接建个通用的,然后去取数就好了,于是尝试了一下,最后接口也测试成功了,后续再测测其他输入有没有问题吧!下面静静的看会代码:

cotroller层:

/**
     * 通用报表类型查询
     *
     * @param username
     * @param password
     * @param map
     * @return
     * @throws ChanjetApiException
     */
    @ApiOperation(value = "通用报表类型查询", httpMethod = "POST")
    @PostMapping("/report/getBaseReport")
    public BaseReportResponse getBaseReport(@RequestHeader("username") String username, @RequestHeader("password") String password, @RequestBody LinkedHashMap<String, Object> map) throws ChanjetApiException {
        Object request = map.get("request");
        BaseReportRequest baseReportRequest = new BaseReportRequest();
        baseReportRequest.setAppKey(appKey);
        baseReportRequest.setAppSecret(appSecret);
        baseReportRequest.setOpenToken(accessToken);
        baseReportRequest.setRequestUri("/tplus/api/v2/reportQuery/GetReportData");
        baseReportRequest.setBizContent(new BaseReportContent(RequestParserUtils.parseRequest(request)));
        return chanjetClient.execute(baseReportRequest);
    }

其中涉及的类都在下面:

BaseReportResponse:

package com.chanjet.magic.response;

import com.chanjet.openapi.sdk.java.ChanjetResponse;

import java.io.Serializable;
import java.util.LinkedHashMap;

/**
 * ClassName: BaseReportResponse
 * Package: com.chanjet.magic.response
 * Description:
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 15:19
 * @Version 1.0.0
 */
public class BaseReportResponse extends LinkedHashMap<String, Object> implements ChanjetResponse, Serializable {
}

BaseReportRequest:

package com.chanjet.magic.request;

import com.chanjet.magic.response.BaseReportResponse;
import com.chanjet.magic.response.SaleDeliveryDetailReportResponse;
import com.chanjet.openapi.sdk.java.AbstractChanjetRequest;
import com.chanjet.openapi.sdk.java.enums.HttpMethod;

/**
 * ClassName: BaseReportRequest
 * Package: com.chanjet.magic.request
 * Description:
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 15:20
 * @Version 1.0.0
 */
public class BaseReportRequest extends AbstractChanjetRequest<BaseReportResponse> {
    @Override
    public Class<BaseReportResponse> getResponseClass() {
        return BaseReportResponse.class;
    }

    @Override
    public HttpMethod getHttpMethod() {
        return HttpMethod.POST;
    }
}

BaseReportContent:

package com.chanjet.magic.request.content;

import com.chanjet.magic.dto.ReportOpenApiRequest;
import com.chanjet.openapi.sdk.java.ChanjetContent;

import java.util.Objects;

/**
 * ClassName: BaseReportContent
 * Package: com.chanjet.magic.request.content
 * Description:
 *
 * @Author Zeiyalo
 * @Create 2025/4/10 11:52
 * @Version 1.0.0
 */
public class BaseReportContent extends Object implements ChanjetContent {
    private static final long serialVersionUID = -5126668713954209529L;

    private ReportOpenApiRequest request;

    public BaseReportContent() {
    }

    public BaseReportContent(ReportOpenApiRequest request) {
        this.request = request;
    }

    public ReportOpenApiRequest getRequest() {
        return request;
    }

    public void setRequest(ReportOpenApiRequest request) {
        this.request = request;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof BaseReportContent)) return false;
        BaseReportContent that = (BaseReportContent) o;
        return Objects.equals(request, that.request);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(request);
    }

    @Override
    public String toString() {
        return "BaseReportContent{" +
                "request=" + request +
                '}';
    }

    public static BaseReportContentBuilder builder() { return BaseReportContent.builder(); }

    public static class BaseReportContentBuilder {
        private ReportOpenApiRequest request;

        BaseReportContentBuilder() {
        }

        public BaseReportContentBuilder request(ReportOpenApiRequest request) {
            this.request = request;
            return this;
        }

        public BaseReportContent build() {
            return new BaseReportContent(request);
        }

        @Override
        public String toString() {
            return "BaseReportContentBuilder{" +
                    "request=" + request +
                    '}';
        }
    }
}

RequestParserUtils和上面一样的,开始也就说过了,请求参数是官网有的,所以直接按照官网的文档去建的;

测试成功如下图:

在这里插入图片描述

OKOK,差不多就到这里了,返回的数据有问题,我还是要去问问是不是我请求参数写错了,结果返回的数据都没有,再弄弄吧;

相关文章:

  • 既然安装了WSL2和Ubuntu,那么怎么和windows传递文件(2)
  • 【Linux】Linux基础指令
  • vxe-table
  • FPGA上实现SD卡连续多块读的命令
  • muduo库源码分析: One Loop Per Thread
  • 解决windows server 2012服务器注册表删除Grace Period报错无法删除 GracePeriod: 删除项时出错
  • 数据结构day05
  • Centos7配置本地Yum源以及网络YUM源(保姆级)
  • HTTP:四.HTTP连接
  • 【软考系统架构设计师】系统配置与性能评价知识点
  • 解决 Elasticsearch 分页查询性能瓶颈——从10分钟到秒级的优化实践
  • Java基础知识全面复习指南
  • Linux:线程理解和控制
  • vue周边库安装与开发者工具(vue系列二)
  • JavaScript 简单类型与复杂类型-复杂类型传参
  • Oracle 排除交集数据 MINUS
  • AOSP14 Launcher3——手势上滑关键类AbsSwipeHandler解析
  • NDT和ICP构建点云地图 |【点云建图、Ubuntu、ROS】
  • 【特权FPGA】之UART串口
  • ZYNQ笔记书签
  • 量化交易网站开发/兰州seo公司
  • 深圳专门网站建设/网络推广外包
  • 家乡网络推广方案/宁波seo网站
  • 《网页设计与网站建设》第04章在线测试/app软件推广怎么做
  • 制作效果图的软件/优化大师免费版下载
  • 南阳旅游网站建设/免费推广seo