fix(接口测试): 修复JSON-Schema请求参数对数字类型使用变量变成字符问题

--bug=1019328 --user=赵勇 [接口测试]github#19415用场景变量和前置返回的变量 int类型的值 都会转成string,也设置成 number 和 integer 都不行 https://www.tapd.cn/55049933/s/1345270
This commit is contained in:
fit2-zhao 2023-03-06 11:15:52 +08:00 committed by fit2-zhao
parent 8000f871d3
commit c52040dcc0
5 changed files with 113 additions and 77 deletions

View File

@ -62,14 +62,6 @@ public class Body {
}
}
public boolean isOldKV() {
if (StringUtils.equals(type, KV)) {
return true;
} else {
return false;
}
}
public List<KeyValue> getBodyParams(HTTPSamplerProxy sampler, String requestId) {
List<KeyValue> body = new ArrayList<>();
if (this.isKV() || this.isBinary()) {
@ -84,7 +76,7 @@ public class Body {
}
} else {
if (StringUtils.isNotEmpty(this.getRaw()) || this.getJsonSchema() != null) {
parseJonBodyMock();
analyticalData();
KeyValue keyValue = new KeyValue(StringUtils.EMPTY, JSON_SCHEMA, this.getRaw(), true, true);
sampler.setPostBodyRaw(true);
keyValue.setEnable(true);
@ -95,33 +87,43 @@ public class Body {
return body;
}
private void parseJonBodyMock() {
if (StringUtils.isNotBlank(this.type) && StringUtils.equals(this.type, JSON_STR)) {
if (StringUtils.isNotEmpty(this.format) && this.getJsonSchema() != null
&& JSON_SCHEMA.equals(this.format)) {
this.raw = StringEscapeUtils.unescapeJava(JSONSchemaBuilder.generator(JSONUtil.toJSONString(this.getJsonSchema())));
private void parseMock() {
if (StringUtils.isNotEmpty(this.getRaw())) {
String value = StringUtils.chomp(this.getRaw().trim());
if (StringUtils.startsWith(value, "[") && StringUtils.endsWith(value, "]")) {
List list = JSON.parseArray(this.getRaw());
if (!this.getRaw().contains(ElementConstants.REF)) {
jsonMockParse(list);
}
this.raw = JSONUtil.toJSONString(list);
} else {
try {
if (StringUtils.isNotEmpty(this.getRaw())) {
String value = StringUtils.chomp(this.getRaw().trim());
if (StringUtils.startsWith(value, "[") && StringUtils.endsWith(value, "]")) {
List list = JSON.parseArray(this.getRaw());
if (!this.getRaw().contains("$ref")) {
jsonMockParse(list);
}
this.raw = JSONUtil.parserArray(JSONUtil.toJSONString(list));
} else {
Map<String, Object> map = JSON.parseObject(this.getRaw(), Map.class);
if (!this.getRaw().contains("$ref")) {
jsonMockParse(map);
}
this.raw = JSONUtil.parserObject(JSONUtil.toJSONString(map));
}
}
} catch (Exception e) {
LoggerUtil.error("json mock value is abnormal", e);
Map<String, Object> map = JSON.parseObject(this.getRaw(), Map.class);
if (!this.getRaw().contains(ElementConstants.REF)) {
jsonMockParse(map);
}
this.raw = JSONUtil.toJSONString(map);
}
}
}
private void analyticalData() {
try {
boolean isArray = false;
if (StringUtils.isNotBlank(this.type) && StringUtils.equals(this.type, JSON_STR)) {
if (StringUtils.isNotEmpty(this.format) && this.getJsonSchema() != null && JSON_SCHEMA.equals(this.format)) {
this.raw = StringEscapeUtils.unescapeJava(JSONSchemaBuilder.generator(JSONUtil.toJSONString(this.getJsonSchema())));
} else {
parseMock();
}
// 格式化处理
if (isArray) {
this.raw = JSONUtil.parserArray(this.raw);
} else {
this.raw = JSONUtil.parserObject(this.raw);
}
}
} catch (Exception e) {
LoggerUtil.error("json mock value is abnormal", e);
}
}

View File

@ -56,7 +56,7 @@ public class JSONSchemaBuilder {
return "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
}
private static void valueOf(String evlValue, String propertyName, JSONObject concept) {
private static boolean valueOf(String evlValue, String propertyName, JSONObject concept) {
if (StringUtils.startsWith(evlValue, "@")) {
String str = ScriptEngineUtils.calculate(evlValue);
switch (evlValue) {
@ -73,8 +73,10 @@ public class JSONSchemaBuilder {
concept.put(propertyName, str);
break;
}
return false;
} else {
concept.put(propertyName, ScriptEngineUtils.buildFunctionCallString(evlValue));
return true;
}
}
@ -122,7 +124,11 @@ public class JSONSchemaBuilder {
}
}
} catch (Exception e) {
valueOf(FormatterUtil.getElementValue(object).getAsString(), propertyName, concept);
boolean hasValue = valueOf(FormatterUtil.getElementValue(object).getAsString(), propertyName, concept);
if (hasValue) {
String value = FormatterUtil.getElementValue(object).getAsString();
processValue(concept, map, propertyName, value);
}
}
} else if (propertyObjType.equals(PropertyConstant.BOOLEAN)) {
// 先设置空值
@ -137,10 +143,7 @@ public class JSONSchemaBuilder {
if (isBoolean(value)) {
concept.put(propertyName, Boolean.valueOf(value));
} else {
concept.put(propertyName, value);
String key = StringUtils.join("\"", propertyName, "\"", ": \"", value, "\"");
String targetValue = StringUtils.join("\"", propertyName, "\"", ":", value);
map.put(key, targetValue);
processValue(concept, map, propertyName, value);
}
}
}
@ -158,6 +161,19 @@ public class JSONSchemaBuilder {
}
}
public static void processValue(JSONObject concept, Map<String, String> map, String propertyName, String value) {
concept.put(propertyName, value);
String key = StringUtils.join("\"", propertyName, "\"", ":\"", value, "\"");
String targetValue = StringUtils.join("\"", propertyName, "\"", ":", value);
map.put(key, targetValue);
}
public static void processArrayValue(Map<String, String> map, String value) {
String key = StringUtils.join("\"",value, "\"");
String targetValue = StringUtils.join(value);
map.put(key, targetValue);
}
private static void analyzeArray(JSONObject concept, String propertyName, JsonObject object, Map<String, String> map) {
JSONArray array = new JSONArray();
if (object.has(PropertyConstant.ITEMS)) {
@ -176,7 +192,7 @@ public class JSONSchemaBuilder {
JsonObject itemsObject = element.getAsJsonObject();
if (object.has(PropertyConstant.ITEMS)) {
if (FormatterUtil.isMockValue(itemsObject)) {
formatItems(itemsObject, targetArray);
formatItems(itemsObject, targetArray, map);
} else if (itemsObject.has(PropertyConstant.TYPE) && (itemsObject.has(PropertyConstant.ENUM) || itemsObject.get(PropertyConstant.TYPE).getAsString().equals(PropertyConstant.STRING))) {
targetArray.put(FormatterUtil.getMockValue(itemsObject));
} else if (itemsObject.has(PropertyConstant.TYPE) && itemsObject.get(PropertyConstant.TYPE).getAsString().equals(PropertyConstant.NUMBER)) {
@ -202,12 +218,12 @@ public class JSONSchemaBuilder {
});
}
private static void formatItems(JsonObject itemsObject, JSONArray array) {
private static void formatItems(JsonObject itemsObject, JSONArray array, Map<String, String> map) {
String type = StringUtils.EMPTY;
if (itemsObject.has(PropertyConstant.TYPE)) {
type = itemsObject.get(PropertyConstant.TYPE).getAsString();
}
try {
String type = StringUtils.EMPTY;
if (itemsObject.has(PropertyConstant.TYPE)) {
type = itemsObject.get(PropertyConstant.TYPE).getAsString();
}
if (StringUtils.equalsIgnoreCase(type, PropertyConstant.STRING)) {
String value = FormatterUtil.getStrValue(itemsObject);
array.put(value);
@ -227,6 +243,10 @@ public class JSONSchemaBuilder {
}
} catch (Exception e) {
arrayValueOf(FormatterUtil.getStrValue(itemsObject), array);
if (StringUtils.equalsAnyIgnoreCase(type, PropertyConstant.INTEGER, PropertyConstant.NUMBER)) {
String value = FormatterUtil.getElementValue(itemsObject).getAsString();
processArrayValue(map, value);
}
}
}

View File

@ -5,32 +5,35 @@ import io.metersphere.commons.constants.PropertyConstant;
import io.metersphere.commons.utils.EnumPropertyUtil;
import io.metersphere.commons.utils.JSONUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class JSONSchemaParser {
private static void analyzeSchema(String json, JSONObject rootObj) {
private static void analyzeSchema(String json, JSONObject rootObj, Map<String, String> processMap) {
Gson gson = new Gson();
JsonElement element = gson.fromJson(json, JsonElement.class);
JsonObject rootElement = element.getAsJsonObject();
analyzeRootSchemaElement(rootElement, rootObj);
analyzeRootSchemaElement(rootElement, rootObj, processMap);
}
private static void analyzeRootSchemaElement(JsonObject rootElement, JSONObject rootObj) {
private static void analyzeRootSchemaElement(JsonObject rootElement, JSONObject rootObj, Map<String, String> processMap) {
if (rootElement.has(PropertyConstant.TYPE) || rootElement.has(PropertyConstant.ALL_OF)) {
analyzeObject(rootElement, rootObj);
analyzeObject(rootElement, rootObj, processMap);
}
if (rootElement.has("definitions")) {
analyzeDefinitions(rootElement);
analyzeDefinitions(rootElement, processMap);
}
}
private static void analyzeObject(JsonObject object, JSONObject rootObj) {
private static void analyzeObject(JsonObject object, JSONObject rootObj, Map<String, String> processMap) {
if (object != null && object.has(PropertyConstant.ALL_OF)) {
JsonArray allOfArray = object.get(PropertyConstant.ALL_OF).getAsJsonArray();
for (JsonElement allOfElement : allOfArray) {
@ -38,29 +41,32 @@ public class JSONSchemaParser {
if (!allOfElementObj.has(PropertyConstant.PROPERTIES)) {
continue;
}
formatObject(allOfElementObj, rootObj);
formatObject(allOfElementObj, rootObj, processMap);
}
} else if (object.has(PropertyConstant.PROPERTIES)) {
formatObject(object, rootObj);
formatObject(object, rootObj, processMap);
} else if (object.has(PropertyConstant.ADDITIONAL_PROPERTIES)) {
analyzeProperty(rootObj, PropertyConstant.ADDITIONAL_PROPERTIES, object.get(PropertyConstant.ADDITIONAL_PROPERTIES).getAsJsonObject());
} else if (object.has(PropertyConstant.TYPE) && object.get(PropertyConstant.TYPE).getAsString().equals(PropertyConstant.ARRAY)) {
analyzeProperty(rootObj, PropertyConstant.MS_OBJECT, object);
} else if (object.has(PropertyConstant.TYPE) && !object.get(PropertyConstant.TYPE).getAsString().equals(PropertyConstant.OBJECT)) {
analyzeProperty(rootObj, object.getAsString(), object);
analyzeProperty(rootObj, PropertyConstant.ADDITIONAL_PROPERTIES,
object.get(PropertyConstant.ADDITIONAL_PROPERTIES).getAsJsonObject(), processMap);
} else if (object.has(PropertyConstant.TYPE)
&& object.get(PropertyConstant.TYPE).getAsString().equals(PropertyConstant.ARRAY)) {
analyzeProperty(rootObj, PropertyConstant.MS_OBJECT, object, processMap);
} else if (object.has(PropertyConstant.TYPE)
&& !object.get(PropertyConstant.TYPE).getAsString().equals(PropertyConstant.OBJECT)) {
analyzeProperty(rootObj, object.getAsString(), object, processMap);
}
}
private static void formatObject(JsonObject object, JSONObject rootObj) {
private static void formatObject(JsonObject object, JSONObject rootObj, Map<String, String> processMap) {
JsonObject propertiesObj = object.get(PropertyConstant.PROPERTIES).getAsJsonObject();
for (Entry<String, JsonElement> entry : propertiesObj.entrySet()) {
String propertyKey = entry.getKey();
JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject();
analyzeProperty(rootObj, propertyKey, propertyObj);
analyzeProperty(rootObj, propertyKey, propertyObj, processMap);
}
}
private static void analyzeProperty(JSONObject concept, String propertyName, JsonObject object) {
private static void analyzeProperty(JSONObject concept, String propertyName, JsonObject object, Map<String, String> processMap) {
if (!object.has(PropertyConstant.TYPE)) {
return;
}
@ -105,7 +111,7 @@ public class JSONSchemaParser {
concept.put(propertyName, value);
} else {
String value = FormatterUtil.getStrValue(object);
concept.put(propertyName, value);
JSONSchemaBuilder.processValue(concept, processMap, propertyName, value);
}
}
} else if (StringUtils.equals(type, PropertyConstant.NUMBER)) {
@ -123,7 +129,7 @@ public class JSONSchemaParser {
concept.put(propertyName, value.floatValue());
}
} else {
concept.put(propertyName, FormatterUtil.getStrValue(object));
JSONSchemaBuilder.processValue(concept, processMap, propertyName, FormatterUtil.getStrValue(object));
}
}
} else if (StringUtils.equals(type, PropertyConstant.BOOLEAN)) {
@ -142,11 +148,11 @@ public class JSONSchemaParser {
}
}
} else if (StringUtils.equals(type, PropertyConstant.ARRAY)) {
analyzeArray(concept, propertyName, object);
analyzeArray(concept, propertyName, object, processMap);
} else if (StringUtils.equals(type, PropertyConstant.OBJECT)) {
JSONObject obj = JSONUtil.createJsonObject(true);
concept.put(propertyName, obj);
analyzeObject(object, obj);
analyzeObject(object, obj, processMap);
} else if (StringUtils.equalsIgnoreCase(type, "null")) {
concept.put(propertyName, JSONObject.NULL);
} else {
@ -154,12 +160,12 @@ public class JSONSchemaParser {
}
}
private static void analyzeArray(JSONObject concept, String propertyName, JsonObject object) {
private static void analyzeArray(JSONObject concept, String propertyName, JsonObject object, Map<String, String> processMap) {
JSONArray array = new JSONArray();
if (object.has(PropertyConstant.ITEMS)) {
if (object.get(PropertyConstant.ITEMS).isJsonArray()) {
JsonArray jsonArray = object.get(PropertyConstant.ITEMS).getAsJsonArray();
loopArray(array, jsonArray, object, propertyName);
loopArray(array, jsonArray, object, propertyName, processMap);
} else {
JsonObject itemsObject = object.get(PropertyConstant.ITEMS).getAsJsonObject();
array.put(itemsObject);
@ -168,7 +174,7 @@ public class JSONSchemaParser {
concept.put(propertyName, array);
}
private static void loopArray(JSONArray array, JsonArray jsonArray, JsonObject object, String propertyName) {
private static void loopArray(JSONArray array, JsonArray jsonArray, JsonObject object, String propertyName, Map<String, String> processMap) {
jsonArray.forEach(element -> {
JsonObject jsonObject = element.getAsJsonObject();
if (object.has(PropertyConstant.ITEMS)) {
@ -200,12 +206,12 @@ public class JSONSchemaParser {
}
} else if (jsonObject.has(PropertyConstant.PROPERTIES)) {
JSONObject propertyConcept = JSONUtil.createJsonObject(true);
formatObject(jsonObject, propertyConcept);
formatObject(jsonObject, propertyConcept, processMap);
array.put(propertyConcept);
} else if (jsonObject.has(PropertyConstant.TYPE) && jsonObject.get(PropertyConstant.TYPE) instanceof JsonPrimitive) {
JSONObject newJsonObj = JSONUtil.createJsonObject(true);
analyzeProperty(newJsonObj, propertyName + PropertyConstant.ITEM, jsonObject);
analyzeProperty(newJsonObj, propertyName + PropertyConstant.ITEM, jsonObject, processMap);
array.put(newJsonObj.get(propertyName + PropertyConstant.ITEM));
}
} else if (object.has(PropertyConstant.ITEMS) && object.get(PropertyConstant.ITEMS).isJsonArray()) {
@ -215,24 +221,33 @@ public class JSONSchemaParser {
});
}
private static void analyzeDefinitions(JsonObject object) {
private static void analyzeDefinitions(JsonObject object, Map<String, String> processMap) {
JsonObject definitionsObj = object.get("definitions").getAsJsonObject();
for (Entry<String, JsonElement> entry : definitionsObj.entrySet()) {
String definitionKey = entry.getKey();
JsonObject definitionObj = definitionsObj.get(definitionKey).getAsJsonObject();
JSONObject obj = JSONUtil.createJsonObject(true);
analyzeRootSchemaElement(definitionObj, obj);
analyzeRootSchemaElement(definitionObj, obj, processMap);
}
}
private static String formerJson(String jsonSchema) {
JSONObject root = JSONUtil.createJsonObject(true);
analyzeSchema(jsonSchema, root);
Map<String, String> processMap = new HashMap<>();
String json;
analyzeSchema(jsonSchema, root, processMap);
// 格式化返回
if (root.opt(PropertyConstant.MS_OBJECT) != null) {
return root.get(PropertyConstant.MS_OBJECT).toString();
json = root.get(PropertyConstant.MS_OBJECT).toString();
} else {
json = root.toString();
}
return root.toString();
if (MapUtils.isNotEmpty(processMap)) {
for (String str : processMap.keySet()) {
json = json.replace(str, processMap.get(str));
}
}
return json;
}
public static String schemaToJson(String jsonSchema) {

View File

@ -61,5 +61,5 @@ public class ElementConstants {
public static final String MS_KEYSTORE_FILE_PATH = "MS-KEYSTORE-FILE-PATH";
public static final String MS_KEYSTORE_FILE_PASSWORD = "MS-KEYSTORE-FILE-PASSWORD";
public static final String VIRTUAL_STEPS = "VIRTUAL_STEPS";
public static final String REF = "$ref";
}

View File

@ -37,7 +37,6 @@ public class JSONUtil {
.disableHtmlEscaping()
.serializeNulls()
.create();
;
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);