Swagger Document to Word Document

GitHub address: https://github.com/JMCuixy/SwaggerToWord/tree/developer

Original works, reproduced, please indicate the source: http://www.cnblogs.com/jmcui/p/8298823.html

I. Preface

Why does this demand arise?

As Party B, our company is always chasing for an API document by customers, when we drop a Swagger document address to our customers. Customers are still very dissatisfied, not formal enough!! We insist on a word document. Then the leader gave me an interface template and gave me the job..... I went to nearly 10 micro services and hundreds of interfaces, which was not going to kill me. (Finally, nearly 200 pages of word documents were sorted out.) Finally, the leader has a way: let's turn Swagger's json file into word document.

Keep a word. As users, people have to accommodate machines; as developers, machines have to accommodate people.

Two, train of thought

Leaders provide an interface template, similar to the following, which is actually a word table page. When you think that html can be word-switched, the problem becomes:

1. Parsing JSON files

2. Fill in the Table of html with the contents of JSON files

3. Direct conversion from html to word

Hundreds of interfaces, in one go! Here's another simple example, the request parameters and the return values. How to deal with it? Write the HTTP request in the program, encapsulate the required parameters to execute a request, and get the corresponding return value!

      

Three, implementation

1. Encapsulation objects

According to the object-oriented idea, an interface Table is an object, and variable request and return parameters are encapsulated as an object...

public class Table {

    /**
     * Headline
     */
    private String title;
    /**
     * Subheading
     */
    private String tag;
    /**
     * url
     */
    private String url;

    /**
     * Response parameter format
     */
    private String responseForm;

    /**
     * Request mode
     */
    private String requestType;

    /**
     * Request body
     */
    private List<Request> requestList;

    /**
     * Return body
     */
    private List<Response> responseList;

    /**
     * Request parameters
     */
    private String requestParam;

    /**
     * Return value
     */
    private String responseParam;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getResponseForm() {
        return responseForm;
    }

    public void setResponseForm(String responseForm) {
        this.responseForm = responseForm;
    }

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public List<Request> getRequestList() {
        return requestList;
    }

    public void setRequestList(List<Request> requestList) {
        this.requestList = requestList;
    }

    public List<Response> getResponseList() {
        return responseList;
    }

    public void setResponseList(List<Response> responseList) {
        this.responseList = responseList;
    }

    public String getRequestParam() {
        return requestParam;
    }

    public void setRequestParam(String requestParam) {
        this.requestParam = requestParam;
    }

    public String getResponseParam() {
        return responseParam;
    }

    public void setResponseParam(String responseParam) {
        this.responseParam = responseParam;
    }
}
Table
public class Request {

    /**
     * Request parameters
     */
    private String description;

    /**
     * Parameter name
     */
    private String name;

    /**
     * data type
     */
    private String type;

    /**
     * Parameter type
     */
    private String paramType;

    /**
     * Is it necessary to fill in?
     */
    private Boolean require;

    /**
     * Explain
     */
    private String remark;

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Boolean getRequire() {
        return require;
    }

    public void setRequire(Boolean require) {
        this.require = require;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public String getParamType() {
        return paramType;
    }

    public void setParamType(String paramType) {
        this.paramType = paramType;
    }
}
Request
public class Response {
    /**
     * Return parameter
     */
    private String description;

    /**
     * Parameter name
     */
    private String name;

    /**
     * Explain
     */
    private String remark;

    public Response(String description, String name, String remark) {
        this.description = description;
        this.name = name;
        this.remark = remark;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}
Response

2. Analyzing json

Let's look at the format of the Swagger json file first. It should be noted that the default host of this json file is not prefixed with http://and we need to add it manually, because the HTTP request of the program does not automatically fill the prefix of http://as browsers do...

Parsing JSON is really a tedious job. You can modify the code here as you want to generate templates... It's worth mentioning that there's something that has been bothering me for a long time. How do you forge the request parameters of the interface to send HTTP requests to avoid throwing exceptions? Finally, we refer to Swagger's method, that is, if it's a String type parameter, set it to "string"; if it's an Integer type parameter, set it to 0; if it's a Double type parameter, set it to 0.0; if it's an unpredictable type, set it to null;

JSON parsing uses Spring's recommended jackson, which feels like nothing to say, just go to the code!

@Service
public class TableServiceImpl implements TableService {

