refactor: 接口导入swagger默认使用jsonSchema

This commit is contained in:
chenjianxing 2021-11-17 20:29:20 +08:00 committed by jianxing
parent 8149af9d17
commit 3f5ad742c9
3 changed files with 311 additions and 87 deletions

View File

@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.variable.JsonSchemaItem;
import io.metersphere.api.dto.definition.response.HttpResponse;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
@ -17,6 +18,7 @@ import io.swagger.models.parameters.*;
import io.swagger.models.properties.*;
import io.swagger.parser.SwaggerParser;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
@ -227,23 +229,149 @@ public class Swagger2Parser extends SwaggerAbstractParser {
private void parseRequestBodyParameters(Parameter parameter, Body body) {
BodyParameter bodyParameter = (BodyParameter) parameter;
body.setRaw(parseSchema(bodyParameter.getSchema()));
if (body.getType().equals(Body.JSON)) {
body.setJsonSchema(parseSchema2JsonSchema(bodyParameter.getSchema()));
body.setFormat("JSON-SCHEMA");
} else {
body.setRaw(parseSchema(bodyParameter.getSchema()));
}
}
private JsonSchemaItem parseSchema2JsonSchema(Model schema) {
if (schema == null) return null;
JsonSchemaItem item = new JsonSchemaItem();
item.setDescription(schema.getDescription());
// 引用模型
if (schema instanceof RefModel) {
HashSet<String> refSet = new HashSet<>();
Model model = getRefModelType(schema, refSet);
item.setType("object");
item.setProperties(parseSchemaProperties(model.getProperties(), refSet));
} else if (schema instanceof ArrayModel) {
//模型数组
ArrayModel arrayModel = (ArrayModel) schema;
HashSet<String> refSet = new HashSet<>();
handleArrayItemProperties(item, arrayModel.getItems(), refSet);
} else if (schema instanceof ModelImpl) {
ModelImpl model = (ModelImpl) schema;
Map<String, Property> properties = model.getProperties();
if (model != null) {
item.setType("object");
item.setProperties(parseSchemaProperties(properties, new HashSet<>()));
}
}
if (schema.getExample() != null) {
item.getMock().put("mock", schema.getExample());
} else {
item.getMock().put("mock", "");
}
return item;
}
private Model getRefModelType(Model schema, HashSet<String> refSet) {
String simpleRef;
RefModel refModel = (RefModel) schema;
String originalRef = refModel.getOriginalRef();
if (refModel.getOriginalRef().split("/").length > 3) {
simpleRef = originalRef.replace("#/definitions/", "");
} else {
simpleRef = refModel.getSimpleRef();
}
refSet.add(simpleRef);
return this.definitions.get(simpleRef);
}
private Map<String, JsonSchemaItem> parseSchemaProperties(Map<String, Property> properties, HashSet<String> refSet) {
if (MapUtils.isEmpty(properties)) return null;
Map<String, JsonSchemaItem> JsonSchemaProperties = new LinkedHashMap<>();
properties.forEach((key, value) -> {
JsonSchemaItem item = new JsonSchemaItem();
item.setDescription(value.getDescription());
if (value instanceof ObjectProperty) {
ObjectProperty objectProperty = (ObjectProperty) value;
item.setType("object");
item.setProperties(parseSchemaProperties(objectProperty.getProperties(), refSet));
} else if (value instanceof ArrayProperty) {
ArrayProperty arrayProperty = (ArrayProperty) value;
handleArrayItemProperties(item, arrayProperty.getItems(), refSet);
} else if (value instanceof RefProperty) {
item.setType("object");
handleRefProperties(item, value, refSet);
} else {
handleBaseProperties(item, value, refSet);
}
if (value.getExample() != null) {
item.getMock().put("mock", value.getExample());
} else {
item.getMock().put("mock", "");
}
JsonSchemaProperties.put(key, item);
});
return JsonSchemaProperties;
}
private void handleArrayItemProperties(JsonSchemaItem item, Property value, HashSet<String> refSet) {
if (value == null) return;
item.setType("array");
JsonSchemaItem subItem = new JsonSchemaItem("object");
if (value instanceof RefProperty) {
subItem.setType("object");
handleRefProperties(subItem, value, refSet);
} else if (value instanceof ObjectProperty) {
subItem.setType("object");
subItem.setProperties(parseSchemaProperties(((ObjectProperty) value).getProperties(), refSet));
} else {
handleBaseProperties(subItem, value, refSet);
}
item.getItems().add(subItem);
}
private void handleBaseProperties(JsonSchemaItem item, Property value, HashSet<String> refSet) {
if (value instanceof StringProperty || value instanceof DateProperty || value instanceof DateTimeProperty ) {
item.setType("string");
} else if (value instanceof IntegerProperty) {
item.setType("integer");
} else if (value instanceof BooleanProperty) {
item.setType("boolean");
} else if (value instanceof LongProperty || value instanceof FloatProperty
|| value instanceof DecimalProperty || value instanceof DoubleProperty) {
item.setType("number");
} else {
item.setType("string");
}
}
private void handleRefProperties(JsonSchemaItem item, Property value, HashSet<String> refSet) {
RefProperty refProperty = (RefProperty) value;
String simpleRef = refProperty.getSimpleRef();
if (isContainRef(refSet, simpleRef)) {
return;
}
Model model = this.definitions.get(simpleRef);
if (model != null) {
item.setProperties(parseSchemaProperties(model.getProperties(), refSet));
}
}
private boolean isContainRef(HashSet<String> refSet, String ref) {
if (refSet.contains(ref)) {
//避免嵌套死循环
return true;
} else {
refSet.add(ref);
return false;
}
}
private String parseSchema(Model schema) {
// 引用模型
if (schema instanceof RefModel) {
String simpleRef = "";
RefModel refModel = (RefModel) schema;
String originalRef = refModel.getOriginalRef();
if (refModel.getOriginalRef().split("/").length > 3) {
simpleRef = originalRef.replace("#/definitions/", "");
} else {
simpleRef = refModel.getSimpleRef();
}
Model model = this.definitions.get(simpleRef);
HashSet<String> refSet = new HashSet<>();
refSet.add(simpleRef);
Model model = getRefModelType(schema, refSet);
if (model != null) {
JSONObject bodyParameters = getBodyParameters(model.getProperties(), refSet);
return bodyParameters.toJSONString();

View File

@ -8,6 +8,7 @@ import io.metersphere.api.dto.definition.ApiModuleDTO;
import io.metersphere.api.dto.definition.SwaggerApiExportResult;
import io.metersphere.api.dto.definition.parse.swagger.*;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.variable.JsonSchemaItem;
import io.metersphere.api.dto.definition.response.HttpResponse;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
@ -131,7 +132,7 @@ public class Swagger3Parser extends SwaggerAbstractParser {
}
private ApiDefinitionWithBLOBs buildApiDefinition(String id, Operation operation, String path, String method, ApiTestImportRequest importRequest) {
String name = "";
String name;
if (StringUtils.isNotBlank(operation.getSummary())) {
name = operation.getSummary();
} else if (StringUtils.isNotBlank(operation.getOperationId())) {
@ -200,12 +201,19 @@ public class Swagger3Parser extends SwaggerAbstractParser {
msResponse.setType(RequestType.HTTP);
// todo 状态码要调整
msResponse.setStatusCode(new ArrayList<>());
ApiResponse apiResponse = responses.get("200");
if (responses != null) {
responses.forEach((responseCode, response) -> {
parseResponseHeader(response, msResponse.getHeaders());
parseResponseBody(response, msResponse.getBody());
parseResponseCode(responseCode, msResponse);
});
if (apiResponse == null) {
responses.forEach((responseCode, response) -> {
parseResponseHeader(response, msResponse.getHeaders());
parseResponseBody(response, msResponse.getBody());
parseResponseCode(responseCode, msResponse);
});
} else {
parseResponseHeader(apiResponse, msResponse.getHeaders());
parseResponseBody(apiResponse, msResponse.getBody());
parseResponseCode("200", msResponse);
}
}
return msResponse;
}
@ -252,7 +260,7 @@ public class Swagger3Parser extends SwaggerAbstractParser {
return;
}
// 多个contentType 优先取json
String contentType = "";
String contentType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
MediaType mediaType = content.get(contentType);
if (mediaType == null) {
Set<String> contentTypes = content.keySet();
@ -264,17 +272,15 @@ public class Swagger3Parser extends SwaggerAbstractParser {
return;
}
mediaType = content.get(contentType);
} else {
contentType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
}
Set<String> refSet = new HashSet<>();
Map<String, Schema> infoMap = new HashMap();
Schema schema = mediaType.getSchema();
Object bodyData = parseSchema(schema, refSet, infoMap);
if (bodyData == null) {
return;
Object bodyData = null;
if (!StringUtils.equals(contentType, org.springframework.http.MediaType.APPLICATION_JSON_VALUE)) {
bodyData = parseSchemaToJson(schema, refSet, infoMap);
if (bodyData == null) return;
}
body.setType(getBodyType(contentType));
@ -284,7 +290,8 @@ public class Swagger3Parser extends SwaggerAbstractParser {
} else if (StringUtils.equals(contentType, org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)) {
parseKvBody(schema, body, bodyData, infoMap);
} else if (StringUtils.equals(contentType, org.springframework.http.MediaType.APPLICATION_JSON_VALUE)) {
body.setRaw(bodyData.toString());
body.setJsonSchema(parseSchema(schema, refSet));
body.setFormat("JSON-SCHEMA");
} else if (StringUtils.equals(contentType, org.springframework.http.MediaType.APPLICATION_XML_VALUE)) {
body.setRaw(parseXmlBody(schema, bodyData));
} else if (StringUtils.equals(contentType, org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE)) {
@ -294,48 +301,82 @@ public class Swagger3Parser extends SwaggerAbstractParser {
}
}
private Object parseSchemaToJson(Schema schema, Set<String> refSet, Map<String, Schema> infoMap) {
if (schema == null) {
return new JSONObject(true);
}
infoMap.put(schema.getName(), schema);
if (StringUtils.isNotBlank(schema.get$ref())) {
if (refSet.contains(schema.get$ref())) {
return new JSONObject(true);
}
refSet.add(schema.get$ref());
Object propertiesResult = parseSchemaPropertiesToJson(getModelByRef(schema.get$ref()), refSet, infoMap);
return propertiesResult == null ? getDefaultValueByPropertyType(schema) : propertiesResult;
} else if (schema instanceof ArraySchema) {
JSONArray jsonArray = new JSONArray();
Schema items = ((ArraySchema) schema).getItems();
parseSchemaToJson(items, refSet, infoMap);
jsonArray.add(parseSchemaToJson(items, refSet, infoMap));
return jsonArray;
} else if (schema instanceof BinarySchema) {
return getDefaultValueByPropertyType(schema);
} else if (schema instanceof ObjectSchema) {
Object propertiesResult = parseSchemaPropertiesToJson(schema, refSet, infoMap);
return propertiesResult == null ? getDefaultValueByPropertyType(schema) : propertiesResult;
} else {
return schema;
}
}
private Object parseSchemaPropertiesToJson(Schema schema, Set<String> refSet, Map<String, Schema> infoMap) {
if (schema == null) return null;
Map<String, Schema> properties = schema.getProperties();
if (MapUtils.isEmpty(properties)) return null;
JSONObject jsonObject = new JSONObject(true);
properties.forEach((key, value) -> {
jsonObject.put(key, parseSchemaToJson(value, refSet, infoMap));
});
return jsonObject;
}
private void parseKvBody(Schema schema, Body body, Object data, Map<String, Schema> infoMap) {
if (data instanceof JSONObject) {
((JSONObject) data).forEach((k, v) -> {
Schema dataSchema = (Schema) v;
KeyValue kv = new KeyValue(k, String.valueOf(dataSchema.getExample()), dataSchema.getDescription());
Schema schemaInfo = infoMap.get(k);
if (schemaInfo != null) {
if (schemaInfo instanceof BinarySchema) {
kv.setType("file");
}
}
if (body.getKvs() == null) { // 防止空指针
body.setKvs(new ArrayList<>());
}
body.getKvs().add(kv);
_parseKvBody(schema, body, k, infoMap);
});
} else {
if(data instanceof Schema) {
Schema dataSchema = (Schema) data;
KeyValue kv = new KeyValue(schema.getName(), String.valueOf(dataSchema.getExample()), schema.getDescription());
Schema schemaInfo = infoMap.get(schema.getName());
if (schemaInfo != null) {
if (schemaInfo instanceof BinarySchema) {
kv.setType("file");
}
}
if (body != null) {
if (body.getKvs() == null) {
body.setKvs(new ArrayList<>());
}
body.getKvs().add(kv);
}
_parseKvBody(schema, body, dataSchema.getName(), infoMap);
}
}
}
private void _parseKvBody(Object schemaObject, Body body, String name, Map<String, Schema> infoMap) {
Schema schema = (Schema) schemaObject;
if (schema == null) return;
KeyValue kv = new KeyValue(name, String.valueOf(schema.getExample() == null ? "" : schema.getExample()), schema.getDescription());
Schema schemaInfo = infoMap.get(name);
if (schemaInfo != null) {
if (schemaInfo instanceof BinarySchema) {
kv.setType("file");
}
}
if (body != null) {
if (body.getKvs() == null) {
body.setKvs(new ArrayList<>());
}
body.getKvs().add(kv);
}
}
private String parseXmlBody(Schema schema, Object data) {
if (data instanceof JSONObject) {
return XMLUtils.jsonToXmlStr((JSONObject) data);
} else {
JSONObject object = new JSONObject();
object.put(schema.getName(), getDefaultValueByPropertyType(schema));
object.put(schema.getName(), schema.getExample());
return XMLUtils.jsonToXmlStr(object);
}
}
@ -350,54 +391,56 @@ public class Swagger3Parser extends SwaggerAbstractParser {
return this.components.getSchemas().get(ref);
}
private Object parseSchema(Schema schema, Set<String> refSet, Map<String, Schema> infoMap) {
if (schema == null) {
return new JSONObject(true);
}
infoMap.put(schema.getName(), schema);
private JsonSchemaItem parseSchema(Schema schema, Set<String> refSet) {
if (schema == null) return null;
JsonSchemaItem item = new JsonSchemaItem();
if (StringUtils.isNotBlank(schema.get$ref())) {
if (refSet.contains(schema.get$ref())) {
return new JSONObject(true);
}
if (refSet.contains(schema.get$ref())) return item;
item.setType("object");
refSet.add(schema.get$ref());
Object propertiesResult = parseSchemaProperties(getModelByRef(schema.get$ref()), refSet, infoMap);
return propertiesResult == null ? getDefaultValueByPropertyType(schema) : propertiesResult;
item.setProperties(parseSchemaProperties(getModelByRef(schema.get$ref()), refSet));
} else if (schema instanceof ArraySchema) {
JSONArray jsonArray = new JSONArray();
Schema items = ((ArraySchema) schema).getItems();
parseSchema(items, refSet, infoMap);
jsonArray.add(parseSchema(items, refSet, infoMap));
return jsonArray;
} else if (schema instanceof BinarySchema) {
return getDefaultValueByPropertyType(schema);
item.setType("array");
item.setItems(new ArrayList<>());
JsonSchemaItem arrayItem = parseSchema(items, refSet);
if (arrayItem != null) item.getItems().add(arrayItem);
} else if (schema instanceof ObjectSchema) {
Object propertiesResult = parseSchemaProperties(schema, refSet, infoMap);
return propertiesResult == null ? getDefaultValueByPropertyType(schema) : propertiesResult;
item.setType("object");
item.setProperties(parseSchemaProperties(schema, refSet));
} else if (schema instanceof StringSchema) {
item.setType("string");
} else if (schema instanceof IntegerSchema) {
item.setType("integer");
} else if (schema instanceof NumberSchema) {
item.setType("number");
} else if (schema instanceof BooleanSchema) {
item.setType("boolean");
} else {
if (schema instanceof StringSchema) {
StringSchema stringSchema = (StringSchema) schema;
return stringSchema.getExample();
} else if (schema.getType() != null) { // 特判属性不是对象的情况直接将基本类型赋值进去
return schema;
}
Object propertiesResult = parseSchemaProperties(schema, refSet, infoMap);
return propertiesResult == null ? getDefaultValueByPropertyType(schema) : propertiesResult;
return null;
}
if (schema.getExample() != null) {
item.getMock().put("mock", schema.getExample());
} else {
item.getMock().put("mock", "");
}
item.setDescription(schema.getDescription());
return item;
}
private Object parseSchemaProperties(Schema schema, Set<String> refSet, Map<String, Schema> infoMap) {
if (schema == null) {
return null;
}
private Map<String, JsonSchemaItem> parseSchemaProperties(Schema schema, Set<String> refSet) {
if (schema == null) return null;
Map<String, Schema> properties = schema.getProperties();
if (MapUtils.isEmpty(properties)) {
return null;
}
JSONObject jsonObject = new JSONObject(true);
if (MapUtils.isEmpty(properties)) return null;
Map<String, JsonSchemaItem> JsonSchemaProperties = new LinkedHashMap<>();
properties.forEach((key, value) -> {
jsonObject.put(key, parseSchema(value, refSet, infoMap));
JsonSchemaItem item = new JsonSchemaItem();
item.setDescription(schema.getDescription());
JsonSchemaItem proItem = parseSchema(value, refSet);
if (proItem != null) JsonSchemaProperties.put(key, proItem);
});
return jsonObject;
return JsonSchemaProperties;
}
private Object getDefaultValueByPropertyType(Schema value) {
@ -406,6 +449,8 @@ public class Swagger3Parser extends SwaggerAbstractParser {
return example == null ? 0 : example;
} else if (value instanceof NumberSchema) {
return example == null ? 0.0 : example;
} else if (value instanceof StringSchema) {
return example == null ? "" : example;
} else {// todo 其他类型?
return getDefaultStringValue(value.getDescription());
}

View File

@ -0,0 +1,51 @@
package io.metersphere.api.dto.definition.request.variable;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Getter;
import lombok.Setter;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@Getter
@Setter
public class JsonSchemaItem {
@JSONField(name = "$id")
private String id;
private String title;
private String type;
private String description;
private List<JsonSchemaItem> items;
private Map<String, Object> mock;
private Map<String, JsonSchemaItem> properties;
@JSONField(name = "$schema")
private String schema;
public JsonSchemaItem() {
this.mock = new LinkedHashMap<>();
this.mock.put("mock", "");
}
public JsonSchemaItem(String type) {
this.type = type;
this.initParam(type);
}
public void setType(String type) {
this.type = type;
this.initParam(type);
}
private void initParam(String type) {
if (type.equals("object")) {
this.properties = new LinkedHashMap<>();
} else if (type.equals("array")) {
this.items = new LinkedList<>();
}
}
}