From c0a4d7814ca9ed15a29f7d72ab22ea3feb2787e6 Mon Sep 17 00:00:00 2001 From: Coooder-X <55648333+Coooder-X@users.noreply.github.com> Date: Wed, 31 Mar 2021 17:46:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20swagger=20=E5=AF=BC=E5=87=BA=E6=97=B6?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E4=BD=93=E7=BC=BA=E5=A4=B1=20(#1771)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(测试跟踪): 测试用例下载模版增加标签列 * fix(接口定义): 扩大请求头键长度 * fix: schedule表对旧数据name字段兼容的补充 * fix(接口定义): 修复swagger导入一些值缺失 & 请求体导出支持json、xml格式 * fix(接口定义): 修复 swagger 导出时请求体缺失 Co-authored-by: jianxing <41557596+AgAngle@users.noreply.github.com> --- .../dto/definition/parse/Swagger3Parser.java | 156 ++++++++++++++---- .../metersphere/commons/utils/XMLUtils.java | 2 + 2 files changed, 122 insertions(+), 36 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java index dd25a0c8b5..c79f394786 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java @@ -107,6 +107,9 @@ public class Swagger3Parser extends SwaggerAbstractParser { parseParameters(operation, request); parseRequestBody(operation.getRequestBody(), request.getBody()); addBodyHeader(request); + if(request.getBody().getKvs().size() > 1 && request.getBody().getKvs().get(0).getName() == null) { + request.getBody().getKvs().remove(0); + } // 有数据的话,去掉 Kvs 里初始化的第一个全 null 的数据,否则有空行 apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses()))); buildModule(parentNode, apiDefinition, operation.getTags()); @@ -260,7 +263,7 @@ public class Swagger3Parser extends SwaggerAbstractParser { if (StringUtils.equals(contentType, org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE)) { parseKvBody(schema, body, bodyData, infoMap); } else if (StringUtils.equals(contentType, org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)) { - body.setRaw(bodyData.toString()); + parseKvBody(schema, body, bodyData, infoMap); } else if (StringUtils.equals(contentType, org.springframework.http.MediaType.APPLICATION_JSON_VALUE)) { body.setRaw(bodyData.toString()); } else if (StringUtils.equals(contentType, org.springframework.http.MediaType.APPLICATION_XML_VALUE)) { @@ -284,6 +287,9 @@ public class Swagger3Parser extends SwaggerAbstractParser { kv.setType("file"); } } + if(body.getKvs() == null) { // 防止空指针 + body.setKvs(new ArrayList<>()); + } body.getKvs().add(kv); }); } else { @@ -445,9 +451,8 @@ public class Swagger3Parser extends SwaggerAbstractParser { JSONObject requestBody = buildRequestBody(requestObject); swaggerApiInfo.setRequestBody(requestBody); // 设置响应体 -// JSONObject reponseObject = JSON.parseObject(apiDefinition.getResponse()); -// swaggerApiInfo.setResponses(buildResponseBody(reponseObject)); - //..... + JSONObject responseObject = JSON.parseObject(apiDefinition.getResponse()); + swaggerApiInfo.setResponses(buildResponseBody(responseObject)); // 设置请求参数列表 List paramsList = buildParameters(requestObject); swaggerApiInfo.setParameters(paramsList); @@ -490,42 +495,15 @@ public class Swagger3Parser extends SwaggerAbstractParser { } private JSONObject buildRequestBody(JSONObject request) { - Hashtable typeMap = new Hashtable() {{ - put("XML", org.springframework.http.MediaType.APPLICATION_XML_VALUE); - put("JSON", org.springframework.http.MediaType.APPLICATION_JSON_VALUE); - put("Raw", "application/urlencoded"); - put("BINARY", org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE); - put("Form Data", org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE); - put("WWW_FORM", org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE); - }}; - JSONObject bodyInfo = new JSONObject(); - if(request.getJSONObject("body") != null && request.getJSONObject("body").containsKey("raw")) { - String bodyType = request.getJSONObject("body").getString("type"); - if(bodyType.equals("JSON")) { - bodyInfo = buildRequestBodyJsonInfo(request.getJSONObject("body").getJSONObject("raw")); - } else if(bodyType.equals("XML")) { - String xmlText = request.getJSONObject("body").getString("raw"); - JSONObject xmlToJson = XMLUtils.XmlToJson(xmlText); - bodyInfo = buildRequestBodyJsonInfo(xmlToJson); - } - } - String type = request.getJSONObject("body").getString("type"); JSONObject requestBody = new JSONObject(); - JSONObject schema = bodyInfo; // 需要转换导出 - JSONObject typeName = new JSONObject(); - schema.put("type", null); - schema.put("format", null); - typeName.put("schema", schema); - JSONObject content = new JSONObject(); - if (type != null && StringUtils.isNotBlank(type)) { - content.put(typeMap.get(type), typeName); - } - requestBody.put("content", content); + requestBody.put("content", buildContent(request)); return requestBody; } // 将请求体中的一个 json 对象转换成 swagger 格式的 json 对象返回 private JSONObject buildRequestBodyJsonInfo(JSONObject requestBody) { + if(requestBody == null) + return null; JSONObject schema = new JSONObject(); schema.put("type", "object"); JSONObject properties = buildSchema(requestBody); @@ -569,9 +547,115 @@ public class Swagger3Parser extends SwaggerAbstractParser { return schema; } - private JSONObject buildResponseBody(JSONObject reponse) { - JSONObject responseBody = new JSONObject(); + private JSONObject buildformDataSchema(JSONObject kvs) { + JSONObject schema = new JSONObject(); + JSONObject properties = new JSONObject(); + for(String key : kvs.keySet()) { + JSONObject property = new JSONObject(); + property.put("type", "string"); + property.put("example", kvs.getString(key)); + properties.put(key, property); + } + schema.put("properties", properties); + return schema; + } + private JSONObject getformDataProperties(JSONArray requestBody) { + JSONObject result = new JSONObject(); + for(Object item : requestBody) { + if(item instanceof JSONObject) { + String name = ((JSONObject) item).getString("name"); + String value = ((JSONObject) item).getString("value"); + if(name != null) { + result.put(name, value); + } + } + } + return result; + } + +/* 请求头格式: + "headers":{ + "headerName":{ + "schema":{ + "type":"string" + } + } + } +*/ + private JSONObject buildResponseBody(JSONObject response) { + JSONObject responseBody = new JSONObject(); + JSONObject statusCodeInfo = new JSONObject(); + // build 请求头 + JSONObject headers = new JSONObject(); + JSONArray headValueList =response.getJSONArray("headers"); + if(headValueList != null) { + for(Object item : headValueList) { + if(item instanceof JSONObject && ((JSONObject) item).getString("name") != null) { + JSONObject head = new JSONObject(), headSchema = new JSONObject(); + head.put("description", ""); + headSchema.put("type", "string"); + head.put("schema", headSchema); + headers.put(((JSONObject) item).getString("name"), head); + } + } + } + statusCodeInfo.put("headers", headers); + // build 请求体 + if(((JSONObject) response.getJSONArray("statusCode").get(0)).getString("name") == null) { + return response; + } + statusCodeInfo.put("content", buildContent(response)); + statusCodeInfo.put("description", ""); + responseBody.put(((JSONObject) response.getJSONArray("statusCode").get(0)).getString("name"), statusCodeInfo); return responseBody; } + +/* 请求体格式: + "content":{ + "application/json":{ + "schema":{ + "type":"xxx", + "xxx":{...} + } + } + } +*/ + private JSONObject buildContent(JSONObject respOrReq) { + Hashtable typeMap = new Hashtable() {{ + put("XML", org.springframework.http.MediaType.APPLICATION_XML_VALUE); + put("JSON", org.springframework.http.MediaType.APPLICATION_JSON_VALUE); + put("Raw", "application/urlencoded"); + put("BINARY", org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE); + put("Form Data", org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE); + put("WWW_FORM", org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE); + }}; + JSONObject bodyInfo = new JSONObject(); + if(respOrReq.getJSONObject("body") != null) { // 将请求体转换成相应的格式导出 + String bodyType = respOrReq.getJSONObject("body").getString("type"); + if(bodyType == null) { + + }else if(bodyType.equals("JSON")) { + bodyInfo = buildRequestBodyJsonInfo(respOrReq.getJSONObject("body").getJSONObject("raw")); + } else if(bodyType.equals("XML")) { + String xmlText = respOrReq.getJSONObject("body").getString("raw"); + JSONObject xmlToJson = XMLUtils.XmlToJson(xmlText); + bodyInfo = buildRequestBodyJsonInfo(xmlToJson); + } else if(bodyType.equals("WWW_FORM") || bodyType.equals("Form Data") || bodyType.equals("BINARY")) { // key-value 类格式 + JSONObject formData = getformDataProperties(respOrReq.getJSONObject("body").getJSONArray("kvs")); + bodyInfo = buildformDataSchema(formData); + } + } + String type = respOrReq.getJSONObject("body").getString("type"); + JSONObject schema = bodyInfo; // 请求体部分 + JSONObject typeName = new JSONObject(); + schema.put("type", null); + schema.put("format", null); + typeName.put("schema", schema); + JSONObject content = new JSONObject(); + if (type != null && StringUtils.isNotBlank(type)) { + content.put(typeMap.get(type), typeName); + } + return content; + } } diff --git a/backend/src/main/java/io/metersphere/commons/utils/XMLUtils.java b/backend/src/main/java/io/metersphere/commons/utils/XMLUtils.java index f8ab892f8c..456671f46d 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/XMLUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/XMLUtils.java @@ -51,6 +51,8 @@ public class XMLUtils { // 传入完整的 xml 文本,转换成 json 对象 public static JSONObject XmlToJson(String xml) { JSONObject result = new JSONObject(); + if(xml == null) + return null; List list = preProcessXml(xml); try { result = (JSONObject) XmlTagToJsonObject(list);