    @Override
    public List<Table> tableList() {
        List<Table> list = new LinkedList();
        try {
            ClassLoader classLoader = TableService.class.getClassLoader();
            URL resource = classLoader.getResource("data.json");
            Map map = new ObjectMapper().readValue(resource, Map.class);
            //obtain host,Used for simulation http request
            String host = String.valueOf(map.get("host"));
            //analysis paths
            LinkedHashMap<String, LinkedHashMap> paths = (LinkedHashMap) map.get("paths");
            if (paths != null) {
                Iterator<Map.Entry<String, LinkedHashMap>> iterator = paths.entrySet().iterator();
                while (iterator.hasNext()) {
                    Table table = new Table();
                    List<Request> requestList = new LinkedList<Request>();
                    String requestType = "";

                    Map.Entry<String, LinkedHashMap> next = iterator.next();
                    String url = next.getKey();//obtain url
                    LinkedHashMap<String, LinkedHashMap> value = next.getValue();
                    //Get the request, and the output is similar to get/post/delete/put such
                    Set<String> requestTypes = value.keySet();
                    for (String str : requestTypes) {
                        requestType += str + "/";
                    }
                    Iterator<Map.Entry<String, LinkedHashMap>> it2 = value.entrySet().iterator();
                    //Parsing request
                    Map.Entry<String, LinkedHashMap> get = it2.next();//obtain get
                    LinkedHashMap getValue = get.getValue();
                    String title = (String) ((List) getValue.get("tags")).get(0);//Get the title
                    String tag = String.valueOf(getValue.get("summary"));
                    //Request body
                    ArrayList parameters = (ArrayList) getValue.get("parameters");
                    if (parameters != null && parameters.size() > 0) {
                        for (int i = 0; i < parameters.size(); i++) {
                            Request request = new Request();
                            LinkedHashMap<String, Object> param = (LinkedHashMap) parameters.get(i);
                            request.setDescription(String.valueOf(param.get("description")));
                            request.setName(String.valueOf(param.get("name")));
                            request.setType(String.valueOf(param.get("type")));
                            request.setParamType(String.valueOf(param.get("in")));
                            request.setRequire((Boolean) param.get("required"));
                            requestList.add(request);
                        }
                    }
                    //Return body, relatively fixed
                    List<Response> responseList = listResponse();
                    //Simulate once HTTP request,Encapsulate the request body and return body, if yes Restful Documents can be supplemented
                    if (requestType.contains("post")) {
                        Map<String, String> stringStringMap = toPostBody(requestList);
                        table.setRequestParam(stringStringMap.toString());
                        String post = NetUtil.post(host + url, stringStringMap);
                        table.setResponseParam(post);
                    } else if (requestType.contains("get")) {
                        String s = toGetHeader(requestList);
                        table.setResponseParam(s);
                        String getStr = NetUtil.get(host + url + s);
                        table.setResponseParam(getStr);
                    }

                    //encapsulation Table
                    table.setTitle(title);
                    table.setUrl(url);
                    table.setTag(tag);
                    table.setResponseForm("application/json");
                    table.setRequestType(StringUtils.removeEnd(requestType, "/"));
                    table.setRequestList(requestList);
                    table.setResponseList(responseList);
                    list.add(table);
                }
            }
            return list;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    //Encapsulation of return information, may require different, you can customize
    private List<Response> listResponse() {
        List<Response> responseList = new LinkedList<Response>();
        responseList.add(new Response("Number of rows affected", "counts", null));
        responseList.add(new Response("Result Description Information", "msg", null));
        responseList.add(new Response("Success", "success", null));
        responseList.add(new Response("Return object", "data", null));
        responseList.add(new Response("error code", "errCode", null));
        return responseList;
    }

    //encapsulation post Request body
    private Map<String, String> toPostBody(List<Request> list) {
        Map<String, String> map = new HashMap<>(16);
        if (list != null && list.size() > 0) {
            for (Request request : list) {
                String name = request.getName();
                String type = request.getType();
                switch (type) {
                    case "string":
                        map.put(name, "string");
                        break;
                    case "integer":
                        map.put(name, "0");
                        break;
                    case "double":
                        map.put(name, "0.0");
                        break;
                    default:
                        map.put(name, "null");
                        break;
                }
            }
        }
        return map;
    }

    //encapsulation get Request header
    private String toGetHeader(List<Request> list) {
        StringBuffer stringBuffer = new StringBuffer();
        if (list != null && list.size() > 0) {
            for (Request request : list) {
                String name = request.getName();
                String type = request.getType();
                switch (type) {
                    case "string":
                        stringBuffer.append(name+"&=string");
                        break;
                    case "integer":
                        stringBuffer.append(name+"&=0");
                        break;
                    case "double":
                        stringBuffer.append(name+"&=0.0");
                        break;
                    default:
                        stringBuffer.append(name+"&=null");
                        break;
                }
            }
        }
        String s = stringBuffer.toString();
        if ("".equalsIgnoreCase(s)){
            return "";
        }
        return "?" + StringUtils.removeStart(s, "&");
    }
}
TableServiceImpl

3. html template

We need an HTML page like the Word Table template, and then use JSP's foreach to traverse the List < Table > collection from the background, and generate all interfaces in one go...

<%-- text/html: Natural html display  application/msword: html Page direct conversion word--%>
<%@ page contentType="application/msword" pageEncoding="UTF-8" language="java" %>
<%--<%@page contentType="text/html" pageEncoding="UTF-8" language="java" %>--%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
    <head>
        <title>tool</title>
        <style type="text/css">
            .bg {
            background-color: rgb(84, 127, 177);
            }

            tr {
            height: 20px;
            font-size: 12px;
            }

            .specialHeight {
            height: 40px;
            }
        </style>
    </head>
    <body>
        <div style="width:800px; margin: 0 auto">
            <c:forEach items="${table}" var="t">
                <h4>${t.title}</h4> <%--This is a description of the class.--%>
                <h5>${t.tag}</h5>   <%--This is a description of each request to facilitate document generation and collation.--%>
                <table border="1" cellspacing="0" cellpadding="0" width="100%">
                    <tr class="bg">
                        <td colspan="6"><c:out value="${t.tag}"/></td>
                    </tr>
                    <tr>
                        <td>URL</td>
                        <td colspan="5">${t.url}</td>
                    </tr>
                    <tr>
                        <td>Request mode</td>
                        <td colspan="5">${t.requestType}</td>
                    </tr>
                    <tr>
                        <td>return type</td>
                        <td colspan="5">${t.responseForm}</td>
                    </tr>

                    <tr class="bg" align="center">
                        <td>Request parameters</td>
                        <td>Parameter name</td>
                        <td>data type</td>
                        <td>Parameter type</td>
                        <td>Is it necessary to fill in?</td>
                        <td>Explain</td>
                    </tr>
                    <c:forEach items="${t.requestList}" var="req">
                        <tr align="center">
                            <td>${req.description}</td>
                            <td>${req.name}</td>
                            <td>${req.type}</td>
                            <td>${req.paramType}</td>
                            <td>
                                <c:choose>
                                    <c:when test="${req.require == true}">Y</c:when>
                                    <c:otherwise>N</c:otherwise>
                                </c:choose>
                            </td>
                            <td>${remark}</td>
                        </tr>
                    </c:forEach>
                    <tr class="bg" align="center">
                        <td>Return parameter</td>
                        <td>Parameter name</td>
                        <td colspan="4">Explain</td>
                    </tr>

                    <c:forEach items="${t.responseList}" var="res">
                        <tr align="center">
                            <td>${res.description}</td>
                            <td>${res.name}</td>
                            <td colspan="4">${res.remark}</td>
                        </tr>
                    </c:forEach>

                    <tr class="bg">
                        <td colspan="6">Example</td>
                    </tr>
                    <tr class="specialHeight">
                        <td class="bg">Request parameters</td>
                        <td colspan="5">${t.requestParam}</td>
                    </tr>
                    <tr class="specialHeight">
                        <td class="bg">Return value</td>
                        <td colspan="5">${t.responseParam}</td>
                    </tr>
                </table>
                <br>
            </c:forEach>
        </div>
    </body>
</html>
json.jsp

4, effect

After running the code, you visit the JSP page, and you don't see the HTML page as usual. Instead, you download and generate a file named after the Spring MVC request method (getJson file in this project). Change the suffix name of this file to. doc to see the effect! Almost as follows:

Of course, the rest of the work, we have to do manual maintenance. For example: classify the requests belonging to the same class together; delete the wrong return value of HTTP requests (can not adapt to all HTTP requests); collate and maintain the effect as follows:

 

Four, use

If you use my API document template directly, you just need to replace the contents of the data.json file in the resources directory with your own Swagger Json file content. However, considering that the return parameter in our template is a customized object of our company, we may need to modify the listResponse() method under the TableServiceImpl class according to our own requirements.

It should be noted that this project does not support all HTTP requests very well, such as restful service putting request parameters in the request path, such as parameters in header, and a series of bug s that may not be considered...

In addition, I think TableService Impl has a lot to improve, and the code is slightly redundant. Then slowly maintain it! Of course, you are welcome to join us in the development of.... Haha

Five, conclusion

I have always felt that the most fascinating part of IT is open source and sharing. People don't know each other. Even if there is no profit to be made, they can contribute their time and energy to the same project and the same goal. It's incredible to think about it. Writing this blog is more about sharing your ideas and ideas. To be honest, the code may be a bit rotten. Also, please don't give up, don't hesitate to give advice!

Keywords: Java JSON JSP github

Added by Sassci on Sat, 18 May 2019 09:01:56 +0300