refactor isAnyTypeSchema, isFreeFormType

This commit is contained in:
William Cheng 2020-12-07 23:09:05 +08:00
parent 751ffad8db
commit 36d366b19b
5 changed files with 56 additions and 89 deletions

View File

@ -2069,13 +2069,13 @@ public class DefaultCodegen implements CodegenConfig {
return schema.getFormat();
}
return "string";
} else if (isFreeFormObject(schema)) {
} else if (ModelUtils.isFreeFormObject(openAPI, schema)) {
// Note: the value of a free-form object cannot be an arbitrary type. Per OAS specification,
// it must be a map of string to values.
return "object";
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { // having property implies it's a model
return "object";
} else if (isAnyTypeSchema(schema)) {
} else if (ModelUtils.isAnyTypeSchema(openAPI, schema)) {
return "AnyType";
} else if (StringUtils.isNotEmpty(schema.getType())) {
if (!importMapping.containsKey(schema.getType())) {
@ -2284,7 +2284,7 @@ public class DefaultCodegen implements CodegenConfig {
m.xmlNamespace = schema.getXml().getNamespace();
m.xmlName = schema.getXml().getName();
}
if (isAnyTypeSchema(schema)) {
if (ModelUtils.isAnyTypeSchema(openAPI, schema)) {
// The 'null' value is allowed when the OAS schema is 'any type'.
// See https://github.com/OAI/OpenAPI-Specification/issues/1389
if (Boolean.FALSE.equals(schema.getNullable())) {
@ -3251,9 +3251,9 @@ public class DefaultCodegen implements CodegenConfig {
property.hasValidation = true;
}
} else if (isFreeFormObject(p)) {
} else if (ModelUtils.isFreeFormObject(openAPI, p)) {
property.isFreeFormObject = true;
} else if (isAnyTypeSchema(p)) {
} else if (ModelUtils.isAnyTypeSchema(openAPI, p)) {
// The 'null' value is allowed when the OAS schema is 'any type'.
// See https://github.com/OAI/OpenAPI-Specification/issues/1389
if (Boolean.FALSE.equals(p.getNullable())) {
@ -3366,13 +3366,13 @@ public class DefaultCodegen implements CodegenConfig {
}
CodegenProperty cp = fromProperty("inner", innerSchema);
updatePropertyForMap(property, cp);
} else if (isFreeFormObject(p)) {
} else if (ModelUtils.isFreeFormObject(openAPI, p)) {
property.isFreeFormObject = true;
property.baseType = getSchemaType(p);
if (languageSpecificPrimitives.contains(property.dataType)) {
property.isPrimitiveType = true;
}
} else if (isAnyTypeSchema(p)) {
} else if (ModelUtils.isAnyTypeSchema(openAPI, p)) {
property.isAnyType = true;
property.baseType = getSchemaType(p);
if (languageSpecificPrimitives.contains(property.dataType)) {
@ -6108,7 +6108,7 @@ public class DefaultCodegen implements CodegenConfig {
codegenProperty = codegenProperty.items;
}
}
} else if (isFreeFormObject(schema)) {
} else if (ModelUtils.isFreeFormObject(openAPI, schema)) {
// HTTP request body is free form object
CodegenProperty codegenProperty = fromProperty("FREE_FORM_REQUEST_BODY", schema);
if (codegenProperty != null) {
@ -6545,82 +6545,6 @@ public class DefaultCodegen implements CodegenConfig {
}
}
/**
* Return true if the schema value can be any type, i.e. it can be
* the null value, integer, number, string, object or array.
* One use case is when the "type" attribute in the OAS schema is unspecified.
*
* Examples:
*
* arbitraryTypeValue:
* description: This is an arbitrary type schema.
* It is not a free-form object.
* The value can be any type except the 'null' value.
* arbitraryTypeNullableValue:
* description: This is an arbitrary type schema.
* It is not a free-form object.
* The value can be any type, including the 'null' value.
* nullable: true
*
* @param schema the OAS schema.
* @return true if the schema value can be an arbitrary type.
*/
public boolean isAnyTypeSchema(Schema schema) {
if (schema == null) {
once(LOGGER).error("Schema cannot be null in isAnyTypeSchema check");
return false;
}
if (isFreeFormObject(schema)) {
// make sure it's not free form object
return false;
}
if (schema.getClass().equals(Schema.class) && schema.get$ref() == null && schema.getType() == null &&
(schema.getProperties() == null || schema.getProperties().isEmpty()) &&
schema.getAdditionalProperties() == null && schema.getNot() == null &&
schema.getEnum() == null) {
return true;
// If and when type arrays are supported in a future OAS specification,
// we could return true if the type array includes all possible JSON schema types.
}
return false;
}
/**
* Check to see if the schema is a free form object.
*
* A free form object is an object (i.e. 'type: object' in a OAS document) that:
* 1) Does not define properties, and
* 2) Is not a composed schema (no anyOf, oneOf, allOf), and
* 3) additionalproperties is not defined, or additionalproperties: true, or additionalproperties: {}.
*
* Examples:
*
* components:
* schemas:
* arbitraryObject:
* type: object
* description: This is a free-form object.
* The value must be a map of strings to values. The value cannot be 'null'.
* It cannot be array, string, integer, number.
* arbitraryNullableObject:
* type: object
* description: This is a free-form object.
* The value must be a map of strings to values. The value can be 'null',
* It cannot be array, string, integer, number.
* nullable: true
* arbitraryTypeValue:
* description: This is NOT a free-form object.
* The value can be any type except the 'null' value.
*
* @param schema potentially containing a '$ref'
* @return true if it's a free-form object
*/
protected boolean isFreeFormObject(Schema schema) {
return ModelUtils.isFreeFormObject(this.openAPI, schema);
}
/**
* Returns the additionalProperties Schema for the specified input schema.
*

View File

@ -17,6 +17,7 @@
package org.openapitools.codegen.languages;
import com.sun.org.apache.xpath.internal.operations.Mod;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.io.FilenameUtils;
@ -394,7 +395,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
if (ref != null && !ref.isEmpty()) {
type = openAPIType;
} else if ("object".equals(openAPIType) && isAnyTypeSchema(p)) {
} else if ("object".equals(openAPIType) && ModelUtils.isAnyTypeSchema(openAPI, p)) {
// Arbitrary type. Note this is not the same thing as free-form object.
type = "interface{}";
} else if (typeMapping.containsKey(openAPIType)) {

View File

@ -395,7 +395,7 @@ public class CppRestSdkClientCodegen extends AbstractCppCodegen {
return "new " + toModelName(ModelUtils.getSimpleRef(p.get$ref())) + "()";
} else if (ModelUtils.isStringSchema(p)) {
return "utility::conversions::to_string_t(\"\")";
} else if (isFreeFormObject(p)) {
} else if (ModelUtils.isFreeFormObject(openAPI, p)) {
return "new Object()";
}

View File

@ -747,14 +747,14 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
return prefix + modelName + fullSuffix;
}
}
if (isAnyTypeSchema(p)) {
if (ModelUtils.isAnyTypeSchema(openAPI, p)) {
return prefix + "bool, date, datetime, dict, float, int, list, str, none_type" + suffix;
}
// Resolve $ref because ModelUtils.isXYZ methods do not automatically resolve references.
if (ModelUtils.isNullable(ModelUtils.getReferencedSchema(this.openAPI, p))) {
fullSuffix = ", none_type" + suffix;
}
if (isFreeFormObject(p) && getAdditionalProperties(p) == null) {
if (ModelUtils.isFreeFormObject(openAPI, p) && getAdditionalProperties(p) == null) {
return prefix + "bool, date, datetime, dict, float, int, list, str" + fullSuffix;
}
if ((ModelUtils.isMapSchema(p) || "object".equals(p.getType())) && getAdditionalProperties(p) != null) {
@ -958,7 +958,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
}
String refModelName = getModelName(schema);
return toExampleValueRecursive(refModelName, refSchema, objExample, indentationLevel, prefix, exampleLine);
} else if (ModelUtils.isNullType(schema) || isAnyTypeSchema(schema)) {
} else if (ModelUtils.isNullType(schema) || ModelUtils.isAnyTypeSchema(openAPI, schema)) {
// The 'null' type is allowed in OAS 3.1 and above. It is not supported by OAS 3.0.x,
// though this tooling supports it.
return fullPrefix + "None" + closeChars;

View File

@ -1593,4 +1593,46 @@ public class ModelUtils {
return new SemVer(version);
}
/**
* Return true if the schema value can be any type, i.e. it can be
* the null value, integer, number, string, object or array.
* One use case is when the "type" attribute in the OAS schema is unspecified.
*
* Examples:
*
* arbitraryTypeValue:
* description: This is an arbitrary type schema.
* It is not a free-form object.
* The value can be any type except the 'null' value.
* arbitraryTypeNullableValue:
* description: This is an arbitrary type schema.
* It is not a free-form object.
* The value can be any type, including the 'null' value.
* nullable: true
*
* @param schema the OAS schema.
* @return true if the schema value can be an arbitrary type.
*/
public static boolean isAnyTypeSchema(OpenAPI openAPI, Schema schema) {
if (schema == null) {
once(LOGGER).error("Schema cannot be null in isAnyTypeSchema check");
return false;
}
if (isFreeFormObject(openAPI, schema)) {
// make sure it's not free form object
return false;
}
if (schema.getClass().equals(Schema.class) && schema.get$ref() == null && schema.getType() == null &&
(schema.getProperties() == null || schema.getProperties().isEmpty()) &&
schema.getAdditionalProperties() == null && schema.getNot() == null &&
schema.getEnum() == null) {
return true;
// If and when type arrays are supported in a future OAS specification,
// we could return true if the type array includes all possible JSON schema types.
}
return false;
}
}