From 2a9ba2ce2ea9974533ce5ce18f0345de54a8ea55 Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Mon, 6 Feb 2023 01:20:07 +0100 Subject: [PATCH 1/9] Fix #14577: Parse JsonSchema for array in OpenAPI 3.1 ModelUtils.isArraySchema(schema) is now returning true if the schema is an instance of ArraySchema or JsonSchema with one "array" type. A new function ModelUtils.getArrayItems(schema) is used to get items in an array schema whatever the type of the schema (ArraySchema or JsonSchema) Add test testOpenAPI310ResponsesJsonSchemaIsArray to validate JsonSchema is correctly translate to an array --- .../openapitools/codegen/DefaultCodegen.java | 36 ++++++------ .../codegen/InlineModelResolver.java | 16 +++-- .../codegen/OpenAPINormalizer.java | 5 +- .../codegen/examples/ExampleGenerator.java | 10 ++-- .../codegen/examples/XmlExampleGenerator.java | 4 +- .../codegen/languages/AbstractAdaCodegen.java | 3 +- .../languages/AbstractApexCodegen.java | 7 +-- .../languages/AbstractDartCodegen.java | 2 +- .../languages/AbstractEiffelCodegen.java | 3 +- .../codegen/languages/AbstractGoCodegen.java | 3 +- .../languages/AbstractGraphQLCodegen.java | 3 +- .../languages/AbstractJavaCodegen.java | 2 +- .../languages/AbstractJuliaCodegen.java | 3 +- .../languages/AbstractKotlinCodegen.java | 4 +- .../codegen/languages/AbstractPhpCodegen.java | 5 +- .../AbstractPythonConnexionServerCodegen.java | 3 +- .../languages/AbstractRubyCodegen.java | 2 +- .../languages/AbstractScalaCodegen.java | 2 +- .../AbstractTypeScriptClientCodegen.java | 5 +- .../languages/AndroidClientCodegen.java | 3 +- .../codegen/languages/ApexClientCodegen.java | 2 +- .../codegen/languages/BashClientCodegen.java | 3 +- .../languages/CLibcurlClientCodegen.java | 2 +- .../languages/ClojureClientCodegen.java | 5 +- .../languages/ConfluenceWikiCodegen.java | 3 +- .../languages/CppPistacheServerCodegen.java | 3 +- .../languages/CppQtAbstractCodegen.java | 6 +- .../languages/CppRestSdkClientCodegen.java | 3 +- .../languages/CppRestbedServerCodegen.java | 3 +- .../CppRestbedServerDeprecatedCodegen.java | 3 +- .../languages/CrystalClientCodegen.java | 2 +- .../languages/ElixirClientCodegen.java | 3 +- .../codegen/languages/ElmClientCodegen.java | 3 +- .../GraphQLNodeJSExpressServerCodegen.java | 3 +- .../languages/HaskellHttpClientCodegen.java | 3 +- .../languages/HaskellServantCodegen.java | 3 +- .../languages/HaskellYesodServerCodegen.java | 3 +- .../languages/JMeterClientCodegen.java | 3 +- .../JavascriptApolloClientCodegen.java | 3 +- .../languages/JavascriptClientCodegen.java | 3 +- ...JavascriptClosureAngularClientCodegen.java | 3 +- .../codegen/languages/LuaClientCodegen.java | 3 +- .../codegen/languages/NimClientCodegen.java | 3 +- .../codegen/languages/OCamlClientCodegen.java | 18 +++--- .../codegen/languages/ObjcClientCodegen.java | 3 +- .../codegen/languages/PerlClientCodegen.java | 3 +- .../PhpDataTransferClientCodegen.java | 4 +- .../PhpMezzioPathHandlerServerCodegen.java | 4 +- .../languages/PhpSilexServerCodegen.java | 3 +- .../languages/PhpSymfonyServerCodegen.java | 3 +- .../languages/PowerShellClientCodegen.java | 3 +- .../languages/ProtobufSchemaCodegen.java | 3 +- .../languages/PythonClientCodegen.java | 9 +-- .../languages/PythonFastAPIServerCodegen.java | 3 +- .../languages/PythonLegacyClientCodegen.java | 3 +- .../languages/PythonNextgenClientCodegen.java | 3 +- .../languages/PythonPriorClientCodegen.java | 9 +-- .../codegen/languages/RClientCodegen.java | 3 +- .../codegen/languages/RustClientCodegen.java | 5 +- .../codegen/languages/RustServerCodegen.java | 6 +- .../languages/ScalaFinchServerCodegen.java | 3 +- .../languages/ScalaGatlingCodegen.java | 3 +- .../ScalaPlayFrameworkServerCodegen.java | 2 +- .../languages/StaticHtml2Generator.java | 3 +- .../languages/StaticHtmlGenerator.java | 3 +- .../languages/Swift5ClientCodegen.java | 3 +- .../languages/TypeScriptClientCodegen.java | 11 ++-- .../TypeScriptNodeClientCodegen.java | 2 +- .../codegen/utils/ModelUtils.java | 58 +++++++++++++++++-- .../codegen/DefaultCodegenTest.java | 14 +++++ 70 files changed, 189 insertions(+), 190 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index f198bb1c8ae..69fdb3b1203 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1007,7 +1007,7 @@ public class DefaultCodegen implements CodegenConfig { addOneOfNameExtension((ComposedSchema) s, n); } } else if (ModelUtils.isArraySchema(s)) { - Schema items = ((ArraySchema) s).getItems(); + Schema items = ModelUtils.getArrayItems(s); if (ModelUtils.isComposedSchema(items)) { addOneOfNameExtension((ComposedSchema) items, nOneOf); addOneOfInterfaceModel((ComposedSchema) items, nOneOf, openAPI); @@ -1929,8 +1929,7 @@ public class DefaultCodegen implements CodegenConfig { String inner = getSchemaType(additionalProperties); return instantiationTypes.get("map") + "<String, " + inner + ">"; } else if (ModelUtils.isArraySchema(schema)) { - ArraySchema arraySchema = (ArraySchema) schema; - String inner = getSchemaType(getSchemaItems(arraySchema)); + String inner = getSchemaType(getSchemaItems(schema)); String parentType; if (ModelUtils.isSet(schema)) { parentType = "set"; @@ -2237,7 +2236,11 @@ public class DefaultCodegen implements CodegenConfig { } - protected Schema<?> getSchemaItems(ArraySchema schema) { + protected Schema<?> getSchemaItems(Schema schema) { + if (!ModelUtils.isArraySchema(schema)) { + LOGGER.error("Schema `{}` is not an array.", schema.getName()); + return null; + } Schema<?> items = schema.getItems(); if (items == null) { LOGGER.error("Undefined array inner type for `{}`. Default to String.", schema.getName()); @@ -3924,8 +3927,7 @@ public class DefaultCodegen implements CodegenConfig { // handle inner property String itemName = getItemsName(p, name); - ArraySchema arraySchema = (ArraySchema) p; - Schema innerSchema = unaliasSchema(getSchemaItems(arraySchema)); + Schema innerSchema = unaliasSchema(getSchemaItems(p)); CodegenProperty cp = fromProperty(itemName, innerSchema, false); updatePropertyForArray(property, cp); } else if (ModelUtils.isTypeObjectSchema(p)) { @@ -4185,8 +4187,7 @@ public class DefaultCodegen implements CodegenConfig { CodegenProperty cm = fromProperty("response", responseSchema, false); if (ModelUtils.isArraySchema(responseSchema)) { - ArraySchema as = (ArraySchema) responseSchema; - CodegenProperty innerProperty = fromProperty("response", getSchemaItems(as), false); + CodegenProperty innerProperty = fromProperty("response", getSchemaItems(responseSchema), false); op.returnBaseType = innerProperty.baseType; } else if (ModelUtils.isMapSchema(responseSchema)) { CodegenProperty innerProperty = fromProperty("response", getAdditionalProperties(responseSchema), false); @@ -4680,8 +4681,7 @@ public class DefaultCodegen implements CodegenConfig { r.simpleType = false; r.isArray = true; r.containerType = cp.containerType; - ArraySchema as = (ArraySchema) responseSchema; - CodegenProperty items = fromProperty("response", getSchemaItems(as), false); + CodegenProperty items = fromProperty("response", getSchemaItems(responseSchema), false); r.setItems(items); CodegenProperty innerCp = items; @@ -5054,8 +5054,7 @@ public class DefaultCodegen implements CodegenConfig { } addVarsRequiredVarsAdditionalProps(parameterSchema, codegenParameter); } else if (ModelUtils.isArraySchema(parameterSchema)) { - final ArraySchema arraySchema = (ArraySchema) parameterSchema; - Schema inner = getSchemaItems(arraySchema); + Schema inner = getSchemaItems(parameterSchema); collectionFormat = getCollectionFormat(parameter); // default to csv: @@ -6823,7 +6822,7 @@ public class DefaultCodegen implements CodegenConfig { // any schema with no type set, composed schemas often do this ; } else if (ModelUtils.isArraySchema(ps)) { - Schema inner = getSchemaItems((ArraySchema) ps); + Schema inner = getSchemaItems(ps); CodegenProperty arrayInnerProperty = fromProperty("inner", inner, false); codegenParameter.items = arrayInnerProperty; codegenParameter.mostInnerItems = arrayInnerProperty.mostInnerItems; @@ -7092,11 +7091,10 @@ public class DefaultCodegen implements CodegenConfig { if (ModelUtils.isGenerateAliasAsModel(schema) && StringUtils.isNotBlank(name)) { this.addBodyModelSchema(codegenParameter, name, schema, imports, bodyParameterName, true); } else { - final ArraySchema arraySchema = (ArraySchema) schema; - Schema inner = getSchemaItems(arraySchema); - CodegenProperty codegenProperty = fromProperty("property", arraySchema, false); + Schema inner = getSchemaItems(schema); + CodegenProperty codegenProperty = fromProperty("property", schema, false); if (codegenProperty == null) { - throw new RuntimeException("CodegenProperty cannot be null. arraySchema for debugging: " + arraySchema); + throw new RuntimeException("CodegenProperty cannot be null. schema for debugging: " + schema); } if (!addSchemaImportsFromV3SpecLocations) { @@ -7117,7 +7115,7 @@ public class DefaultCodegen implements CodegenConfig { } if (mostInnerItem == null) { - throw new RuntimeException("mostInnerItem (codegen property of array item) cannot be null. " + arraySchema); + throw new RuntimeException("mostInnerItem (codegen property of array item) cannot be null. " + schema); } if (StringUtils.isEmpty(bodyParameterName)) { @@ -7132,7 +7130,7 @@ public class DefaultCodegen implements CodegenConfig { codegenParameter.paramName = toArrayModelParamName(codegenParameter.baseName); codegenParameter.items = codegenProperty.items; codegenParameter.mostInnerItems = codegenProperty.mostInnerItems; - codegenParameter.dataType = getTypeDeclaration(arraySchema); + codegenParameter.dataType = getTypeDeclaration(schema); codegenParameter.baseType = getSchemaType(inner); codegenParameter.isContainer = Boolean.TRUE; codegenParameter.isNullable = codegenProperty.isNullable; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java index bec487686bd..f4110bd7576 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java @@ -305,9 +305,8 @@ public class InlineModelResolver { return; } // Check array items - if (schema instanceof ArraySchema) { - ArraySchema array = (ArraySchema) schema; - Schema items = array.getItems(); + if (ModelUtils.isArraySchema(schema)) { + Schema items = ModelUtils.getArrayItems(schema); /*if (items.getTitle() != null) { LOGGER.info("schema title {}", items); throw new RuntimeException("getTitle for array item is not null"); @@ -325,7 +324,7 @@ public class InlineModelResolver { if (isModelNeeded(items)) { // If this schema should be split into its own model, do so Schema refSchema = this.makeSchemaInComponents(schemaName, items); - array.setItems(refSchema); + schema.setItems(refSchema); } } // Check allOf, anyOf, oneOf for inline models @@ -733,9 +732,8 @@ public class InlineModelResolver { propsToUpdate.put(key, schema); modelsToAdd.put(modelName, model); } - } else if (property instanceof ArraySchema) { - ArraySchema ap = (ArraySchema) property; - Schema inner = ap.getItems(); + } else if (ModelUtils.isArraySchema(property)) { + Schema inner = ModelUtils.getArrayItems(property); if (inner instanceof ObjectSchema) { ObjectSchema op = (ObjectSchema) inner; if (op.getProperties() != null && op.getProperties().size() > 0) { @@ -746,12 +744,12 @@ public class InlineModelResolver { if (existing != null) { Schema schema = new Schema().$ref(existing); schema.setRequired(op.getRequired()); - ap.setItems(schema); + property.setItems(schema); } else { modelName = addSchemas(modelName, innerModel); Schema schema = new Schema().$ref(modelName); schema.setRequired(op.getRequired()); - ap.setItems(schema); + property.setItems(schema); } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index b4ec2e1ea03..32be85cdf46 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -301,8 +301,9 @@ public class OpenAPINormalizer { visitedSchemas.add(schema); } - if (schema instanceof ArraySchema) { - normalizeSchema(schema.getItems(), visitedSchemas); + if (ModelUtils.isArraySchema(schema)) { + Schema itemsSchema = ModelUtils.getArrayItems(schema); + normalizeSchema(itemsSchema, visitedSchemas); } else if (schema.getAdditionalProperties() instanceof Schema) { // map normalizeSchema((Schema) schema.getAdditionalProperties(), visitedSchemas); } else if (ModelUtils.isComposedSchema(schema)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java index a8d7286b582..29934e4efde 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java @@ -19,7 +19,6 @@ package org.openapitools.codegen.examples; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.utils.ModelUtils; @@ -79,10 +78,9 @@ public class ExampleGenerator { } if (ModelUtils.isArraySchema(responseSchema)) { // array of schema - ArraySchema as = (ArraySchema) responseSchema; - if (as.getItems() != null) { // array of primitive types + if (ModelUtils.getArrayItems(responseSchema) != null) { // array of primitive types return generate((Map<String, Object>) responseSchema.getExample(), - new ArrayList<>(producesInfo), as); + new ArrayList<>(producesInfo), responseSchema); } else { // TODO log warning message as such case is not handled at the moment return null; @@ -229,9 +227,9 @@ public class ExampleGenerator { } return Boolean.TRUE; } else if (ModelUtils.isArraySchema(property)) { - Schema innerType = ((ArraySchema) property).getItems(); + Schema innerType = ModelUtils.getArrayItems(property); if (innerType != null) { - int arrayLength = null == ((ArraySchema) property).getMaxItems() ? 2 : ((ArraySchema) property).getMaxItems(); + int arrayLength = null == property.getMaxItems() ? 2 : property.getMaxItems(); // avoid memory issues by limiting to max. 5 items arrayLength = Math.min(arrayLength, 5); Object[] objectProperties = new Object[arrayLength]; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/XmlExampleGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/XmlExampleGenerator.java index 3151c0bffd9..065a4b42353 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/XmlExampleGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/XmlExampleGenerator.java @@ -17,7 +17,6 @@ package org.openapitools.codegen.examples; -import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.XML; import org.apache.commons.lang3.StringUtils; @@ -128,8 +127,7 @@ public class XmlExampleGenerator { StringBuilder sb = new StringBuilder(); if (ModelUtils.isArraySchema(schema)) { - ArraySchema as = (ArraySchema) schema; - Schema inner = as.getItems(); + Schema inner = ModelUtils.getArrayItems(schema); boolean wrapped = false; if (schema.getXml() != null && schema.getXml().getWrapped() != null && schema.getXml().getWrapped()) { wrapped = true; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractAdaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractAdaCodegen.java index dd67f9f4b57..c3898d86452 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractAdaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractAdaCodegen.java @@ -451,8 +451,7 @@ abstract public class AbstractAdaCodegen extends DefaultCodegen implements Codeg } if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getTypeDeclaration(inner) + "_Vectors.Vector"; } if (ModelUtils.isMapSchema(p)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java index d64a2d56714..f3d5ac29cdd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java @@ -188,10 +188,9 @@ public abstract class AbstractApexCodegen extends DefaultCodegen implements Code @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); if (inner == null) { - LOGGER.warn("{}(array property) does not have a proper inner type defined", ap.getName()); + LOGGER.warn("{}(array property) does not have a proper inner type defined", p.getName()); // TODO maybe better defaulting to StringProperty than returning null return null; } @@ -318,7 +317,7 @@ public abstract class AbstractApexCodegen extends DefaultCodegen implements Code if (ModelUtils.isArraySchema(p)) { example = "new " + getTypeDeclaration(p) + "{" + toExampleValue( - ((ArraySchema) p).getItems()) + "}"; + ModelUtils.getArrayItems(p)) + "}"; } else if (ModelUtils.isBooleanSchema(p)) { example = String.valueOf(!"false".equals(example)); } else if (ModelUtils.isByteArraySchema(p)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java index 11495fd7672..985aa9725f1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java @@ -493,7 +493,7 @@ public abstract class AbstractDartCodegen extends DefaultCodegen { Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems((ArraySchema) schema); + Schema<?> items = getSchemaItems(schema); return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">"; } if (ModelUtils.isMapSchema(target)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java index 112861cbb8f..6941e698aae 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java @@ -296,8 +296,7 @@ public abstract class AbstractEiffelCodegen extends DefaultCodegen implements Co @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "LIST [" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java index a72ca4a6f35..64cca0b5041 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java @@ -345,8 +345,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); // In OAS 3.0.x, the array "items" attribute is required. // In OAS >= 3.1, the array "items" attribute is optional such that the OAS // specification is aligned with the JSON schema specification. diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGraphQLCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGraphQLCodegen.java index b72b574e89a..8b5bf336aba 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGraphQLCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGraphQLCodegen.java @@ -273,8 +273,7 @@ public abstract class AbstractGraphQLCodegen extends DefaultCodegen implements C @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = (Schema) p.getAdditionalProperties(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index ad513d893f5..a03c57bb75f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -949,7 +949,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems((ArraySchema) schema); + Schema<?> items = getSchemaItems(schema); return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">"; } else if (ModelUtils.isMapSchema(target)) { // Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJuliaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJuliaCodegen.java index 822539153ae..1188058a1d0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJuliaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJuliaCodegen.java @@ -317,8 +317,7 @@ public abstract class AbstractJuliaCodegen extends DefaultCodegen { @Override public String getTypeDeclaration(Schema schema) { if (ModelUtils.isArraySchema(schema)) { - ArraySchema ap = (ArraySchema) schema; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(schema); return getSchemaType(schema) + "{" + getTypeDeclaration(inner) + "}"; } else if (ModelUtils.isSet(schema)) { Schema inner = getAdditionalProperties(schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index 023a2b412fe..1f3707dffc0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -381,7 +381,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems((ArraySchema) schema); + Schema<?> items = getSchemaItems(schema); return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">"; } else if (ModelUtils.isMapSchema(target)) { // Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines @@ -1094,7 +1094,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co } StringBuilder defaultContent = new StringBuilder(); - Schema<?> itemsSchema = getSchemaItems((ArraySchema) schema); + Schema<?> itemsSchema = getSchemaItems(schema); _default.elements().forEachRemaining((element) -> { itemsSchema.setDefault(element.asText()); defaultContent.append(toDefaultValue(itemsSchema)).append(","); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java index 1620e905da0..9e879c35186 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java @@ -317,11 +317,10 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); if (inner == null) { LOGGER.warn("{}(array property) does not have a proper inner type defined.Default to string", - ap.getName()); + p.getName()); inner = new StringSchema().description("TODO default missing array inner type to string"); } return getTypeDeclaration(inner) + "[]"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonConnexionServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonConnexionServerCodegen.java index 88ae7be78fd..197dd08eae5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonConnexionServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonConnexionServerCodegen.java @@ -342,8 +342,7 @@ public abstract class AbstractPythonConnexionServerCodegen extends AbstractPytho @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java index 3ecbc7d2f4e..c818dba0b2a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java @@ -119,7 +119,7 @@ abstract public class AbstractRubyCodegen extends DefaultCodegen implements Code @Override public String getTypeDeclaration(Schema schema) { if (ModelUtils.isArraySchema(schema)) { - Schema inner = ((ArraySchema) schema).getItems(); + Schema inner = ModelUtils.getArrayItems(schema); return getSchemaType(schema) + "<" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(schema)) { Schema inner = getAdditionalProperties(schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java index 3fa7e4c9368..1d5fe33898d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java @@ -366,7 +366,7 @@ public abstract class AbstractScalaCodegen extends DefaultCodegen { Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems((ArraySchema) schema); + Schema<?> items = getSchemaItems(schema); return getSchemaType(target) + "[" + getTypeDeclaration(items) + "]"; } else if (ModelUtils.isMapSchema(target)) { Schema<?> inner = getAdditionalProperties(target); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java index 779a71ccf60..44f91dcc9a4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java @@ -601,7 +601,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - Schema<?> items = getSchemaItems((ArraySchema) p); + Schema<?> items = getSchemaItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(unaliasSchema(items)) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema<?> inner = getSchemaAdditionalProperties(p); @@ -1120,8 +1120,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp return filteredSchemas.stream().map(schema -> { String schemaType = getSchemaType(schema); if (ModelUtils.isArraySchema(schema)) { - ArraySchema ap = (ArraySchema) schema; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(schema); schemaType = schemaType + "<" + getSchemaType(inner) + ">"; } return schemaType; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AndroidClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AndroidClientCodegen.java index 597e94fd510..0ddc483af0b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AndroidClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AndroidClientCodegen.java @@ -225,8 +225,7 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java index f8d43504d27..16f43cc9225 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java @@ -223,7 +223,7 @@ public class ApexClientCodegen extends AbstractApexCodegen { public String toDefaultValue(Schema p) { String out = null; if (ModelUtils.isArraySchema(p)) { - Schema inner = ((ArraySchema) p).getItems(); + Schema inner = ModelUtils.getArrayItems(p); out = String.format( Locale.ROOT, "new List<%s>()", diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/BashClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/BashClientCodegen.java index 64980677c15..2511e38264b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/BashClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/BashClientCodegen.java @@ -429,8 +429,7 @@ public class BashClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java index 16436597ffc..072905ff707 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java @@ -407,7 +407,7 @@ public class CLibcurlClientCodegen extends DefaultCodegen implements CodegenConf public String getTypeDeclaration(Schema schema) { /* comment out below as we'll do it in the template instead if (ModelUtils.isArraySchema(schema)) { - Schema inner = ((ArraySchema) schema).getItems(); + Schema inner = ModelUtils.getArrayItems(schema); return getSchemaType(schema) + "<" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(schema)) { Schema inner = (Schema) schema.getAdditionalProperties(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java index c5163ecb6e2..08edba79c88 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ClojureClientCodegen.java @@ -165,9 +165,8 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi @Override public String getTypeDeclaration(Schema p) { - if (p instanceof ArraySchema) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + if (ModelUtils.isArraySchema(p)) { + Schema inner = ModelUtils.getArrayItems(p); return "(s/coll-of " + getTypeDeclaration(inner) + ")"; } else if (ModelUtils.isMapSchema(p)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ConfluenceWikiCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ConfluenceWikiCodegen.java index a8ea8c701e8..fa774134e3c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ConfluenceWikiCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ConfluenceWikiCodegen.java @@ -108,8 +108,7 @@ public class ConfluenceWikiCodegen extends DefaultCodegen implements CodegenConf @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java index 1026f9e9eb6..487edf92452 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java @@ -363,8 +363,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { String openAPIType = getSchemaType(p); if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">"; } if (ModelUtils.isMapSchema(p)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQtAbstractCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQtAbstractCodegen.java index 573242d5494..1312a65f1b7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQtAbstractCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQtAbstractCodegen.java @@ -186,8 +186,7 @@ public abstract class CppQtAbstractCodegen extends AbstractCppCodegen implements String openAPIType = getSchemaType(p); if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); @@ -229,8 +228,7 @@ public abstract class CppQtAbstractCodegen extends AbstractCppCodegen implements Schema inner = getAdditionalProperties(p); return "QMap<QString, " + getTypeDeclaration(inner) + ">()"; } else if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "QList<" + getTypeDeclaration(inner) + ">()"; } else if (ModelUtils.isStringSchema(p)) { return "QString(\"\")"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java index ec800290c28..9e054e0aa9a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java @@ -367,8 +367,7 @@ public class CppRestSdkClientCodegen extends AbstractCppCodegen { String openAPIType = getSchemaType(p); if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java index 93ade02496e..350c80773ca 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerCodegen.java @@ -379,8 +379,7 @@ public class CppRestbedServerCodegen extends AbstractCppCodegen { String openAPIType = getSchemaType(p); if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerDeprecatedCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerDeprecatedCodegen.java index 0e243b2f61c..885d40f3c90 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerDeprecatedCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestbedServerDeprecatedCodegen.java @@ -351,8 +351,7 @@ public class CppRestbedServerDeprecatedCodegen extends AbstractCppCodegen { String openAPIType = getSchemaType(p); if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java index fd072c6bd02..e5570801575 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java @@ -809,7 +809,7 @@ public class CrystalClientCodegen extends DefaultCodegen { @Override public String getTypeDeclaration(Schema schema) { if (ModelUtils.isArraySchema(schema)) { - Schema inner = ((ArraySchema) schema).getItems(); + Schema inner = ModelUtils.getArrayItems(schema); return getSchemaType(schema) + "(" + getTypeDeclaration(inner) + ")"; } else if (ModelUtils.isMapSchema(schema)) { Schema inner = getAdditionalProperties(schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java index dbde8ce1b58..8969f303595 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java @@ -546,8 +546,7 @@ public class ElixirClientCodegen extends DefaultCodegen { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java index 89d2c4cbf04..8d4fc647781 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElmClientCodegen.java @@ -448,8 +448,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getTypeDeclaration(inner); } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GraphQLNodeJSExpressServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GraphQLNodeJSExpressServerCodegen.java index fc68c05827a..383ea898a56 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GraphQLNodeJSExpressServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GraphQLNodeJSExpressServerCodegen.java @@ -124,8 +124,7 @@ public class GraphQLNodeJSExpressServerCodegen extends AbstractGraphQLCodegen im @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); // IMPORTANT NOTE we add the braces within template because there we have the possibility to differentiate // between some specific types for GraphQL: diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java index 407e05a09af..ace5d90a36a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellHttpClientCodegen.java @@ -645,8 +645,7 @@ public class HaskellHttpClientCodegen extends DefaultCodegen implements CodegenC @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java index 96397b796f4..3c590207463 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellServantCodegen.java @@ -378,8 +378,7 @@ public class HaskellServantCodegen extends DefaultCodegen implements CodegenConf @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellYesodServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellYesodServerCodegen.java index 8b8c49076fc..6038add9efc 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellYesodServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/HaskellYesodServerCodegen.java @@ -301,8 +301,7 @@ public class HaskellYesodServerCodegen extends DefaultCodegen implements Codegen @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JMeterClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JMeterClientCodegen.java index bad912d9a8f..4487c9edcd4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JMeterClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JMeterClientCodegen.java @@ -204,8 +204,7 @@ public class JMeterClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java index e979a72b2c1..ff7ffe59817 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java @@ -610,8 +610,7 @@ public class JavascriptApolloClientCodegen extends DefaultCodegen implements Cod @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java index 5d388308675..8d5cc606280 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java @@ -595,8 +595,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClosureAngularClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClosureAngularClientCodegen.java index b0649d5a8a1..e62e1230db5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClosureAngularClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClosureAngularClientCodegen.java @@ -225,8 +225,7 @@ public class JavascriptClosureAngularClientCodegen extends DefaultCodegen implem @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<!" + getTypeDeclaration(inner) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/LuaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/LuaClientCodegen.java index aeff481eaf6..d8e168db614 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/LuaClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/LuaClientCodegen.java @@ -368,8 +368,7 @@ public class LuaClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getTypeDeclaration(inner); } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java index af90ec386ad..e7d024ba8af 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java @@ -274,8 +274,7 @@ public class NimClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); if (inner == null) { return null; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java index 509f6d49956..ea2812ec9ca 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java @@ -279,8 +279,9 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig } private void collectEnumSchemas(String parentName, String sName, Schema schema) { - if (schema instanceof ArraySchema) { - collectEnumSchemas(parentName, sName, ((ArraySchema) schema).getItems()); + if (ModelUtils.isArraySchema(schema)) { + Schema itemsSchema = ModelUtils.getArrayItems(schema); + collectEnumSchemas(parentName, sName, itemsSchema); } else if (schema instanceof MapSchema && schema.getAdditionalProperties() instanceof Schema) { collectEnumSchemas(parentName, sName, (Schema) schema.getAdditionalProperties()); } else if (isEnumSchema(schema)) { @@ -317,11 +318,11 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig collectEnumSchemas(pName, (Schema) schema.getAdditionalProperties()); } - if (schema instanceof ArraySchema) { - ArraySchema s = (ArraySchema) schema; - if (s.getItems() != null) { + if (ModelUtils.isArraySchema(schema)) { + Schema itemsSchema = ModelUtils.getArrayItems(schema); + if (itemsSchema != null) { String pName = parentName != null ? parentName + "_" + sName : sName; - collectEnumSchemas(pName, s.getItems()); + collectEnumSchemas(pName, itemsSchema); } } } @@ -581,11 +582,10 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); if (inner == null) { LOGGER.warn("{}(array property) does not have a proper inner type defined.Default to string", - ap.getName()); + p.getName()); inner = new StringSchema().description("TODO default missing array inner type to string"); } return getTypeDeclaration(inner) + " list"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java index 0b7f640cba5..239bbe0bbd7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ObjcClientCodegen.java @@ -370,8 +370,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); String innerTypeDeclaration = getTypeDeclaration(inner); if (innerTypeDeclaration.endsWith("*")) { innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PerlClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PerlClientCodegen.java index d4a44799ba4..852979216b1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PerlClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PerlClientCodegen.java @@ -259,8 +259,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpDataTransferClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpDataTransferClientCodegen.java index 796d8ad8478..bde02d214ff 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpDataTransferClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpDataTransferClientCodegen.java @@ -248,7 +248,7 @@ public class PhpDataTransferClientCodegen extends AbstractPhpCodegen { Schema parameterSchema = ModelUtils.getReferencedSchema(openAPI, parameter.getSchema()); // array if (ModelUtils.isArraySchema(parameterSchema)) { - Schema itemSchema = ((ArraySchema) parameterSchema).getItems(); + Schema itemSchema = ModelUtils.getArrayItems(parameterSchema); ArraySchema arraySchema = new ArraySchema(); arraySchema.setMinItems(parameterSchema.getMinItems()); arraySchema.setMaxItems(parameterSchema.getMaxItems()); @@ -389,7 +389,7 @@ public class PhpDataTransferClientCodegen extends AbstractPhpCodegen { } } else if (ModelUtils.isArraySchema(schema)) { //Recursively process schema of array items - generateContainerSchemas(openAPI, ((ArraySchema) schema).getItems()); + generateContainerSchemas(openAPI, ModelUtils.getArrayItems(schema)); isContainer = Boolean.TRUE; } else if (ModelUtils.isMapSchema(schema)) { //Recursively process schema of map items diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpMezzioPathHandlerServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpMezzioPathHandlerServerCodegen.java index 50050aa23fa..5d42a2ca794 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpMezzioPathHandlerServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpMezzioPathHandlerServerCodegen.java @@ -248,7 +248,7 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen { Schema parameterSchema = ModelUtils.getReferencedSchema(openAPI, queryParameter.getSchema()); // array if (ModelUtils.isArraySchema(parameterSchema)) { - Schema itemSchema = ((ArraySchema) parameterSchema).getItems(); + Schema itemSchema = ModelUtils.getArrayItems(parameterSchema); ArraySchema arraySchema = new ArraySchema(); arraySchema.setMinItems(parameterSchema.getMinItems()); arraySchema.setMaxItems(parameterSchema.getMaxItems()); @@ -390,7 +390,7 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen { } } else if (ModelUtils.isArraySchema(schema)) { //Recursively process schema of array items - generateContainerSchemas(openAPI, ((ArraySchema) schema).getItems()); + generateContainerSchemas(openAPI, ModelUtils.getArrayItems(schema)); isContainer = Boolean.TRUE; } else if (ModelUtils.isMapSchema(schema)) { //Recursively process schema of map items diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSilexServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSilexServerCodegen.java index a2388a6fc12..0f3707da7b4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSilexServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSilexServerCodegen.java @@ -175,8 +175,7 @@ public class PhpSilexServerCodegen extends DefaultCodegen implements CodegenConf @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java index 85331d98613..56d0588e787 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java @@ -535,8 +535,7 @@ public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements Codeg @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getTypeDeclaration(inner); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java index 2a6c52fc201..8b321a5dc21 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java @@ -992,8 +992,7 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getTypeDeclaration(inner) + "[]"; } else if (ModelUtils.isMapSchema(p)) { return "System.Collections.Hashtable"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java index 79a55ee8bab..e82f882e1b2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java @@ -608,8 +608,7 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java index 3eecc392a80..7f406093af8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java @@ -1607,8 +1607,7 @@ public class PythonClientCodegen extends AbstractPythonCodegen { // TODO add code here to add property values too if they exist } } else if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); if (inner == null) { // In OAS 3.0.x, the array "items" attribute is required. // In OAS >= 3.1, the array "items" attribute is optional such that the OAS @@ -1965,8 +1964,7 @@ public class PythonClientCodegen extends AbstractPythonCodegen { // complex composed array type schemas not yet handled and the code returns early return fullPrefix + "[]" + closeChars; } - ArraySchema arrayschema = (ArraySchema) schema; - Schema itemSchema = arrayschema.getItems(); + Schema itemSchema = ModelUtils.getArrayItems(schema); String itemModelName = getModelName(itemSchema); if(includedSchemas.contains(schema)) { return ""; @@ -2129,8 +2127,7 @@ public class PythonClientCodegen extends AbstractPythonCodegen { } else if (simpleStringSchema(schema)) { return propName + "_example"; } else if (ModelUtils.isArraySchema(schema)) { - ArraySchema arraySchema = (ArraySchema) schema; - Schema itemSchema = arraySchema.getItems(); + Schema itemSchema = ModelUtils.getArrayItems(schema); example = getObjectExample(itemSchema); if (example != null) { return example; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonFastAPIServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonFastAPIServerCodegen.java index 76c13906f07..71813aad20a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonFastAPIServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonFastAPIServerCodegen.java @@ -191,8 +191,7 @@ public class PythonFastAPIServerCodegen extends AbstractPythonCodegen { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java index b33c6825519..bb0b753a5a0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java @@ -452,8 +452,7 @@ public class PythonLegacyClientCodegen extends AbstractPythonCodegen implements @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonNextgenClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonNextgenClientCodegen.java index 52e021c9c73..e89a731d21b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonNextgenClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonNextgenClientCodegen.java @@ -354,8 +354,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java index c6d071e3b99..670cce62e74 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java @@ -894,8 +894,7 @@ public class PythonPriorClientCodegen extends PythonLegacyClientCodegen { Schema inner = getAdditionalProperties(p); return prefix + "{str: " + getTypeString(inner, "(", ")", referencedModelNames) + "}" + fullSuffix; } else if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); if (inner == null) { // In OAS 3.0.x, the array "items" attribute is required. // In OAS >= 3.1, the array "items" attribute is optional such that the OAS @@ -1238,8 +1237,7 @@ public class PythonPriorClientCodegen extends PythonLegacyClientCodegen { } return fullPrefix + example + closeChars; } else if (ModelUtils.isArraySchema(schema)) { - ArraySchema arrayschema = (ArraySchema) schema; - Schema itemSchema = arrayschema.getItems(); + Schema itemSchema = ModelUtils.getArrayItems(schema); String itemModelName = getModelName(itemSchema); if (objExample instanceof Iterable && itemModelName == null) { // If the example is already a list, return it directly instead of wrongly wrap it in another list @@ -1388,8 +1386,7 @@ public class PythonPriorClientCodegen extends PythonLegacyClientCodegen { } else if (simpleStringSchema(schema)) { return propName + "_example"; } else if (ModelUtils.isArraySchema(schema)) { - ArraySchema arraySchema = (ArraySchema) schema; - Schema itemSchema = arraySchema.getItems(); + Schema itemSchema = ModelUtils.getArrayItems(schema); example = getObjectExample(itemSchema); if (example != null) { return example; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RClientCodegen.java index 24669ea6db1..909ec1ffa40 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RClientCodegen.java @@ -514,8 +514,7 @@ public class RClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java index 2aeefdbac00..f0816b1ae67 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java @@ -426,11 +426,10 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon public String getTypeDeclaration(Schema p) { Schema unaliasSchema = unaliasSchema(p); if (ModelUtils.isArraySchema(unaliasSchema)) { - ArraySchema ap = (ArraySchema) unaliasSchema; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(unaliasSchema); if (inner == null) { LOGGER.warn("{}(array property) does not have a proper inner type defined.Default to string", - ap.getName()); + p.getName()); inner = new StringSchema().description("TODO default missing array inner type to string"); } return "Vec<" + getTypeDeclaration(inner) + ">"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index 60e977633c8..80df5b06287 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -983,8 +983,7 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); String innerType = getTypeDeclaration(inner); return typeMapping.get("array") + "<" + innerType + ">"; } else if (ModelUtils.isMapSchema(p)) { @@ -1018,8 +1017,7 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon @Override public String toInstantiationType(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return instantiationTypes.get("array") + "<" + getSchemaType(inner) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java index 4dde3ea3b6f..95c6eac0f45 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaFinchServerCodegen.java @@ -261,8 +261,7 @@ public class ScalaFinchServerCodegen extends DefaultCodegen implements CodegenCo @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaGatlingCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaGatlingCodegen.java index 7098f0d591d..83094987303 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaGatlingCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaGatlingCodegen.java @@ -384,8 +384,7 @@ public class ScalaGatlingCodegen extends AbstractScalaCodegen implements Codegen @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java index fe503eb1ed0..602df34c3c7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java @@ -369,7 +369,7 @@ public class ScalaPlayFrameworkServerCodegen extends AbstractScalaCodegen implem } if (ModelUtils.isArraySchema(p)) { - Schema items = ((ArraySchema) p).getItems(); + Schema items = ModelUtils.getArrayItems(p); String inner = getSchemaType(items); if (ModelUtils.isSet(p)) { return "Set.empty[" + inner + "]"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java index b2210f39f51..178a38a68f9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtml2Generator.java @@ -133,8 +133,7 @@ public class StaticHtml2Generator extends DefaultCodegen implements CodegenConfi @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtmlGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtmlGenerator.java index 63457b57d7d..1a89b3e3ef5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtmlGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/StaticHtmlGenerator.java @@ -116,8 +116,7 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java index 5bd1dfb2db0..d4a75b90f34 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java @@ -685,8 +685,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(p); return ModelUtils.isSet(p) ? "Set<" + getTypeDeclaration(inner) + ">" : "[" + getTypeDeclaration(inner) + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = getAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java index b6c868f8968..894c64e06a8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java @@ -882,7 +882,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo public String getTypeDeclaration(Schema p) { Schema inner; if (ModelUtils.isArraySchema(p)) { - inner = ((ArraySchema) p).getItems(); + inner = ModelUtils.getArrayItems(p); return this.getSchemaType(p) + "<" + this.getTypeDeclaration(unaliasSchema(inner)) + ">"; } else if (ModelUtils.isMapSchema(p)) { inner = getSchemaAdditionalProperties(p); @@ -1183,8 +1183,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo } return fullPrefix + example + closeChars; } else if (ModelUtils.isArraySchema(schema)) { - ArraySchema arrayschema = (ArraySchema) schema; - Schema itemSchema = arrayschema.getItems(); + Schema itemSchema = ModelUtils.getArrayItems(schema); String itemModelName = getModelName(itemSchema); if (objExample instanceof Iterable && itemModelName == null) { // If the example is already a list, return it directly instead of wrongly wrap it in another list @@ -1315,8 +1314,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo } else if (simpleStringSchema(schema)) { return propName + "_example"; } else if (ModelUtils.isArraySchema(schema)) { - ArraySchema arraySchema = (ArraySchema) schema; - Schema itemSchema = arraySchema.getItems(); + Schema itemSchema = ModelUtils.getArrayItems(schema); example = getObjectExample(itemSchema); if (example != null) { return example; @@ -1520,8 +1518,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo return filteredSchemas.stream().map(schema -> { String schemaType = getSchemaType(schema); if (ModelUtils.isArraySchema(schema)) { - ArraySchema ap = (ArraySchema) schema; - Schema inner = ap.getItems(); + Schema inner = ModelUtils.getArrayItems(schema); schemaType = schemaType + "<" + getSchemaType(inner) + ">"; } return schemaType; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java index 953465863c3..a28e6e1693c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java @@ -333,7 +333,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen Schema additionalProperties = getAdditionalProperties(schema); codegenModel.additionalPropertiesType = getSchemaType(additionalProperties); if ("array".equalsIgnoreCase(codegenModel.additionalPropertiesType)) { - codegenModel.additionalPropertiesType += '<' + getSchemaType(((ArraySchema) additionalProperties).getItems()) + '>'; + codegenModel.additionalPropertiesType += '<' + getSchemaType(ModelUtils.getArrayItems(additionalProperties)) + '>'; } addImport(codegenModel, codegenModel.additionalPropertiesType); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index 11c08308542..cf0be634fad 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -349,8 +349,8 @@ public class ModelUtils { visitSchema(openAPI, s, mimeType, visitedSchemas, visitor); } } - } else if (schema instanceof ArraySchema) { - Schema itemsSchema = ((ArraySchema) schema).getItems(); + } else if (isArraySchema(schema)) { + Schema itemsSchema = getArrayItems(schema); if (itemsSchema != null) { visitSchema(openAPI, itemsSchema, mimeType, visitedSchemas, visitor); } @@ -567,14 +567,64 @@ public class ModelUtils { return false; } + /** + * Return true if the specified schema is a json schema. + * + * @param schema the OAS schema + * @return true if the specified schema is an Json schema. + */ + public static boolean isJsonSchema(Schema schema) { + return (schema instanceof JsonSchema); + } + + /** + * Return the type defined in a JsonSchema + * Since swagger-core 2.2.0, getTypes can be defined for OpenAPI 3.1.0 + * https://github.com/swagger-api/swagger-core/blob/v2.2.4/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java#L453-L460 + * https://github.com/swagger-api/swagger-parser/blob/v2.1.8/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java#L383-L390 + * Return the first element of types if schema is a JsonFormat and it only contains one type like it is currently done in swagger-parser since 2.1.8: + * https://github.com/swagger-api/swagger-parser/blob/v2.1.8/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java#L469-L477 + * + * @param schema the schema that we are checking + * @return String + */ + public static String getJsonSchemaOneTypeOnly(Schema schema) { + if (isJsonSchema(schema) && schema.getTypes() != null && schema.getTypes().size() == 1) { + return (String)schema.getTypes().iterator().next(); + } + return null; + } + /** * Return true if the specified schema is an array of items. + * It can be an instance of ArraySchema + * or with OpenAPI3.1, it can be a JsonSchema with a type "array" * * @param schema the OAS schema * @return true if the specified schema is an Array schema. */ public static boolean isArraySchema(Schema schema) { - return (schema instanceof ArraySchema); + if (schema instanceof ArraySchema) { + return true; + } + + return StringUtils.equals(getJsonSchemaOneTypeOnly(schema), "array"); + } + + /** + * Return items in the array schema + * + * @param schema the OAS schema + * @return Schema + */ + public static Schema getArrayItems(Schema schema) { + Schema itemsSchema = null; + if (schema instanceof ArraySchema) { + itemsSchema = ((ArraySchema) schema).getItems(); + } else if (isJsonSchema(schema)) { + itemsSchema = ((JsonSchema) schema).getItems(); + } + return itemsSchema; } public static boolean isSet(Schema schema) { @@ -1191,7 +1241,7 @@ public class ModelUtils { } } } else if (isArraySchema(schema)) { - Schema itemsSchema = ((ArraySchema) schema).getItems(); + Schema itemsSchema = getArrayItems(schema); if (itemsSchema != null) { return hasSelfReference(openAPI, itemsSchema, visitedSchemaNames); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index b571cf2173c..febbbe6f6e2 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -4380,4 +4380,18 @@ public class DefaultCodegenTest { assertNull(schema3.getAnyOf()); assertTrue(schema3 instanceof StringSchema); } + + @Test + public void testOpenAPI310ResponsesJsonSchemaIsArray() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/petstore.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + final String path = "/pet/findByStatus"; + + final Operation operation = openAPI.getPaths().get(path).getGet(); + final CodegenOperation co = codegen.fromOperation(path, "get", operation, null); + + Assert.assertTrue(co.responses.get(0).isArray); + } } -- GitLab From c1bc24215b8f00e2b3268e1595cc6148eb69f9d3 Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Mon, 6 Feb 2023 11:49:16 +0100 Subject: [PATCH 2/9] Move getSchemaType in ModelUtils --- .../openapitools/codegen/DefaultCodegen.java | 28 +++++-------------- .../languages/AbstractDartCodegen.java | 2 +- .../languages/AbstractJavaCodegen.java | 2 +- .../languages/AbstractKotlinCodegen.java | 4 +-- .../languages/AbstractScalaCodegen.java | 2 +- .../AbstractTypeScriptClientCodegen.java | 2 +- .../codegen/utils/ModelUtils.java | 17 ++++++----- 7 files changed, 23 insertions(+), 34 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 69fdb3b1203..90c290e3dae 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1929,7 +1929,7 @@ public class DefaultCodegen implements CodegenConfig { String inner = getSchemaType(additionalProperties); return instantiationTypes.get("map") + "<String, " + inner + ">"; } else if (ModelUtils.isArraySchema(schema)) { - String inner = getSchemaType(getSchemaItems(schema)); + String inner = getSchemaType(ModelUtils.getArrayItems(schema)); String parentType; if (ModelUtils.isSet(schema)) { parentType = "set"; @@ -2236,20 +2236,6 @@ public class DefaultCodegen implements CodegenConfig { } - protected Schema<?> getSchemaItems(Schema schema) { - if (!ModelUtils.isArraySchema(schema)) { - LOGGER.error("Schema `{}` is not an array.", schema.getName()); - return null; - } - Schema<?> items = schema.getItems(); - if (items == null) { - LOGGER.error("Undefined array inner type for `{}`. Default to String.", schema.getName()); - items = new StringSchema().description("TODO default missing array inner type to string"); - schema.setItems(items); - } - return items; - } - protected Schema<?> getSchemaAdditionalProperties(Schema schema) { Schema<?> inner = getAdditionalProperties(schema); if (inner == null) { @@ -3927,7 +3913,7 @@ public class DefaultCodegen implements CodegenConfig { // handle inner property String itemName = getItemsName(p, name); - Schema innerSchema = unaliasSchema(getSchemaItems(p)); + Schema innerSchema = unaliasSchema(ModelUtils.getArrayItems(p)); CodegenProperty cp = fromProperty(itemName, innerSchema, false); updatePropertyForArray(property, cp); } else if (ModelUtils.isTypeObjectSchema(p)) { @@ -4187,7 +4173,7 @@ public class DefaultCodegen implements CodegenConfig { CodegenProperty cm = fromProperty("response", responseSchema, false); if (ModelUtils.isArraySchema(responseSchema)) { - CodegenProperty innerProperty = fromProperty("response", getSchemaItems(responseSchema), false); + CodegenProperty innerProperty = fromProperty("response", ModelUtils.getArrayItems(responseSchema), false); op.returnBaseType = innerProperty.baseType; } else if (ModelUtils.isMapSchema(responseSchema)) { CodegenProperty innerProperty = fromProperty("response", getAdditionalProperties(responseSchema), false); @@ -4681,7 +4667,7 @@ public class DefaultCodegen implements CodegenConfig { r.simpleType = false; r.isArray = true; r.containerType = cp.containerType; - CodegenProperty items = fromProperty("response", getSchemaItems(responseSchema), false); + CodegenProperty items = fromProperty("response", ModelUtils.getArrayItems(responseSchema), false); r.setItems(items); CodegenProperty innerCp = items; @@ -5054,7 +5040,7 @@ public class DefaultCodegen implements CodegenConfig { } addVarsRequiredVarsAdditionalProps(parameterSchema, codegenParameter); } else if (ModelUtils.isArraySchema(parameterSchema)) { - Schema inner = getSchemaItems(parameterSchema); + Schema inner = ModelUtils.getArrayItems(parameterSchema); collectionFormat = getCollectionFormat(parameter); // default to csv: @@ -6822,7 +6808,7 @@ public class DefaultCodegen implements CodegenConfig { // any schema with no type set, composed schemas often do this ; } else if (ModelUtils.isArraySchema(ps)) { - Schema inner = getSchemaItems(ps); + Schema inner = ModelUtils.getArrayItems(ps); CodegenProperty arrayInnerProperty = fromProperty("inner", inner, false); codegenParameter.items = arrayInnerProperty; codegenParameter.mostInnerItems = arrayInnerProperty.mostInnerItems; @@ -7091,7 +7077,7 @@ public class DefaultCodegen implements CodegenConfig { if (ModelUtils.isGenerateAliasAsModel(schema) && StringUtils.isNotBlank(name)) { this.addBodyModelSchema(codegenParameter, name, schema, imports, bodyParameterName, true); } else { - Schema inner = getSchemaItems(schema); + Schema inner = ModelUtils.getArrayItems(schema); CodegenProperty codegenProperty = fromProperty("property", schema, false); if (codegenProperty == null) { throw new RuntimeException("CodegenProperty cannot be null. schema for debugging: " + schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java index 985aa9725f1..63c55a7d3c5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java @@ -493,7 +493,7 @@ public abstract class AbstractDartCodegen extends DefaultCodegen { Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems(schema); + Schema<?> items = ModelUtils.getArrayItems(schema); return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">"; } if (ModelUtils.isMapSchema(target)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index a03c57bb75f..9b111935298 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -949,7 +949,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems(schema); + Schema<?> items = ModelUtils.getArrayItems(schema); return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">"; } else if (ModelUtils.isMapSchema(target)) { // Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index 1f3707dffc0..ea78a33ae50 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -381,7 +381,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems(schema); + Schema<?> items = ModelUtils.getArrayItems(schema); return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">"; } else if (ModelUtils.isMapSchema(target)) { // Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines @@ -1094,7 +1094,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co } StringBuilder defaultContent = new StringBuilder(); - Schema<?> itemsSchema = getSchemaItems(schema); + Schema<?> itemsSchema = ModelUtils.getArrayItems(schema); _default.elements().forEachRemaining((element) -> { itemsSchema.setDefault(element.asText()); defaultContent.append(toDefaultValue(itemsSchema)).append(","); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java index 1d5fe33898d..21dbe9fb2f5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java @@ -366,7 +366,7 @@ public abstract class AbstractScalaCodegen extends DefaultCodegen { Schema<?> schema = unaliasSchema(p); Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { - Schema<?> items = getSchemaItems(schema); + Schema<?> items = ModelUtils.getArrayItems(schema); return getSchemaType(target) + "[" + getTypeDeclaration(items) + "]"; } else if (ModelUtils.isMapSchema(target)) { Schema<?> inner = getAdditionalProperties(target); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java index 44f91dcc9a4..8a043b5cb58 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java @@ -601,7 +601,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { - Schema<?> items = getSchemaItems(p); + Schema<?> items = ModelUtils.getArrayItems(p); return getSchemaType(p) + "<" + getTypeDeclaration(unaliasSchema(items)) + ">"; } else if (ModelUtils.isMapSchema(p)) { Schema<?> inner = getSchemaAdditionalProperties(p); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index cf0be634fad..2e8de750161 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -617,14 +617,17 @@ public class ModelUtils { * @param schema the OAS schema * @return Schema */ - public static Schema getArrayItems(Schema schema) { - Schema itemsSchema = null; - if (schema instanceof ArraySchema) { - itemsSchema = ((ArraySchema) schema).getItems(); - } else if (isJsonSchema(schema)) { - itemsSchema = ((JsonSchema) schema).getItems(); + public static Schema<?> getArrayItems(Schema schema) { + if (!ModelUtils.isArraySchema(schema)) { + LOGGER.error("Schema `{}` is not an array.", schema.getName()); + } + Schema<?> items = schema.getItems(); + if (items == null) { + LOGGER.error("Undefined array inner type for `{}`. Default to String.", schema.getName()); + items = new StringSchema().description("TODO default missing array inner type to string"); + schema.setItems(items); } - return itemsSchema; + return items; } public static boolean isSet(Schema schema) { -- GitLab From b43b9223ac03d4192a3f6ab5d6b03d8db792a644 Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Tue, 7 Feb 2023 14:53:50 +0100 Subject: [PATCH 3/9] Generalize validation of the type contained in JsonSchema. Without this generalization to the check isXyz() in ModelUtils, an array of string was parsed as a List[object] with a null dataType. --- .../openapitools/codegen/DefaultCodegen.java | 4 +- .../codegen/utils/ModelUtils.java | 50 ++++++++++--------- .../codegen/DefaultCodegenTest.java | 21 +++++++- .../src/test/resources/3_1/petstore.yaml | 5 +- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 90c290e3dae..7eea3d3719e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -2413,6 +2413,8 @@ public class DefaultCodegen implements CodegenConfig { // 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 (ModelUtils.isJsonSchema(schema) && ModelUtils.getJsonSchemaOneTypeOnly(schema) != null) { + return ModelUtils.getJsonSchemaOneTypeOnly(schema); } else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { // having property implies it's a model return "object"; } else if (ModelUtils.isAnyType(schema)) { @@ -7804,7 +7806,7 @@ public class DefaultCodegen implements CodegenConfig { return false; } - if (schema.getClass().equals(Schema.class) && schema.get$ref() == null && schema.getType() == null && + if (schema.getClass().equals(Schema.class) && schema.get$ref() == null && schema.getType() == null && schema.getTypes() == null && (schema.getProperties() == null || schema.getProperties().isEmpty()) && schema.getAdditionalProperties() == null && schema.getNot() == null && schema.getEnum() == null) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index 2e8de750161..04f586096aa 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -420,7 +420,7 @@ public class ModelUtils { if (SchemaTypeUtil.OBJECT_TYPE.equals(schema.getType())) { return true; } - return false; + return SchemaTypeUtil.OBJECT_TYPE.equals(getJsonSchemaOneTypeOnly(schema)); } /** @@ -455,6 +455,10 @@ public class ModelUtils { return true; } + if (SchemaTypeUtil.OBJECT_TYPE.equals(getJsonSchemaOneTypeOnly(schema))) { + return true; + } + // must have at least one property if (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()) { return true; @@ -608,7 +612,7 @@ public class ModelUtils { return true; } - return StringUtils.equals(getJsonSchemaOneTypeOnly(schema), "array"); + return "array".equals(getJsonSchemaOneTypeOnly(schema)); } /** @@ -638,7 +642,7 @@ public class ModelUtils { if (schema instanceof StringSchema || SchemaTypeUtil.STRING_TYPE.equals(schema.getType())) { return true; } - return false; + return SchemaTypeUtil.STRING_TYPE.equals(getJsonSchemaOneTypeOnly(schema)); } public static boolean isIntegerSchema(Schema schema) { @@ -648,11 +652,11 @@ public class ModelUtils { if (SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType())) { return true; } - return false; + return SchemaTypeUtil.INTEGER_TYPE.equals(getJsonSchemaOneTypeOnly(schema)); } public static boolean isShortSchema(Schema schema) { - if (SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType()) // type: integer + if (isIntegerSchema(schema) // type: integer && SchemaTypeUtil.INTEGER32_FORMAT.equals(schema.getFormat())) { // format: short (int32) return true; } @@ -660,7 +664,7 @@ public class ModelUtils { } public static boolean isLongSchema(Schema schema) { - if (SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType()) // type: integer + if (isIntegerSchema(schema) // type: integer && SchemaTypeUtil.INTEGER64_FORMAT.equals(schema.getFormat())) { // format: long (int64) return true; } @@ -674,7 +678,7 @@ public class ModelUtils { if (SchemaTypeUtil.BOOLEAN_TYPE.equals(schema.getType())) { return true; } - return false; + return SchemaTypeUtil.BOOLEAN_TYPE.equals(getJsonSchemaOneTypeOnly(schema)); } public static boolean isNumberSchema(Schema schema) { @@ -684,11 +688,11 @@ public class ModelUtils { if (SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType())) { return true; } - return false; + return SchemaTypeUtil.NUMBER_TYPE.equals(getJsonSchemaOneTypeOnly(schema)); } public static boolean isFloatSchema(Schema schema) { - if (SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType()) + if (isNumberSchema(schema) && SchemaTypeUtil.FLOAT_FORMAT.equals(schema.getFormat())) { // format: float return true; } @@ -696,7 +700,7 @@ public class ModelUtils { } public static boolean isDoubleSchema(Schema schema) { - if (SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType()) + if (isNumberSchema(schema) && SchemaTypeUtil.DOUBLE_FORMAT.equals(schema.getFormat())) { // format: double return true; } @@ -708,7 +712,7 @@ public class ModelUtils { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && SchemaTypeUtil.DATE_FORMAT.equals(schema.getFormat())) { // format: date return true; } @@ -719,7 +723,7 @@ public class ModelUtils { if (schema instanceof DateTimeSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && SchemaTypeUtil.DATE_TIME_FORMAT.equals(schema.getFormat())) { // format: date-time return true; } @@ -730,7 +734,7 @@ public class ModelUtils { if (schema instanceof PasswordSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && SchemaTypeUtil.PASSWORD_FORMAT.equals(schema.getFormat())) { // double return true; } @@ -741,7 +745,7 @@ public class ModelUtils { if (schema instanceof ByteArraySchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && SchemaTypeUtil.BYTE_FORMAT.equals(schema.getFormat())) { // format: byte return true; } @@ -752,7 +756,7 @@ public class ModelUtils { if (schema instanceof BinarySchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && SchemaTypeUtil.BINARY_FORMAT.equals(schema.getFormat())) { // format: binary return true; } @@ -771,7 +775,7 @@ public class ModelUtils { if (schema instanceof UUIDSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && SchemaTypeUtil.UUID_FORMAT.equals(schema.getFormat())) { // format: uuid return true; } @@ -779,7 +783,7 @@ public class ModelUtils { } public static boolean isURISchema(Schema schema) { - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && URI_FORMAT.equals(schema.getFormat())) { // format: uri return true; } @@ -790,7 +794,7 @@ public class ModelUtils { if (schema instanceof EmailSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + if (isStringSchema(schema) && SchemaTypeUtil.EMAIL_FORMAT.equals(schema.getFormat())) { // format: email return true; } @@ -798,7 +802,7 @@ public class ModelUtils { } public static boolean isDecimalSchema(Schema schema) { - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) // type: string + if (isStringSchema(schema) // type: string && "number".equals(schema.getFormat())) { // format: number return true; } @@ -910,7 +914,7 @@ public class ModelUtils { } // has at least one property - if ("object".equals(schema.getType())) { + if ("object".equals(schema.getType()) || "object".equals(getJsonSchemaOneTypeOnly(schema))) { // no properties if ((schema.getProperties() == null || schema.getProperties().isEmpty())) { Schema addlProps = getAdditionalProperties(openAPI, schema); @@ -936,7 +940,7 @@ public class ModelUtils { } } else if (addlProps instanceof Schema) { // additionalProperties defined as {} - if (addlProps.getType() == null && addlProps.get$ref() == null && (addlProps.getProperties() == null || addlProps.getProperties().isEmpty())) { + if (addlProps.getType() == null && addlProps.getTypes() == null && addlProps.get$ref() == null && (addlProps.getProperties() == null || addlProps.getProperties().isEmpty())) { return true; } } @@ -1726,7 +1730,7 @@ public class ModelUtils { * @return true if the schema is the 'null' type */ public static boolean isNullType(Schema schema) { - if ("null".equals(schema.getType())) { + if ("null".equals(schema.getType()) || "null".equals(getJsonSchemaOneTypeOnly(schema))) { return true; } return false; @@ -1745,7 +1749,7 @@ public class ModelUtils { // TODO remove the ref check here, or pass in the spec version // openapi 3.1.0 specs allow ref to be adjacent to any keyword // openapi 3.0.3 and earlier do not allow adjacent keywords to refs - return (schema.get$ref() == null && schema.getType() == null); + return (schema.get$ref() == null && schema.getType() == null && schema.getTypes() == null); } public static void syncValidationProperties(Schema schema, IJsonSchemaValidationProperties target) { diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index febbbe6f6e2..e364bf1dd78 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -4382,7 +4382,7 @@ public class DefaultCodegenTest { } @Test - public void testOpenAPI310ResponsesJsonSchemaIsArray() { + public void testOpenAPI310JsonSchemaIsArrayRef() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/petstore.yaml"); final DefaultCodegen codegen = new DefaultCodegen(); codegen.setOpenAPI(openAPI); @@ -4393,5 +4393,24 @@ public class DefaultCodegenTest { final CodegenOperation co = codegen.fromOperation(path, "get", operation, null); Assert.assertTrue(co.responses.get(0).isArray); + Assert.assertEquals(co.responses.get(0).dataType, "List"); + Assert.assertEquals(co.responses.get(0).baseType, "Pet"); + } + + @Test + public void testOpenAPI310JsonSchemaArrayString() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/petstore.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + final String path = "/pet/findByTags"; + + final Operation operation = openAPI.getPaths().get(path).getGet(); + final CodegenOperation co = codegen.fromOperation(path, "get", operation, null); + + Assert.assertTrue(co.queryParams.get(0).isArray); + Assert.assertEquals(co.queryParams.get(0).dataType, "List"); + Assert.assertEquals(co.queryParams.get(0).baseType, "String"); + Assert.assertTrue(co.queryParams.get(0).items.isString); } } diff --git a/modules/openapi-generator/src/test/resources/3_1/petstore.yaml b/modules/openapi-generator/src/test/resources/3_1/petstore.yaml index 6c6de61d69b..c801448cb52 100644 --- a/modules/openapi-generator/src/test/resources/3_1/petstore.yaml +++ b/modules/openapi-generator/src/test/resources/3_1/petstore.yaml @@ -49,6 +49,9 @@ paths: summary: Update an existing pet description: '' operationId: updatePet + externalDocs: + url: "http://petstore.swagger.io/v2/doc/updatePet" + description: "API documentation for the updatePet operation" responses: '200': description: successful operation @@ -124,7 +127,7 @@ paths: tag2, tag3 for testing. operationId: findPetsByTags parameters: - - name: tags + - name: tagssss in: query description: Tags to filter by required: true -- GitLab From 03cc1bbbf672d8cfb65924fcdae41a12418dfb8b Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Tue, 7 Feb 2023 16:27:25 +0100 Subject: [PATCH 4/9] Fix issue with integer which was parsed as null because getType() was used --- .../openapitools/codegen/DefaultCodegen.java | 19 +++++++++------ .../codegen/DefaultCodegenTest.java | 17 +++++++++++++ .../test/resources/3_1/parameter-integer.yaml | 24 +++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 7eea3d3719e..de89d7fd34e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -2346,12 +2346,17 @@ public class DefaultCodegen implements CodegenConfig { * @return type */ private String getPrimitiveType(Schema schema) { + String type = schema.getType(); + if (type == null) { + type = ModelUtils.getJsonSchemaOneTypeOnly(schema); + } + if (schema == null) { throw new RuntimeException("schema cannot be null in getPrimitiveType"); - } else if (typeMapping.containsKey(schema.getType() + "+" + schema.getFormat())) { + } else if (typeMapping.containsKey(type + "+" + schema.getFormat())) { // allows custom type_format mapping. // use {type}+{format} - return typeMapping.get(schema.getType() + "+" + schema.getFormat()); + return typeMapping.get(type + "+" + schema.getFormat()); } else if (ModelUtils.isNullType(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. @@ -2386,7 +2391,7 @@ public class DefaultCodegen implements CodegenConfig { if (ModelUtils.isLongSchema(schema)) { return "long"; } else { - return schema.getType(); // integer + return type; // integer } } else if (ModelUtils.isMapSchema(schema)) { return "map"; @@ -2419,11 +2424,11 @@ public class DefaultCodegen implements CodegenConfig { return "object"; } else if (ModelUtils.isAnyType(schema)) { return "AnyType"; - } else if (StringUtils.isNotEmpty(schema.getType())) { - if (!schemaMapping.containsKey(schema.getType())) { - LOGGER.warn("Unknown type found in the schema: {}. To map it, please use the schema mapping option (e.g. --schema-mappings in CLI)", schema.getType()); + } else if (StringUtils.isNotEmpty(type)) { + if (!schemaMapping.containsKey(type)) { + LOGGER.warn("Unknown type found in the schema: {}. To map it, please use the schema mapping option (e.g. --schema-mappings in CLI)", type); } - return schema.getType(); + return type; } // The 'type' attribute has not been set in the OAS schema, which means the value // can be an arbitrary type, e.g. integer, string, object, array, number... diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index e364bf1dd78..c5dd74fd4c4 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -4413,4 +4413,21 @@ public class DefaultCodegenTest { Assert.assertEquals(co.queryParams.get(0).baseType, "String"); Assert.assertTrue(co.queryParams.get(0).items.isString); } + + @Test + public void testOpenAPI310JsonSchemaInteger() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/parameter-integer.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + final String path = "/elements"; + + final Operation operation = openAPI.getPaths().get(path).getGet(); + final CodegenOperation co = codegen.fromOperation(path, "get", operation, null); + + Assert.assertTrue(co.queryParams.get(0).isInteger); + Assert.assertTrue(co.queryParams.get(0).isUnboundedInteger); + Assert.assertEquals(co.queryParams.get(0).dataType, "Integer"); + Assert.assertEquals(co.queryParams.get(0).baseType, null); + } } diff --git a/modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml b/modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml new file mode 100644 index 00000000000..5b0b964923a --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml @@ -0,0 +1,24 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + description: Specification with integer parameters + title: Specification with integer parameters +paths: + /elements: + get: + parameters: + - in: query + name: limit + schema: + type: integer + - in: query + name: offset + schema: + type: integer + responses: + '200': + description: OK + content: + application/json: + schema: + type: boolean -- GitLab From b8871c892f2813eb56c0fc603ef2b6ae0057ed5b Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Tue, 7 Feb 2023 16:32:30 +0100 Subject: [PATCH 5/9] Revert change in modules/openapi-generator/src/test/resources/3_1/petstore.yaml --- .../openapi-generator/src/test/resources/3_1/petstore.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/test/resources/3_1/petstore.yaml b/modules/openapi-generator/src/test/resources/3_1/petstore.yaml index c801448cb52..6c6de61d69b 100644 --- a/modules/openapi-generator/src/test/resources/3_1/petstore.yaml +++ b/modules/openapi-generator/src/test/resources/3_1/petstore.yaml @@ -49,9 +49,6 @@ paths: summary: Update an existing pet description: '' operationId: updatePet - externalDocs: - url: "http://petstore.swagger.io/v2/doc/updatePet" - description: "API documentation for the updatePet operation" responses: '200': description: successful operation @@ -127,7 +124,7 @@ paths: tag2, tag3 for testing. operationId: findPetsByTags parameters: - - name: tagssss + - name: tags in: query description: Tags to filter by required: true -- GitLab From 70e2fa112c5cbd5b2adde3aa8b483157eba8d520 Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Tue, 7 Feb 2023 17:45:10 +0100 Subject: [PATCH 6/9] Instead of checking integer only, test for all primitive types --- .../codegen/DefaultCodegenTest.java | 128 +++++++++++++++++- .../test/resources/3_1/parameter-integer.yaml | 24 ---- .../3_1/parameter-primitive-types.yaml | 92 +++++++++++++ 3 files changed, 213 insertions(+), 31 deletions(-) delete mode 100644 modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index c5dd74fd4c4..55ca44656b9 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -4414,9 +4414,18 @@ public class DefaultCodegenTest { Assert.assertTrue(co.queryParams.get(0).items.isString); } + public CodegenParameter getQueryParamsByName(List<CodegenParameter> queryParams, String baseName) { + for (CodegenParameter param : queryParams) { + if (param.baseName.equals(baseName)) { + return param; + } + } + return null; + } + @Test - public void testOpenAPI310JsonSchemaInteger() { - final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/parameter-integer.yaml"); + public void testOpenAPI310JsonSchemaPrimitivesTypes() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/parameter-primitive-types.yaml"); final DefaultCodegen codegen = new DefaultCodegen(); codegen.setOpenAPI(openAPI); @@ -4424,10 +4433,115 @@ public class DefaultCodegenTest { final Operation operation = openAPI.getPaths().get(path).getGet(); final CodegenOperation co = codegen.fromOperation(path, "get", operation, null); - - Assert.assertTrue(co.queryParams.get(0).isInteger); - Assert.assertTrue(co.queryParams.get(0).isUnboundedInteger); - Assert.assertEquals(co.queryParams.get(0).dataType, "Integer"); - Assert.assertEquals(co.queryParams.get(0).baseType, null); + String name = ""; + + name = "boolean"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isBoolean); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "Boolean"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, null); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "integer"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isInteger); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isUnboundedInteger); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "Integer"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, null); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "integerint32"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isInteger); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isShort); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "Integer"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "int32"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "integerint64"; + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isInteger); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isLong); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "Long"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "int64"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "number"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isNumber); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "BigDecimal"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, null); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "numberfloat"; + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isNumber); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isFloat); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "Float"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "float"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "numberdouble"; + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isNumber); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isDouble); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "Double"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "double"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "string"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "String"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, null); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringdate"; + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isDate); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "date"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "date"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringdate-time"; + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isDateTime); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "Date"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "date-time"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringpassword"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "String"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "password"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringbyte"; + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isByteArray); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "byte[]"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "byte"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringbinary"; + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isFile); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isBinary); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "File"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "binary"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringuuid"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isUuid); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "UUID"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "uuid"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringuri"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isString); + // Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isUri); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "URI"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "uri"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringnumber"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isDecimal); + Assert.assertFalse(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "BigDecimal"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "number"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); } } diff --git a/modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml b/modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml deleted file mode 100644 index 5b0b964923a..00000000000 --- a/modules/openapi-generator/src/test/resources/3_1/parameter-integer.yaml +++ /dev/null @@ -1,24 +0,0 @@ -openapi: 3.1.0 -info: - version: 1.0.0 - description: Specification with integer parameters - title: Specification with integer parameters -paths: - /elements: - get: - parameters: - - in: query - name: limit - schema: - type: integer - - in: query - name: offset - schema: - type: integer - responses: - '200': - description: OK - content: - application/json: - schema: - type: boolean diff --git a/modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml b/modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml new file mode 100644 index 00000000000..b9995d0d20f --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml @@ -0,0 +1,92 @@ +openapi: 3.1.0 +info: + version: 1.0.0 + description: Specification with integer parameters + title: Specification with integer parameters +paths: + /elements: + get: + parameters: + - in: query + name: boolean + schema: + type: boolean + - in: query + name: integer + schema: + type: integer + - in: query + name: integerint32 + schema: + type: integer + format: int32 + - in: query + name: integerint64 + schema: + type: integer + format: int64 + - in: query + name: number + schema: + type: number + - in: query + name: numberfloat + schema: + type: number + format: float + - in: query + name: numberdouble + schema: + type: number + format: double + - in: query + name: string + schema: + type: string + - in: query + name: stringdate + schema: + type: string + format: date + - in: query + name: stringdate-time + schema: + type: string + format: date-time + - in: query + name: stringpassword + schema: + type: string + format: password + - in: query + name: stringbyte + schema: + type: string + format: byte + - in: query + name: stringbinary + schema: + type: string + format: binary + - in: query + name: stringuuid + schema: + type: string + format: uuid + - in: query + name: stringuri + schema: + type: string + format: uri + - in: query + name: stringnumber + schema: + type: string + format: number + responses: + '200': + description: OK + content: + application/json: + schema: + type: boolean -- GitLab From 00f93e8af9ccb980715b2740f8c932f8552a5469 Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Wed, 8 Feb 2023 00:26:08 +0100 Subject: [PATCH 7/9] Add test for enum --- .../org/openapitools/codegen/DefaultCodegenTest.java | 10 ++++++++++ .../test/resources/3_1/parameter-primitive-types.yaml | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 55ca44656b9..71e7f4abbce 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -4543,5 +4543,15 @@ public class DefaultCodegenTest { Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "BigDecimal"); Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, "number"); Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); + + name = "stringenum"; + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isEnum); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name).isString); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name)._enum.contains("enum1")); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name)._enum.contains("enum2")); + Assert.assertTrue(getQueryParamsByName(co.queryParams, name)._enum.contains("enum3")); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataType, "String"); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, null); + Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); } } diff --git a/modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml b/modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml index b9995d0d20f..c9aa1a954ae 100644 --- a/modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml +++ b/modules/openapi-generator/src/test/resources/3_1/parameter-primitive-types.yaml @@ -83,6 +83,11 @@ paths: schema: type: string format: number + - in: query + name: stringenum + schema: + type: string + enum: [enum1, enum2, enum3] responses: '200': description: OK -- GitLab From 3b635d51842f67364fcc296500ace89436d4aac4 Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Wed, 8 Feb 2023 18:04:01 +0100 Subject: [PATCH 8/9] Support ComposedSchema and MapSchema as JsonSchema for OpenAPI 3.1 --- .../openapitools/codegen/DefaultCodegen.java | 94 ++++--- .../codegen/InlineModelResolver.java | 53 ++-- .../codegen/OpenAPINormalizer.java | 4 +- .../languages/AbstractDartCodegen.java | 2 +- .../languages/AbstractJavaCodegen.java | 6 +- .../languages/AbstractKotlinCodegen.java | 2 +- .../AbstractTypeScriptClientCodegen.java | 6 +- .../languages/CSharpNetCoreClientCodegen.java | 2 +- .../CSharpNetCoreReducedClientCodegen.java | 2 +- .../codegen/languages/GoServerCodegen.java | 2 +- .../languages/JavaCXFServerCodegen.java | 2 +- .../JavascriptApolloClientCodegen.java | 2 +- .../languages/JavascriptClientCodegen.java | 2 +- .../codegen/languages/OCamlClientCodegen.java | 2 +- .../languages/PythonClientCodegen.java | 10 +- .../languages/PythonPriorClientCodegen.java | 4 +- .../codegen/languages/RustServerCodegen.java | 4 +- .../TypeScriptAxiosClientCodegen.java | 2 +- .../languages/TypeScriptClientCodegen.java | 8 +- .../TypeScriptRxjsClientCodegen.java | 2 +- .../codegen/utils/ModelUtils.java | 76 +++--- .../oas/OpenApiSchemaValidations.java | 4 +- .../codegen/DefaultCodegenTest.java | 245 ++++++++++++++++++ .../resources/3_0/oas31-composed-schemas.yaml | 202 +++++++++++++++ .../test/resources/3_0/oas31-map-schemas.yaml | 70 +++++ .../resources/3_1/oas31-composed-schemas.yaml | 175 +++++++++++++ .../test/resources/3_1/oas31-map-schemas.yaml | 70 +++++ 27 files changed, 924 insertions(+), 129 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/oas31-composed-schemas.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/oas31-map-schemas.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_1/oas31-composed-schemas.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_1/oas31-map-schemas.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index de89d7fd34e..571f2614632 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1000,23 +1000,23 @@ public class DefaultCodegen implements CodegenConfig { if (ModelUtils.isComposedSchema(s)) { if (e.getKey().contains("/")) { // if this is property schema, we also need to generate the oneOf interface model - addOneOfNameExtension((ComposedSchema) s, nOneOf); - addOneOfInterfaceModel((ComposedSchema) s, nOneOf, openAPI); + addOneOfNameExtension(s, nOneOf); + addOneOfInterfaceModel(s, nOneOf, openAPI); } else { // else this is a component schema, so we will just use that as the oneOf interface model - addOneOfNameExtension((ComposedSchema) s, n); + addOneOfNameExtension(s, n); } } else if (ModelUtils.isArraySchema(s)) { Schema items = ModelUtils.getArrayItems(s); if (ModelUtils.isComposedSchema(items)) { - addOneOfNameExtension((ComposedSchema) items, nOneOf); - addOneOfInterfaceModel((ComposedSchema) items, nOneOf, openAPI); + addOneOfNameExtension(items, nOneOf); + addOneOfInterfaceModel(items, nOneOf, openAPI); } } else if (ModelUtils.isMapSchema(s)) { Schema addProps = getAdditionalProperties(s); if (addProps != null && ModelUtils.isComposedSchema(addProps)) { - addOneOfNameExtension((ComposedSchema) addProps, nOneOf); - addOneOfInterfaceModel((ComposedSchema) addProps, nOneOf, openAPI); + addOneOfNameExtension(addProps, nOneOf); + addOneOfInterfaceModel(addProps, nOneOf, openAPI); } } } @@ -2210,8 +2210,8 @@ public class DefaultCodegen implements CodegenConfig { **/ @SuppressWarnings("static-method") public String getSchemaType(Schema schema) { - if (schema instanceof ComposedSchema) { // composed schema - ComposedSchema cs = (ComposedSchema) schema; + if (ModelUtils.isComposedSchema(schema)) { // composed schema + Schema<?> cs = schema; // Get the interfaces, i.e. the set of elements under 'allOf', 'anyOf' or 'oneOf'. List<Schema> schemas = ModelUtils.getInterfaces(cs); @@ -2254,7 +2254,10 @@ public class DefaultCodegen implements CodegenConfig { * @return name of the allOf schema */ @SuppressWarnings("static-method") - public String toAllOfName(List<String> names, ComposedSchema composedSchema) { + public String toAllOfName(List<String> names, Schema<?> composedSchema) { + if (!ModelUtils.isComposedSchema(composedSchema)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", composedSchema.getName()); + } Map<String, Object> exts = composedSchema.getExtensions(); if (exts != null && exts.containsKey("x-all-of-name")) { return (String) exts.get("x-all-of-name"); @@ -2278,7 +2281,10 @@ public class DefaultCodegen implements CodegenConfig { * @return name of the anyOf schema */ @SuppressWarnings("static-method") - public String toAnyOfName(List<String> names, ComposedSchema composedSchema) { + public String toAnyOfName(List<String> names, Schema<?> composedSchema) { + if (!ModelUtils.isComposedSchema(composedSchema)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", composedSchema.getName()); + } return "anyOf<" + String.join(",", names) + ">"; } @@ -2296,7 +2302,10 @@ public class DefaultCodegen implements CodegenConfig { * @return name of the oneOf schema */ @SuppressWarnings("static-method") - public String toOneOfName(List<String> names, ComposedSchema composedSchema) { + public String toOneOfName(List<String> names, Schema<?> composedSchema) { + if (!ModelUtils.isComposedSchema(composedSchema)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", composedSchema.getName()); + } Map<String, Object> exts = composedSchema.getExtensions(); if (exts != null && exts.containsKey("x-one-of-name")) { return (String) exts.get("x-one-of-name"); @@ -2418,8 +2427,6 @@ public class DefaultCodegen implements CodegenConfig { // 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 (ModelUtils.isJsonSchema(schema) && ModelUtils.getJsonSchemaOneTypeOnly(schema) != null) { - return ModelUtils.getJsonSchemaOneTypeOnly(schema); } else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { // having property implies it's a model return "object"; } else if (ModelUtils.isAnyType(schema)) { @@ -2597,7 +2604,10 @@ public class DefaultCodegen implements CodegenConfig { Map<NamedSchema, CodegenProperty> schemaCodegenPropertyCache = new HashMap<>(); protected void updateModelForComposedSchema(CodegenModel m, Schema schema, Map<String, Schema> allDefinitions) { - final ComposedSchema composed = (ComposedSchema) schema; + if (!ModelUtils.isComposedSchema(schema)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", schema.getName()); + } + final Schema<?> composed = schema; Map<String, Schema> properties = new LinkedHashMap<>(); List<String> required = new ArrayList<>(); Map<String, Schema> allProperties = new LinkedHashMap<>(); @@ -2788,7 +2798,7 @@ public class DefaultCodegen implements CodegenConfig { } protected void updateModelForObject(CodegenModel m, Schema schema) { - if (schema.getProperties() != null || schema.getRequired() != null && !(schema instanceof ComposedSchema)) { + if (schema.getProperties() != null || schema.getRequired() != null && !(ModelUtils.isComposedSchema(schema))) { // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); } @@ -2817,7 +2827,7 @@ public class DefaultCodegen implements CodegenConfig { addAdditionPropertiesToCodeGenModel(m, schema); m.isMap = true; } - if (schema.getProperties() != null || schema.getRequired() != null && !(schema instanceof ComposedSchema)) { + if (schema.getProperties() != null || schema.getRequired() != null && !(ModelUtils.isComposedSchema(schema))) { // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); } @@ -3026,7 +3036,7 @@ public class DefaultCodegen implements CodegenConfig { m.setRef(schema.get$ref()); } - if (schema instanceof ComposedSchema) { + if (ModelUtils.isComposedSchema(schema)) { updateModelForComposedSchema(m, schema, allDefinitions); } @@ -3153,7 +3163,7 @@ public class DefaultCodegen implements CodegenConfig { return cp; } if (ModelUtils.isComposedSchema(refSchema)) { - ComposedSchema composedSchema = (ComposedSchema) refSchema; + Schema<?> composedSchema = refSchema; if (composedSchema.getAllOf() != null) { // If our discriminator is in one of the allOf schemas break when we find it for (Schema allOf : composedSchema.getAllOf()) { @@ -3233,7 +3243,7 @@ public class DefaultCodegen implements CodegenConfig { } Discriminator disc = new Discriminator(); if (ModelUtils.isComposedSchema(refSchema)) { - ComposedSchema composedSchema = (ComposedSchema) refSchema; + Schema<?> composedSchema = refSchema; if (composedSchema.getAllOf() != null) { // If our discriminator is in one of the allOf schemas break when we find it for (Schema allOf : composedSchema.getAllOf()) { @@ -3321,7 +3331,10 @@ public class DefaultCodegen implements CodegenConfig { * @param openAPI The OpenAPI spec that we are using * @return the list of oneOf and anyOf MappedModel that need to be added to the discriminator map */ - protected List<MappedModel> getOneOfAnyOfDescendants(String composedSchemaName, String discPropName, ComposedSchema c, OpenAPI openAPI) { + protected List<MappedModel> getOneOfAnyOfDescendants(String composedSchemaName, String discPropName, Schema<?> c, OpenAPI openAPI) { + if (!ModelUtils.isComposedSchema(c)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", c.getName()); + } ArrayList<List<Schema>> listOLists = new ArrayList<>(); listOLists.add(c.getOneOf()); listOLists.add(c.getAnyOf()); @@ -3369,7 +3382,7 @@ public class DefaultCodegen implements CodegenConfig { } MappedModel mm = new MappedModel(modelName, toModelName(modelName)); descendentSchemas.add(mm); - Schema cs = ModelUtils.getSchema(openAPI, modelName); + Schema<?> cs = ModelUtils.getSchema(openAPI, modelName); if (cs == null) { // cannot lookup the model based on the name LOGGER.error("Failed to lookup the schema '{}' when processing oneOf/anyOf. Please check to ensure it's defined properly.", modelName); } else { @@ -3401,10 +3414,10 @@ public class DefaultCodegen implements CodegenConfig { } Schema child = schemas.get(childName); if (ModelUtils.isComposedSchema(child)) { - ComposedSchema composedChild = (ComposedSchema) child; + Schema<?> composedChild = child; List<Schema> parents = composedChild.getAllOf(); if (parents != null) { - for (Schema parent : parents) { + for (Schema<?> parent : parents) { String ref = parent.get$ref(); if (ref == null) { // for schemas with no ref, it is not possible to build the discriminator map @@ -3430,7 +3443,7 @@ public class DefaultCodegen implements CodegenConfig { currentSchemaName = queue.remove(0); MappedModel mm = new MappedModel(currentSchemaName, toModelName(currentSchemaName)); descendentSchemas.add(mm); - Schema cs = schemas.get(currentSchemaName); + Schema<?> cs = schemas.get(currentSchemaName); Map<String, Object> vendorExtensions = cs.getExtensions(); if (vendorExtensions != null && !vendorExtensions.isEmpty() && vendorExtensions.containsKey("x-discriminator-value")) { String xDiscriminatorValue = (String) vendorExtensions.get("x-discriminator-value"); @@ -3502,7 +3515,7 @@ public class DefaultCodegen implements CodegenConfig { } // if there are composed oneOf/anyOf schemas, add them to this discriminator if (ModelUtils.isComposedSchema(schema) && !this.getLegacyDiscriminatorBehavior()) { - List<MappedModel> otherDescendants = getOneOfAnyOfDescendants(schemaName, discPropName, (ComposedSchema) schema, openAPI); + List<MappedModel> otherDescendants = getOneOfAnyOfDescendants(schemaName, discPropName, schema, openAPI); for (MappedModel otherDescendant : otherDescendants) { if (!uniqueDescendants.contains(otherDescendant)) { uniqueDescendants.add(otherDescendant); @@ -3539,8 +3552,8 @@ public class DefaultCodegen implements CodegenConfig { if (!visitedSchemas.add(schema)) { return; } - if (schema instanceof ComposedSchema) { - ComposedSchema composedSchema = (ComposedSchema) schema; + if (ModelUtils.isComposedSchema(schema)) { + Schema<?> composedSchema = schema; if (composedSchema.getAllOf() != null) { for (Schema component : composedSchema.getAllOf()) { @@ -3639,8 +3652,8 @@ public class DefaultCodegen implements CodegenConfig { if (Boolean.FALSE.equals(p.getNullable())) { LOGGER.warn("Schema '{}' is any type, which includes the 'null' value. 'nullable' cannot be set to 'false'", p.getName()); } - ComposedSchema composedSchema = p instanceof ComposedSchema - ? (ComposedSchema) p + Schema<?> composedSchema = ModelUtils.isComposedSchema(p) + ? p : null; property.isNullable = property.isNullable || composedSchema == null || composedSchema.getAllOf() == null || composedSchema.getAllOf().size() == 0; if (languageSpecificPrimitives.contains(property.dataType)) { @@ -5558,7 +5571,10 @@ public class DefaultCodegen implements CodegenConfig { * @param model codegen model * @param modelName model name */ - protected void addImport(ComposedSchema composed, Schema childSchema, CodegenModel model, String modelName ) { + protected void addImport(Schema<?> composed, Schema childSchema, CodegenModel model, String modelName ) { + if (!ModelUtils.isComposedSchema(composed)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", composed.getName()); + } // import only if it's not allOf composition schema (without discriminator) if (!(composed.getAllOf() != null && childSchema.getDiscriminator() == null)) { addImport(model, modelName); @@ -7675,7 +7691,10 @@ public class DefaultCodegen implements CodegenConfig { * @param s schema to add the extension to * @param name name of the parent oneOf schema */ - public void addOneOfNameExtension(ComposedSchema s, String name) { + public void addOneOfNameExtension(Schema<?> s, String name) { + if (!ModelUtils.isComposedSchema(s)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", s.getName()); + } if (s.getOneOf() != null && s.getOneOf().size() > 0) { s.addExtension("x-one-of-name", name); } @@ -7688,7 +7707,10 @@ public class DefaultCodegen implements CodegenConfig { * @param type name to use for the generated interface model * @param openAPI OpenAPI spec that we are using */ - public void addOneOfInterfaceModel(ComposedSchema cs, String type, OpenAPI openAPI) { + public void addOneOfInterfaceModel(Schema<?> cs, String type, OpenAPI openAPI) { + if (!ModelUtils.isComposedSchema(cs)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", cs.getName()); + } if (cs.getOneOf() == null) { return; } @@ -7931,7 +7953,7 @@ public class DefaultCodegen implements CodegenConfig { } private CodegenComposedSchemas getComposedSchemas(Schema schema) { - if (!(schema instanceof ComposedSchema) && schema.getNot()==null) { + if (!(ModelUtils.isComposedSchema(schema)) && schema.getNot()==null) { return null; } Schema notSchema = schema.getNot(); @@ -7942,8 +7964,8 @@ public class DefaultCodegen implements CodegenConfig { List<CodegenProperty> allOf = new ArrayList<>(); List<CodegenProperty> oneOf = new ArrayList<>(); List<CodegenProperty> anyOf = new ArrayList<>(); - if (schema instanceof ComposedSchema) { - ComposedSchema cs = (ComposedSchema) schema; + if (ModelUtils.isComposedSchema(schema)) { + Schema<?> cs = schema; allOf = getComposedProperties(cs.getAllOf(), "all_of"); oneOf = getComposedProperties(cs.getOneOf(), "one_of"); anyOf = getComposedProperties(cs.getAnyOf(), "any_of"); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java index f4110bd7576..b1be070aee0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java @@ -186,15 +186,15 @@ public class InlineModelResolver { if (resolveInlineEnums && schema.getEnum() != null && schema.getEnum().size() > 0) { return true; } - if (schema.getType() == null || "object".equals(schema.getType())) { + if (schema.getType() == null && schema.getTypes() == null || "object".equals(schema.getType()) || "object".equals(ModelUtils.getJsonSchemaOneTypeOnly(schema))) { // object or undeclared type with properties if (schema.getProperties() != null && schema.getProperties().size() > 0) { return true; } } - if (schema instanceof ComposedSchema) { + if (ModelUtils.isComposedSchema(schema)) { // allOf, anyOf, oneOf - ComposedSchema m = (ComposedSchema) schema; + Schema<?> m = schema; boolean isSingleAllOf = m.getAllOf() != null && m.getAllOf().size() == 1; boolean isReadOnly = m.getReadOnly() != null && m.getReadOnly(); @@ -202,7 +202,12 @@ public class InlineModelResolver { if (isSingleAllOf && (isReadOnly || isNullable)) { // Check if this composed schema only contains an allOf and a readOnly or nullable. - ComposedSchema c = new ComposedSchema(); + Schema c; + if (ModelUtils.isJsonSchema(m)) { + c = new JsonSchema(); + } else { + c = new ComposedSchema(); + } c.setAllOf(m.getAllOf()); c.setReadOnly(m.getReadOnly()); c.setNullable(m.getNullable()); @@ -243,9 +248,9 @@ public class InlineModelResolver { if (schema.get$ref() != null) { // if ref already, no inline schemas should be present but check for // any to catch OpenAPI violations - if (isModelNeeded(schema) || "object".equals(schema.getType()) || + if (isModelNeeded(schema) || "object".equals(schema.getType()) || "object".equals(ModelUtils.getJsonSchemaOneTypeOnly(schema)) || schema.getProperties() != null || schema.getAdditionalProperties() != null || - schema instanceof ComposedSchema) { + ModelUtils.isComposedSchema(schema)) { LOGGER.error("Illegal schema found with $ref combined with other properties," + " no properties should be defined alongside a $ref:\n " + schema.toString()); } @@ -254,7 +259,7 @@ public class InlineModelResolver { // Check object models / any type models / composed models for properties, // if the schema has a type defined that is not "object" it should not define // any properties - if (schema.getType() == null || "object".equals(schema.getType())) { + if (schema.getType() == null && schema.getTypes() == null || "object".equals(schema.getType()) || "object".equals(ModelUtils.getJsonSchemaOneTypeOnly(schema))) { // Check properties and recurse, each property could be its own inline model Map<String, Schema> props = schema.getProperties(); if (props != null) { @@ -267,10 +272,10 @@ public class InlineModelResolver { // If this schema should be split into its own model, do so Schema refSchema = this.makeSchemaInComponents(schemaName, prop); props.put(propName, refSchema); - } else if (prop instanceof ComposedSchema) { - ComposedSchema m = (ComposedSchema) prop; + } else if (ModelUtils.isComposedSchema(prop)) { + Schema<?> m = prop; if (m.getAllOf() != null && m.getAllOf().size() == 1 && - !(m.getAllOf().get(0).getType() == null || "object".equals(m.getAllOf().get(0).getType()))) { + !(m.getAllOf().get(0).getType() == null && m.getAllOf().get(0).getTypes() == null || "object".equals(m.getAllOf().get(0).getType()) || "object".equals(ModelUtils.getJsonSchemaOneTypeOnly(m.getAllOf().get(0))))) { // allOf with only 1 type (non-model) LOGGER.info("allOf schema used by the property `{}` replaced by its only item (a type)", propName); props.put(propName, m.getAllOf().get(0)); @@ -328,8 +333,8 @@ public class InlineModelResolver { } } // Check allOf, anyOf, oneOf for inline models - if (schema instanceof ComposedSchema) { - ComposedSchema m = (ComposedSchema) schema; + if (ModelUtils.isComposedSchema(schema)) { + Schema<?> m = schema; if (m.getAllOf() != null) { List<Schema> newAllOf = new ArrayList<Schema>(); boolean atLeastOneModel = false; @@ -592,11 +597,10 @@ public class InlineModelResolver { for (String modelName : modelNames) { Schema model = models.get(modelName); if (ModelUtils.isComposedSchema(model)) { - ComposedSchema m = (ComposedSchema) model; // inline child schemas - flattenComposedChildren(modelName + "_allOf", m.getAllOf()); - flattenComposedChildren(modelName + "_anyOf", m.getAnyOf()); - flattenComposedChildren(modelName + "_oneOf", m.getOneOf()); + flattenComposedChildren(modelName + "_allOf", model.getAllOf()); + flattenComposedChildren(modelName + "_anyOf", model.getAnyOf()); + flattenComposedChildren(modelName + "_oneOf", model.getOneOf()); } else if (model instanceof Schema) { gatherInlineModels(model, modelName); } @@ -619,7 +623,7 @@ public class InlineModelResolver { } private boolean schemaIsOfType(Schema m, String type) { - return m.getType() != null && m.getType().equals(type); + return m.getType() != null && m.getType().equals(type) || type.equals(ModelUtils.getJsonSchemaOneTypeOnly(m)); } private boolean schemaContainsExample(Schema m) { @@ -715,9 +719,9 @@ public class InlineModelResolver { for (Map.Entry<String, Schema> propertiesEntry : properties.entrySet()) { String key = propertiesEntry.getKey(); Schema property = propertiesEntry.getValue(); - if (property instanceof ObjectSchema && ((ObjectSchema) property).getProperties() != null - && ((ObjectSchema) property).getProperties().size() > 0) { - ObjectSchema op = (ObjectSchema) property; + if (ModelUtils.isObjectSchema(property) && property.getProperties() != null + && property.getProperties().size() > 0) { + Schema op = property; String modelName = resolveModelName(op.getTitle(), path + "_" + key); Schema model = modelFromProperty(openAPI, op, modelName); String existing = matchGenerated(model); @@ -734,8 +738,8 @@ public class InlineModelResolver { } } else if (ModelUtils.isArraySchema(property)) { Schema inner = ModelUtils.getArrayItems(property); - if (inner instanceof ObjectSchema) { - ObjectSchema op = (ObjectSchema) inner; + if (ModelUtils.isObjectSchema(inner)) { + Schema op = inner; if (op.getProperties() != null && op.getProperties().size() > 0) { flattenProperties(openAPI, op.getProperties(), path); String modelName = resolveModelName(op.getTitle(), path + "_" + key); @@ -756,8 +760,8 @@ public class InlineModelResolver { } if (ModelUtils.isMapSchema(property)) { Schema inner = ModelUtils.getAdditionalProperties(openAPI, property); - if (inner instanceof ObjectSchema) { - ObjectSchema op = (ObjectSchema) inner; + if (ModelUtils.isObjectSchema(inner)) { + Schema op = inner; if (op.getProperties() != null && op.getProperties().size() > 0) { flattenProperties(openAPI, op.getProperties(), path); String modelName = resolveModelName(op.getTitle(), path + "_" + key); @@ -802,6 +806,7 @@ public class InlineModelResolver { // No need to null check setters below. All defaults in the new'd Schema are null, so setting to null would just be a noop. Schema model = new Schema(); model.setType(object.getType()); + model.setTypes(object.getTypes()); // Even though the `format` keyword typically applies to primitive types only, // the JSON schema specification states `format` can be used for any model type instance diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index 32be85cdf46..4afebdf0ed8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -307,10 +307,10 @@ public class OpenAPINormalizer { } else if (schema.getAdditionalProperties() instanceof Schema) { // map normalizeSchema((Schema) schema.getAdditionalProperties(), visitedSchemas); } else if (ModelUtils.isComposedSchema(schema)) { - ComposedSchema cs = (ComposedSchema) schema; + Schema<?> cs = schema; if (ModelUtils.isComplexComposedSchema(cs)) { - cs = (ComposedSchema) normalizeComplexComposedSchema(cs, visitedSchemas); + cs = normalizeComplexComposedSchema(cs, visitedSchemas); } if (cs.getAllOf() != null && !cs.getAllOf().isEmpty()) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java index 63c55a7d3c5..782351e2e5f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java @@ -558,7 +558,7 @@ public abstract class AbstractDartCodegen extends DefaultCodegen { // Handle composed properties if (ModelUtils.isComposedSchema(p)) { - ComposedSchema composed = (ComposedSchema) p; + Schema<?> composed = p; // Count the occurrences of allOf/anyOf/oneOf with exactly one child element long count = Stream.of(composed.getAllOf(), composed.getAnyOf(), composed.getOneOf()) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 9b111935298..d7cac396bcb 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -1051,7 +1051,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code } else { // has default value return toArrayDefaultValue(cp, schema); } - } else if (ModelUtils.isMapSchema(schema) && !(schema instanceof ComposedSchema)) { + } else if (ModelUtils.isMapSchema(schema) && !ModelUtils.isComposedSchema(schema)) { if (schema.getProperties() != null && schema.getProperties().size() > 0) { // object is complex object with free-form additional properties if (schema.getDefault() != null) { @@ -1617,8 +1617,8 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code .map(Schema::getProperties)) .forEach(schemas -> schemas.replaceAll( (name, s) -> Stream.of(s) - .filter(schema -> schema instanceof ComposedSchema) - .map(schema -> (ComposedSchema) schema) + .map(schema -> (Schema<?>) schema) + .filter(schema -> ModelUtils.isComposedSchema(schema)) .filter(schema -> Objects.nonNull(schema.getAnyOf())) .flatMap(schema -> schema.getAnyOf().stream()) .filter(schema -> Objects.nonNull(schema.getEnum())) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index ea78a33ae50..5f2fe3fe7e2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -1129,7 +1129,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co * ModelUtils.isMapSchema * In other generators, isMap is true for all type object schemas */ - if (schema.getProperties() != null || schema.getRequired() != null && !(schema instanceof ComposedSchema)) { + if (schema.getProperties() != null || schema.getRequired() != null && !(ModelUtils.isComposedSchema(schema))) { // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java index 8a043b5cb58..354c58bfcb2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java @@ -1085,21 +1085,21 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp } @Override - public String toAnyOfName(List<String> names, ComposedSchema composedSchema) { + public String toAnyOfName(List<String> names, Schema<?> composedSchema) { List<String> types = getTypesFromSchemas(composedSchema.getAnyOf()); return String.join(" | ", types); } @Override - public String toOneOfName(List<String> names, ComposedSchema composedSchema) { + public String toOneOfName(List<String> names, Schema<?> composedSchema) { List<String> types = getTypesFromSchemas(composedSchema.getOneOf()); return String.join(" | ", types); } @Override - public String toAllOfName(List<String> names, ComposedSchema composedSchema) { + public String toAllOfName(List<String> names, Schema<?> composedSchema) { List<String> types = getTypesFromSchemas(composedSchema.getAllOf()); return String.join(" & ", types); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java index 184df911737..e7cdad60ec1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java @@ -1575,7 +1575,7 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen { * ModelUtils.isMapSchema * In other generators, isMap is true for all type object schemas */ - if (schema.getProperties() != null || schema.getRequired() != null && !(schema instanceof ComposedSchema)) { + if (schema.getProperties() != null || schema.getRequired() != null && !(ModelUtils.isComposedSchema(schema))) { // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreReducedClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreReducedClientCodegen.java index e9b09f0acb9..f8f8b159884 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreReducedClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreReducedClientCodegen.java @@ -1130,7 +1130,7 @@ public class CSharpNetCoreReducedClientCodegen extends AbstractCSharpCodegen { * ModelUtils.isMapSchema * In other generators, isMap is true for all type object schemas */ - if (schema.getProperties() != null || schema.getRequired() != null && !(schema instanceof ComposedSchema)) { + if (schema.getProperties() != null || schema.getRequired() != null && !(ModelUtils.isComposedSchema(schema))) { // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java index 2a8acd9c23c..ccc6dc9568b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java @@ -411,7 +411,7 @@ public class GoServerCodegen extends AbstractGoCodegen { * ModelUtils.isMapSchema * In other generators, isMap is true for all type object schemas */ - if (schema.getProperties() != null || schema.getRequired() != null && !(schema instanceof ComposedSchema)) { + if (schema.getProperties() != null || schema.getRequired() != null && !(ModelUtils.isComposedSchema(schema))) { // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaCXFServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaCXFServerCodegen.java index 0bd87011cb1..2dc61052bb7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaCXFServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaCXFServerCodegen.java @@ -352,7 +352,7 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen * ModelUtils.isMapSchema * In other generators, isMap is true for all type object schemas */ - if (schema.getProperties() != null || schema.getRequired() != null && !(schema instanceof ComposedSchema)) { + if (schema.getProperties() != null || schema.getRequired() != null && !(ModelUtils.isComposedSchema(schema))) { // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java index ff7ffe59817..e1cd8b4435b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptApolloClientCodegen.java @@ -1232,7 +1232,7 @@ public class JavascriptApolloClientCodegen extends DefaultCodegen implements Cod public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.JAVASCRIPT; } @Override - protected void addImport(ComposedSchema composed, Schema childSchema, CodegenModel model, String modelName ) { + protected void addImport(Schema composed, Schema childSchema, CodegenModel model, String modelName ) { // import everything (including child schema of a composed schema) addImport(model, modelName); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java index 8d5cc606280..b2c5b794baf 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java @@ -1226,7 +1226,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo } @Override - protected void addImport(ComposedSchema composed, Schema childSchema, CodegenModel model, String modelName) { + protected void addImport(Schema composed, Schema childSchema, CodegenModel model, String modelName) { // import everything (including child schema of a composed schema) addImport(model, modelName); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java index ea2812ec9ca..b0156893e62 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OCamlClientCodegen.java @@ -282,7 +282,7 @@ public class OCamlClientCodegen extends DefaultCodegen implements CodegenConfig if (ModelUtils.isArraySchema(schema)) { Schema itemsSchema = ModelUtils.getArrayItems(schema); collectEnumSchemas(parentName, sName, itemsSchema); - } else if (schema instanceof MapSchema && schema.getAdditionalProperties() instanceof Schema) { + } else if (ModelUtils.isMapSchema(schema) && schema.getAdditionalProperties() instanceof Schema) { collectEnumSchemas(parentName, sName, (Schema) schema.getAdditionalProperties()); } else if (isEnumSchema(schema)) { String h = hashEnum(schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java index 7f406093af8..33adb0088de 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java @@ -685,8 +685,8 @@ public class PythonClientCodegen extends AbstractPythonCodegen { if (ModelUtils.isAnyType(schema) && supportsAdditionalPropertiesWithComposedSchema) { // if anyType schema has properties then add them if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { - if (schema instanceof ComposedSchema) { - ComposedSchema cs = (ComposedSchema) schema; + if (ModelUtils.isComposedSchema(schema)) { + Schema<?> cs = schema; if (cs.getOneOf() != null && !cs.getOneOf().isEmpty()) { LOGGER.warn("'oneOf' is intended to include only the additional optional OAS extension discriminator object. " + "For more details, see https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.9.2.1.3 and the OAS section on 'Composition and Inheritance'."); @@ -1822,7 +1822,7 @@ public class PythonClientCodegen extends AbstractPythonCodegen { // or items + properties, both a ist and a dict could be accepted as payloads return fullPrefix + "{}" + closeChars; } - ComposedSchema cs = (ComposedSchema) schema; + Schema<?> cs = schema; Integer allOfExists = 0; if (cs.getAllOf() != null && !cs.getAllOf().isEmpty()) { allOfExists = 1; @@ -1992,7 +1992,7 @@ public class PythonClientCodegen extends AbstractPythonCodegen { // what if this composed schema defined properties + allOf? return fullPrefix + closeChars; } - ComposedSchema cs = (ComposedSchema) schema; + Schema<?> cs = schema; Integer allOfExists = 0; if (cs.getAllOf() != null && !cs.getAllOf().isEmpty()) { allOfExists = 1; @@ -2425,7 +2425,7 @@ public class PythonClientCodegen extends AbstractPythonCodegen { @Override protected void updateModelForComposedSchema(CodegenModel m, Schema schema, Map<String, Schema> allDefinitions) { - final ComposedSchema composed = (ComposedSchema) schema; + final Schema<?> composed = schema; // TODO revise the logic below to set discriminator, xml attributes if (composed.getAllOf() != null) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java index 670cce62e74..b83200b4006 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonPriorClientCodegen.java @@ -616,7 +616,7 @@ public class PythonPriorClientCodegen extends PythonLegacyClientCodegen { // but they should not be required because if we have ComposedSchema: oneOf -schemaA -schemaB // and the required props are only in schemaB, we do not need to use them when making an instance of // ComposedSchema + schemaA - ComposedSchema cs = (ComposedSchema) schema; + Schema<?> cs = schema; // these are the properties that are from properties in self cs or cs allOf Map<String, Schema> selfProperties = new LinkedHashMap<>(); @@ -1511,7 +1511,7 @@ public class PythonPriorClientCodegen extends PythonLegacyClientCodegen { public String generatorLanguageVersion() { return ">=3.6"; }; @Override - protected void addImport(ComposedSchema composed, Schema childSchema, CodegenModel model, String modelName ) { + protected void addImport(Schema composed, Schema childSchema, CodegenModel model, String modelName ) { // import everything (including child schema of a composed schema) addImport(model, modelName); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index 80df5b06287..c00a1cfc2b4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -1243,7 +1243,7 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon } @Override - public String toOneOfName(List<String> names, ComposedSchema composedSchema) { + public String toOneOfName(List<String> names, Schema<?> composedSchema) { List<Schema> schemas = ModelUtils.getInterfaces(composedSchema); List<String> types = new ArrayList<>(); @@ -1254,7 +1254,7 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon } @Override - public String toAnyOfName(List<String> names, ComposedSchema composedSchema) { + public String toAnyOfName(List<String> names, Schema<?> composedSchema) { List<Schema> schemas = ModelUtils.getInterfaces(composedSchema); List<String> types = new ArrayList<>(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAxiosClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAxiosClientCodegen.java index bd42a79069c..d91897f6952 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAxiosClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAxiosClientCodegen.java @@ -292,7 +292,7 @@ public class TypeScriptAxiosClientCodegen extends AbstractTypeScriptClientCodege } @Override - protected void addImport(ComposedSchema composed, Schema childSchema, CodegenModel model, String modelName) { + protected void addImport(Schema composed, Schema childSchema, CodegenModel model, String modelName) { // import everything (including child schema of a composed schema) addImport(model, modelName); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java index 894c64e06a8..35b02aee61e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java @@ -1221,7 +1221,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo } return example; } else if (ModelUtils.isComposedSchema(schema)) { - ComposedSchema cm = (ComposedSchema) schema; + Schema cm = schema; List<Schema> ls = cm.getOneOf(); if (ls != null && !ls.isEmpty()) { return fullPrefix + toExampleValue(ls.get(0)) + closeChars; @@ -1483,21 +1483,21 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo } @Override - public String toAnyOfName(List<String> names, ComposedSchema composedSchema) { + public String toAnyOfName(List<String> names, Schema<?> composedSchema) { List<String> types = getTypesFromSchemas(composedSchema.getAnyOf()); return String.join(" | ", types); } @Override - public String toOneOfName(List<String> names, ComposedSchema composedSchema) { + public String toOneOfName(List<String> names, Schema<?> composedSchema) { List<String> types = getTypesFromSchemas(composedSchema.getOneOf()); return String.join(" | ", types); } @Override - public String toAllOfName(List<String> names, ComposedSchema composedSchema) { + public String toAllOfName(List<String> names, Schema<?> composedSchema) { List<String> types = getTypesFromSchemas(composedSchema.getAllOf()); return String.join(" & ", types); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java index aeaca5caf3c..eda31e86340 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java @@ -423,7 +423,7 @@ public class TypeScriptRxjsClientCodegen extends AbstractTypeScriptClientCodegen } @Override - protected void addImport(ComposedSchema composed, Schema childSchema, CodegenModel model, String modelName) { + protected void addImport(Schema composed, Schema childSchema, CodegenModel model, String modelName) { // import everything (including child schema of a composed schema) addImport(model, modelName); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index 04f586096aa..c90301c6151 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -330,20 +330,20 @@ public class ModelUtils { } } } - if (schema instanceof ComposedSchema) { - List<Schema> oneOf = ((ComposedSchema) schema).getOneOf(); + if (isComposedSchema(schema)) { + List<Schema> oneOf = schema.getOneOf(); if (oneOf != null) { for (Schema s : oneOf) { visitSchema(openAPI, s, mimeType, visitedSchemas, visitor); } } - List<Schema> allOf = ((ComposedSchema) schema).getAllOf(); + List<Schema> allOf = schema.getAllOf(); if (allOf != null) { for (Schema s : allOf) { visitSchema(openAPI, s, mimeType, visitedSchemas, visitor); } } - List<Schema> anyOf = ((ComposedSchema) schema).getAnyOf(); + List<Schema> anyOf = schema.getAnyOf(); if (anyOf != null) { for (Schema s : anyOf) { visitSchema(openAPI, s, mimeType, visitedSchemas, visitor); @@ -455,12 +455,18 @@ public class ModelUtils { return true; } - if (SchemaTypeUtil.OBJECT_TYPE.equals(getJsonSchemaOneTypeOnly(schema))) { + // Schema is almost always a JsonSchema but in a case of an inline object, the schema is not a JsonSchema but a Schema. + // type: object + // properties: + // bark: + // type: boolean + // Instead of using getJsonSchemaOneTypeOnly, get the type without checking the kind of Schema + if (schema != null && schema.getTypes() != null && schema.getTypes().size() == 1 && SchemaTypeUtil.OBJECT_TYPE.equals((String)schema.getTypes().iterator().next())) { return true; } // must have at least one property - if (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()) { + if (schema.getType() == null && schema.getTypes() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()) { return true; } return false; @@ -477,7 +483,7 @@ public class ModelUtils { if (schema instanceof ComposedSchema) { return true; } - return false; + return isJsonSchema(schema) && (schema.getAllOf() != null || schema.getOneOf() != null || schema.getAnyOf() != null); } /** @@ -488,7 +494,7 @@ public class ModelUtils { * @return true if the specified schema is a Composed schema. */ public static boolean isComplexComposedSchema(Schema schema) { - if (!(schema instanceof ComposedSchema)) { + if (!isComposedSchema(schema)) { return false; } @@ -582,18 +588,18 @@ public class ModelUtils { } /** - * Return the type defined in a JsonSchema + * Return the first and only type defined in the field "types" * Since swagger-core 2.2.0, getTypes can be defined for OpenAPI 3.1.0 * https://github.com/swagger-api/swagger-core/blob/v2.2.4/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java#L453-L460 * https://github.com/swagger-api/swagger-parser/blob/v2.1.8/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java#L383-L390 - * Return the first element of types if schema is a JsonFormat and it only contains one type like it is currently done in swagger-parser since 2.1.8: + * Use the same way it is currently done in swagger-parser since 2.1.8: * https://github.com/swagger-api/swagger-parser/blob/v2.1.8/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java#L469-L477 * * @param schema the schema that we are checking * @return String */ public static String getJsonSchemaOneTypeOnly(Schema schema) { - if (isJsonSchema(schema) && schema.getTypes() != null && schema.getTypes().size() == 1) { + if (schema != null && isJsonSchema(schema) && schema.getTypes() != null && schema.getTypes().size() == 1) { return (String)schema.getTypes().iterator().next(); } return null; @@ -826,7 +832,7 @@ public class ModelUtils { } // composed schema is a model, consider very simple ObjectSchema a model - return schema instanceof ComposedSchema || schema instanceof ObjectSchema; + return isComposedSchema(schema) || schema instanceof ObjectSchema || "object".equals(getJsonSchemaOneTypeOnly(schema)); } /** @@ -905,9 +911,8 @@ public class ModelUtils { } // not free-form if allOf, anyOf, oneOf is not empty - if (schema instanceof ComposedSchema) { - ComposedSchema cs = (ComposedSchema) schema; - List<Schema> interfaces = ModelUtils.getInterfaces(cs); + if (isComposedSchema(schema)) { + List<Schema> interfaces = ModelUtils.getInterfaces(schema); if (interfaces != null && !interfaces.isEmpty()) { return false; } @@ -932,10 +937,9 @@ public class ModelUtils { if (addlProps == null) { return true; } else { - if (addlProps instanceof ObjectSchema) { - ObjectSchema objSchema = (ObjectSchema) addlProps; + if (isObjectSchema(addlProps)) { // additionalProperties defined as {} - if (objSchema.getProperties() == null || objSchema.getProperties().isEmpty()) { + if (addlProps.getProperties() == null || addlProps.getProperties().isEmpty()) { return true; } } else if (addlProps instanceof Schema) { @@ -1222,8 +1226,8 @@ public class ModelUtils { return true; } } - if (schema instanceof ComposedSchema) { - List<Schema> oneOf = ((ComposedSchema) schema).getOneOf(); + if (ModelUtils.isComposedSchema(schema)) { + List<Schema> oneOf = (schema).getOneOf(); if (oneOf != null) { for (Schema s : oneOf) { if (hasSelfReference(openAPI, s, visitedSchemaNames)) { @@ -1231,7 +1235,7 @@ public class ModelUtils { } } } - List<Schema> allOf = ((ComposedSchema) schema).getAllOf(); + List<Schema> allOf = (schema).getAllOf(); if (allOf != null) { for (Schema s : allOf) { if (hasSelfReference(openAPI, s, visitedSchemaNames)) { @@ -1239,7 +1243,7 @@ public class ModelUtils { } } } - List<Schema> anyOf = ((ComposedSchema) schema).getAnyOf(); + List<Schema> anyOf = (schema).getAnyOf(); if (anyOf != null) { for (Schema s : anyOf) { if (hasSelfReference(openAPI, s, visitedSchemaNames)) { @@ -1444,8 +1448,8 @@ public class ModelUtils { Map<String, List<Entry<String, Schema>>> groupedByParent = allSchemas.entrySet().stream() .filter(entry -> isComposedSchema(entry.getValue())) - .filter(entry -> getParentName((ComposedSchema) entry.getValue(), allSchemas) != null) - .collect(Collectors.groupingBy(entry -> getParentName((ComposedSchema) entry.getValue(), allSchemas))); + .filter(entry -> getParentName(entry.getValue(), allSchemas) != null) + .collect(Collectors.groupingBy(entry -> getParentName(entry.getValue(), allSchemas))); return groupedByParent.entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().stream().map(e -> e.getKey()).collect(Collectors.toList()))); @@ -1458,7 +1462,10 @@ public class ModelUtils { * @param composed schema (alias or direct reference) * @return a list of schema defined in allOf, anyOf or oneOf */ - public static List<Schema> getInterfaces(ComposedSchema composed) { + public static List<Schema> getInterfaces(Schema composed) { + if (!isComposedSchema(composed)) { + LOGGER.error("Schema `{}` is not a ComposedSchema.", composed.getName()); + } if (composed.getAllOf() != null && !composed.getAllOf().isEmpty()) { return composed.getAllOf(); } else if (composed.getAnyOf() != null && !composed.getAnyOf().isEmpty()) { @@ -1499,7 +1506,7 @@ public class ModelUtils { * @param allSchemas all schemas * @return the name of the parent model */ - public static String getParentName(ComposedSchema composedSchema, Map<String, Schema> allSchemas) { + public static String getParentName(Schema<?> composedSchema, Map<String, Schema> allSchemas) { List<Schema> interfaces = getInterfaces(composedSchema); int nullSchemaChildrenCount = 0; boolean hasAmbiguousParents = false; @@ -1559,7 +1566,7 @@ public class ModelUtils { * @param includeAncestors if true, include the indirect ancestors in the return value. If false, return the direct parents. * @return the name of the parent model */ - public static List<String> getAllParentsName(ComposedSchema composedSchema, Map<String, Schema> allSchemas, boolean includeAncestors) { + public static List<String> getAllParentsName(Schema<?> composedSchema, Map<String, Schema> allSchemas, boolean includeAncestors) { List<Schema> interfaces = getInterfaces(composedSchema); List<String> names = new ArrayList<String>(); @@ -1575,8 +1582,8 @@ public class ModelUtils { } else if (hasOrInheritsDiscriminator(s, allSchemas)) { // discriminator.propertyName is used or x-parent is used names.add(parentName); - if (includeAncestors && s instanceof ComposedSchema) { - names.addAll(getAllParentsName((ComposedSchema) s, allSchemas, true)); + if (includeAncestors && isComposedSchema(s)) { + names.addAll(getAllParentsName(s, allSchemas, true)); } } else { // not a parent since discriminator.propertyName is not set @@ -1609,9 +1616,8 @@ public class ModelUtils { } else { LOGGER.error("Failed to obtain schema from {}", parentName); } - } else if (schema instanceof ComposedSchema) { - final ComposedSchema composed = (ComposedSchema) schema; - final List<Schema> interfaces = getInterfaces(composed); + } else if (isComposedSchema(schema)) { + final List<Schema> interfaces = getInterfaces(schema); for (Schema i : interfaces) { if (hasOrInheritsDiscriminator(i, allSchemas)) { return true; @@ -1678,8 +1684,8 @@ public class ModelUtils { return Boolean.parseBoolean(schema.getExtensions().get("x-nullable").toString()); } // In OAS 3.1, the recommended way to define a nullable property or object is to use oneOf. - if (schema instanceof ComposedSchema) { - return isNullableComposedSchema(((ComposedSchema) schema)); + if (isComposedSchema(schema)) { + return isNullableComposedSchema(schema); } return false; } @@ -1700,7 +1706,7 @@ public class ModelUtils { * @param schema the OAS composed schema. * @return true if the composed schema is nullable. */ - public static boolean isNullableComposedSchema(ComposedSchema schema) { + public static boolean isNullableComposedSchema(Schema schema) { List<Schema> oneOf = schema.getOneOf(); if (oneOf != null && oneOf.size() <= 2) { for (Schema s : oneOf) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/validations/oas/OpenApiSchemaValidations.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/validations/oas/OpenApiSchemaValidations.java index af784363e29..45f5c815f93 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/validations/oas/OpenApiSchemaValidations.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/validations/oas/OpenApiSchemaValidations.java @@ -69,8 +69,8 @@ class OpenApiSchemaValidations extends GenericValidator<SchemaWrapper> { Schema schema = schemaWrapper.getSchema(); ValidationRule.Result result = ValidationRule.Pass.empty(); - if (schema instanceof ComposedSchema) { - final ComposedSchema composed = (ComposedSchema) schema; + if (ModelUtils.isComposedSchema(schema)) { + final Schema<?> composed = schema; // check for loosely defined oneOf extension requirements. // This is a recommendation because the 3.0.x spec is not clear enough on usage of oneOf. // see https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.9.2.1.3 and the OAS section on 'Composition and Inheritance'. diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 71e7f4abbce..fc5964279f4 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -45,6 +45,8 @@ import org.openapitools.codegen.templating.mustache.TitlecaseLambda; import org.openapitools.codegen.templating.mustache.UppercaseLambda; import org.openapitools.codegen.utils.ModelUtils; import org.openapitools.codegen.utils.SemVer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.Ignore; import org.testng.annotations.Test; @@ -57,6 +59,7 @@ import java.util.stream.Collectors; import static org.testng.Assert.*; public class DefaultCodegenTest { + private final Logger LOG = LoggerFactory.getLogger(DefaultCodegenTest.class); @Test public void testDeeplyNestedAdditionalPropertiesImports() { @@ -4554,4 +4557,246 @@ public class DefaultCodegenTest { Assert.assertEquals(getQueryParamsByName(co.queryParams, name).dataFormat, null); Assert.assertEquals(getQueryParamsByName(co.queryParams, name).baseType, null); } + + @Test + public void testOpenAPI310JsonSchemaComposedSchemaOneOf() { + // Test should have the same result for OpenAPI 3.0 and OpenAPI 3.1 + List<String> files = Arrays.asList( + "src/test/resources/3_0/oas31-composed-schemas.yaml", + "src/test/resources/3_1/oas31-composed-schemas.yaml" + ); + for (String file : files) { + LOG.info("Process file: {}", file); + final OpenAPI openAPI = TestUtils.parseFlattenSpec(file); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + // From path + Operation operation = openAPI.getPaths().get("/state").getGet(); + Schema schema = ModelUtils.getReferencedSchema(openAPI, + ModelUtils.getSchemaFromResponse(operation.getResponses().get("200"))); + String type = codegen.getSchemaType(schema); + + Assert.assertNotNull(type); + Assert.assertEquals(type, "oneOf<ObjA,ObjB,ObjC>"); + + // From components + schema = openAPI.getComponents().getSchemas().get("CustomOneOfSchema"); + CodegenModel model = codegen.fromModel("CustomOneOfSchema", schema); + Assert.assertEquals(model.dataType, "oneOf<ObjA,ObjB,ObjC>"); + Assert.assertEquals(model.oneOf.size(), 3); + Assert.assertEquals(model.vars.size(), 5); + + schema = openAPI.getComponents().getSchemas().get("CustomOneOfSchemaInline"); + model = codegen.fromModel("CustomOneOfSchemaInline", schema); + Assert.assertEquals(model.dataType, "oneOf<ObjA,ObjB,ObjC,CustomOneOfSchemaInline_oneOf,AnyType>"); + Assert.assertEquals(model.oneOf.size(), 5); + Assert.assertEquals(model.vars.size(), 7); + + schema = openAPI.getComponents().getSchemas().get("CustomOneOfSchemaDiscriminator"); + model = codegen.fromModel("CustomOneOfSchemaDiscriminator", schema); + Assert.assertEquals(model.getHasDiscriminatorWithNonEmptyMapping(), true); + Assert.assertEquals(model.dataType, "oneOf<ObjA,ObjB,ObjC>"); + Assert.assertEquals(model.oneOf.size(), 3); + Assert.assertEquals(model.vars.size(), 5); + + Map<String, String> mapping = new HashMap<>(); + mapping.put("a-type", "#/components/schemas/ObjA"); + mapping.put("b-type", "#/components/schemas/ObjB"); + mapping.put("c-type", "#/components/schemas/ObjC"); + Assert.assertEquals(model.getDiscriminator().getMapping(), mapping); + + java.util.LinkedHashSet mappedModels = new LinkedHashSet<>(); + mappedModels.add(new CodegenDiscriminator.MappedModel("a-type", codegen.toModelName("ObjA"))); + mappedModels.add(new CodegenDiscriminator.MappedModel("b-type", codegen.toModelName("ObjB"))); + mappedModels.add(new CodegenDiscriminator.MappedModel("c-type", codegen.toModelName("ObjC"))); + Assert.assertEquals(model.getDiscriminator().getMappedModels(), mappedModels); + + CodegenDiscriminator testDiscriminator = new CodegenDiscriminator(); + testDiscriminator.setPropertyName("realtype"); + testDiscriminator.setPropertyBaseName("realtype"); + testDiscriminator.setMapping(mapping); + testDiscriminator.setMappedModels(mappedModels); + Assert.assertEquals(model.getDiscriminator(), testDiscriminator); + } + } + + @Test + public void testOpenAPI310JsonSchemaComposedSchemaAnyOf() { + // Test should have the same result for OpenAPI 3.0 and OpenAPI 3.1 + List<String> files = Arrays.asList( + "src/test/resources/3_0/oas31-composed-schemas.yaml", + "src/test/resources/3_1/oas31-composed-schemas.yaml" + ); + for (String file : files) { + LOG.info("Process file: {}", file); + final OpenAPI openAPI = TestUtils.parseFlattenSpec(file); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + Operation operation = openAPI.getPaths().get("/state").getPost(); + Schema schema = ModelUtils.getReferencedSchema(openAPI, + ModelUtils.getSchemaFromRequestBody(operation.getRequestBody())); + String type = codegen.getSchemaType(schema); + + Assert.assertNotNull(type); + Assert.assertEquals(type, "anyOf<ObjA,ObjB,ObjD>"); + + // From components + schema = openAPI.getComponents().getSchemas().get("CustomAnyOfSchema"); + CodegenModel model = codegen.fromModel("CustomAnyOfSchema", schema); + Assert.assertEquals(model.dataType, "anyOf<ObjA,ObjB,ObjD>"); + Assert.assertEquals(model.anyOf.size(), 3); + Assert.assertEquals(model.vars.size(), 5); + + schema = openAPI.getComponents().getSchemas().get("CustomAnyOfSchemaInline"); + model = codegen.fromModel("CustomAnyOfSchemaInline", schema); + Assert.assertEquals(model.dataType, "anyOf<ObjA,ObjB,ObjD,CustomOneOfSchemaInline_oneOf,AnyType>"); + Assert.assertEquals(model.anyOf.size(), 5); + Assert.assertEquals(model.vars.size(), 7); + + + schema = openAPI.getComponents().getSchemas().get("CustomAnyOfSchemaDiscriminator"); + model = codegen.fromModel("CustomAnyOfSchemaDiscriminator", schema); + Assert.assertEquals(model.getHasDiscriminatorWithNonEmptyMapping(), true); + Assert.assertEquals(model.dataType, "anyOf<ObjA,ObjB,ObjD>"); + Assert.assertEquals(model.anyOf.size(), 3); + Assert.assertEquals(model.vars.size(), 5); + + Map<String, String> mapping = new HashMap<>(); + mapping.put("a-type", "#/components/schemas/ObjA"); + mapping.put("b-type", "#/components/schemas/ObjB"); + mapping.put("d-type", "#/components/schemas/ObjD"); + Assert.assertEquals(model.getDiscriminator().getMapping(), mapping); + + java.util.LinkedHashSet mappedModels = new LinkedHashSet<>(); + mappedModels.add(new CodegenDiscriminator.MappedModel("a-type", codegen.toModelName("ObjA"))); + mappedModels.add(new CodegenDiscriminator.MappedModel("b-type", codegen.toModelName("ObjB"))); + mappedModels.add(new CodegenDiscriminator.MappedModel("d-type", codegen.toModelName("ObjD"))); + Assert.assertEquals(model.getDiscriminator().getMappedModels(), mappedModels); + + CodegenDiscriminator testDiscriminator = new CodegenDiscriminator(); + testDiscriminator.setPropertyName("realtype"); + testDiscriminator.setPropertyBaseName("realtype"); + testDiscriminator.setMapping(mapping); + testDiscriminator.setMappedModels(mappedModels); + Assert.assertEquals(model.getDiscriminator(), testDiscriminator); + } + } + + @Test + public void testOpenAPI310JsonSchemaComposedSchemaAllOf() { + // Test should have the same result for OpenAPI 3.0 and OpenAPI 3.1 + List<String> files = Arrays.asList( + "src/test/resources/3_0/oas31-composed-schemas.yaml", + "src/test/resources/3_1/oas31-composed-schemas.yaml" + ); + for (String file : files) { + LOG.info("Process file: {}", file); + final OpenAPI openAPI = TestUtils.parseFlattenSpec(file); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + Operation operation = openAPI.getPaths().get("/states").getGet(); + Schema schema = ModelUtils.getReferencedSchema(openAPI, + ModelUtils.getSchemaFromResponse(operation.getResponses().get("200"))); + String type = codegen.getSchemaType(schema); + + Assert.assertNotNull(type); + Assert.assertEquals(type, "ObjB"); + + // From components + schema = openAPI.getComponents().getSchemas().get("CustomAllOfSchema"); + CodegenModel model = codegen.fromModel("CustomAllOfSchema", schema); + // Only return first element + Assert.assertEquals(model.dataType, "ObjB"); + Assert.assertEquals(model.allOf.size(), 3); + Assert.assertEquals(model.vars.size(), 5); + + schema = openAPI.getComponents().getSchemas().get("CustomAllOfSchemaInline"); + model = codegen.fromModel("CustomAllOfSchemaInline", schema); + Assert.assertEquals(model.dataType, "ObjB"); + Assert.assertEquals(model.allOf.size(), 4); + Assert.assertEquals(model.vars.size(), 7); + + schema = openAPI.getComponents().getSchemas().get("CustomAllOfSchemaDiscriminator"); + model = codegen.fromModel("CustomAllOfSchemaDiscriminator", schema); + Assert.assertEquals(model.getHasDiscriminatorWithNonEmptyMapping(), true); + Assert.assertEquals(model.dataType, "ObjB"); + Assert.assertEquals(model.allOf.size(), 3); + Assert.assertEquals(model.vars.size(), 5); + + Map<String, String> mapping = new HashMap<>(); + mapping.put("b-type", "#/components/schemas/ObjB"); + mapping.put("c-type", "#/components/schemas/ObjC"); + mapping.put("d-type", "#/components/schemas/ObjD"); + Assert.assertEquals(model.getDiscriminator().getMapping(), mapping); + + java.util.LinkedHashSet mappedModels = new LinkedHashSet<>(); + mappedModels.add(new CodegenDiscriminator.MappedModel("b-type", codegen.toModelName("ObjB"))); + mappedModels.add(new CodegenDiscriminator.MappedModel("c-type", codegen.toModelName("ObjC"))); + mappedModels.add(new CodegenDiscriminator.MappedModel("d-type", codegen.toModelName("ObjD"))); + Assert.assertEquals(model.getDiscriminator().getMappedModels(), mappedModels); + + CodegenDiscriminator testDiscriminator = new CodegenDiscriminator(); + testDiscriminator.setPropertyName("realtype"); + testDiscriminator.setPropertyBaseName("realtype"); + testDiscriminator.setMapping(mapping); + testDiscriminator.setMappedModels(mappedModels); + Assert.assertEquals(model.getDiscriminator(), testDiscriminator); + } + } + + @Test + public void testOpenAPI310JsonSchemaMapSchema() { + // Test should have the same result for OpenAPI 3.0 and OpenAPI 3.1 + List<String> files = Arrays.asList( + "src/test/resources/3_0/oas31-map-schemas.yaml", + "src/test/resources/3_1/oas31-map-schemas.yaml" + ); + for (String file : files) { + LOG.info("Process file: {}", file); + final OpenAPI openAPI = TestUtils.parseFlattenSpec(file); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + // From path + Operation operation = openAPI.getPaths().get("/state").getGet(); + Schema schema = ModelUtils.getReferencedSchema(openAPI, + ModelUtils.getSchemaFromResponse(operation.getResponses().get("200"))); + String type = codegen.getSchemaType(schema); + Assert.assertNotNull(type); + Assert.assertEquals(type, "map"); + + operation = openAPI.getPaths().get("/state").getPost(); + schema = ModelUtils.getReferencedSchema(openAPI, + ModelUtils.getSchemaFromRequestBody(operation.getRequestBody())); + type = codegen.getSchemaType(schema); + Assert.assertNotNull(type); + Assert.assertEquals(type, "map"); + + operation = openAPI.getPaths().get("/states").getGet(); + schema = ModelUtils.getReferencedSchema(openAPI, + ModelUtils.getSchemaFromResponse(operation.getResponses().get("200"))); + type = codegen.getSchemaType(schema); + Assert.assertNotNull(type); + Assert.assertEquals(type, "ObjA"); + + // From Components + schema = openAPI.getComponents().getSchemas().get("ObjC"); + CodegenModel model = codegen.fromModel("ObjC", schema); + Assert.assertTrue(model.isMap); + Assert.assertEquals(model.dataType, "map"); + + schema = openAPI.getComponents().getSchemas().get("ObjD"); + model = codegen.fromModel("ObjD", schema); + Assert.assertTrue(model.isMap); + Assert.assertEquals(model.dataType, "map"); + + schema = openAPI.getComponents().getSchemas().get("ObjE"); + model = codegen.fromModel("ObjE", schema); + Assert.assertTrue(model.isMap); + Assert.assertEquals(model.dataType, "ObjA"); + } + } } diff --git a/modules/openapi-generator/src/test/resources/3_0/oas31-composed-schemas.yaml b/modules/openapi-generator/src/test/resources/3_0/oas31-composed-schemas.yaml new file mode 100644 index 00000000000..cd6e374e470 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/oas31-composed-schemas.yaml @@ -0,0 +1,202 @@ +openapi: 3.0.1 +info: + title: oneOf/anyOf/allOf test + version: '1.0' +servers: + - url: 'http://localhost:8000/' +paths: + /state: + get: + operationId: getState + responses: + '200': + description: OK + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + post: + operationId: createState + requestBody: + content: + application/json: + schema: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + required: true + responses: + '201': + description: OK + /states: + get: + operationId: getStates + responses: + '200': + description: OK + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' +components: + schemas: + ObjA: + type: object + properties: + realtype: + type: string + message: + type: string + ObjB: + type: object + properties: + realtype: + type: string + description: + type: string + code: + type: integer + format: int32 + ObjC: + type: object + properties: + realtype: + type: string + state: + type: string + ObjD: + type: object + properties: + realtype: + type: string + color: + type: string + + CustomOneOfSchema: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + discriminator: + propertyName: realtype + mapping: + a-type: '#/components/schemas/ObjA' + b-type: '#/components/schemas/ObjB' + c-type: '#/components/schemas/ObjC' + CustomOneOfSchemaInline: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - type: object + properties: + bark: + type: boolean + breed: + type: string + enum: [Dingo, Husky, Retriever, Shepherd] + # This field will not match to any type. + - description: Dog information + CustomOneOfSchemaDiscriminator: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + discriminator: + propertyName: realtype + mapping: + a-type: '#/components/schemas/ObjA' + b-type: '#/components/schemas/ObjB' + c-type: '#/components/schemas/ObjC' + CustomOneOfArraySchema: + type: array + items: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + + + CustomAnyOfSchema: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + CustomAnyOfSchemaInline: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + - type: object + properties: + bark: + type: boolean + breed: + type: string + enum: [Dingo, Husky, Retriever, Shepherd] + # This field will not match to any type. + - description: Dog information + CustomAnyOfSchemaDiscriminator: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + discriminator: + propertyName: realtype + mapping: + a-type: '#/components/schemas/ObjA' + b-type: '#/components/schemas/ObjB' + d-type: '#/components/schemas/ObjD' + CustomOnyOfArraySchema: + type: array + items: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + + + CustomAllOfSchema: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' + CustomAllOfSchemaInline: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' + - type: object + properties: + bark: + type: boolean + breed: + type: string + enum: [Dingo, Husky, Retriever, Shepherd] + # This field will not match to any type. + - description: Dog information + CustomAllOfSchemaDiscriminator: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' + discriminator: + propertyName: realtype + mapping: + b-type: '#/components/schemas/ObjB' + c-type: '#/components/schemas/ObjC' + d-type: '#/components/schemas/ObjD' + CustomAllOfArraySchema: + type: array + items: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' diff --git a/modules/openapi-generator/src/test/resources/3_0/oas31-map-schemas.yaml b/modules/openapi-generator/src/test/resources/3_0/oas31-map-schemas.yaml new file mode 100644 index 00000000000..9a7bd1d3211 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/oas31-map-schemas.yaml @@ -0,0 +1,70 @@ +openapi: 3.0.1 +info: + title: map test + version: '1.0' +servers: + - url: 'http://localhost:8000/' +paths: + /state: + get: + operationId: getState + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ObjC' + post: + operationId: createState + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ObjD' + required: true + responses: + '201': + description: OK + /states: + get: + operationId: getStates + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ObjE' +components: + schemas: + ObjA: + type: object + properties: + realtype: + type: string + message: + type: string + ObjB: + type: object + properties: + description: + type: string + code: + type: integer + format: int32 + ObjC: + type: object + additionalProperties: true + ObjD: + type: object + additionalProperties: + type: object + properties: + code: + type: integer + ObjE: + additionalProperties: true + allOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' diff --git a/modules/openapi-generator/src/test/resources/3_1/oas31-composed-schemas.yaml b/modules/openapi-generator/src/test/resources/3_1/oas31-composed-schemas.yaml new file mode 100644 index 00000000000..7eff3ec9bf9 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/oas31-composed-schemas.yaml @@ -0,0 +1,175 @@ +openapi: 3.1.0 +info: + title: oneOf/anyOf/allOf test + version: '1.0' +servers: + - url: 'http://localhost:8000/' +paths: + /state: + get: + operationId: getState + responses: + '200': + description: OK + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + post: + operationId: createState + requestBody: + content: + application/json: + schema: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + required: true + responses: + '201': + description: OK + /states: + get: + operationId: getStates + responses: + '200': + description: OK + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' +components: + schemas: + ObjA: + type: object + properties: + realtype: + type: string + message: + type: string + ObjB: + type: object + properties: + realtype: + type: string + description: + type: string + code: + type: integer + format: int32 + ObjC: + type: object + properties: + realtype: + type: string + state: + type: string + ObjD: + type: object + properties: + realtype: + type: string + color: + type: string + + CustomOneOfSchema: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + CustomOneOfSchemaInline: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - type: object + properties: + bark: + type: boolean + breed: + type: string + enum: [Dingo, Husky, Retriever, Shepherd] + # This field will not match to any type. + - description: Dog information + CustomOneOfSchemaDiscriminator: + oneOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + discriminator: + propertyName: realtype + mapping: + a-type: '#/components/schemas/ObjA' + b-type: '#/components/schemas/ObjB' + c-type: '#/components/schemas/ObjC' + + + CustomAnyOfSchema: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + CustomAnyOfSchemaInline: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + - type: object + properties: + bark: + type: boolean + breed: + type: string + enum: [Dingo, Husky, Retriever, Shepherd] + # This field will not match to any type. + - description: Dog information + CustomAnyOfSchemaDiscriminator: + anyOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjD' + discriminator: + propertyName: realtype + mapping: + a-type: '#/components/schemas/ObjA' + b-type: '#/components/schemas/ObjB' + d-type: '#/components/schemas/ObjD' + + + CustomAllOfSchema: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' + CustomAllOfSchemaInline: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' + - type: object + properties: + bark: + type: boolean + breed: + type: string + enum: [Dingo, Husky, Retriever, Shepherd] + # This field will not match to any type. + - description: Dog information + CustomAllOfSchemaDiscriminator: + allOf: + - $ref: '#/components/schemas/ObjB' + - $ref: '#/components/schemas/ObjC' + - $ref: '#/components/schemas/ObjD' + discriminator: + propertyName: realtype + mapping: + b-type: '#/components/schemas/ObjB' + c-type: '#/components/schemas/ObjC' + d-type: '#/components/schemas/ObjD' diff --git a/modules/openapi-generator/src/test/resources/3_1/oas31-map-schemas.yaml b/modules/openapi-generator/src/test/resources/3_1/oas31-map-schemas.yaml new file mode 100644 index 00000000000..5c40549d47e --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/oas31-map-schemas.yaml @@ -0,0 +1,70 @@ +openapi: 3.1.0 +info: + title: map test + version: '1.0' +servers: + - url: 'http://localhost:8000/' +paths: + /state: + get: + operationId: getState + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ObjC' + post: + operationId: createState + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ObjD' + required: true + responses: + '201': + description: OK + /states: + get: + operationId: getStates + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ObjE' +components: + schemas: + ObjA: + type: object + properties: + realtype: + type: string + message: + type: string + ObjB: + type: object + properties: + description: + type: string + code: + type: integer + format: int32 + ObjC: + type: object + additionalProperties: true + ObjD: + type: object + additionalProperties: + type: object + properties: + code: + type: integer + ObjE: + additionalProperties: true + allOf: + - $ref: '#/components/schemas/ObjA' + - $ref: '#/components/schemas/ObjB' -- GitLab From 678dc001583c324f09c5b62ec8da5d765b125f9d Mon Sep 17 00:00:00 2001 From: Guillaume Smaha <guillaume.smaha@gmail.com> Date: Wed, 8 Feb 2023 23:30:32 +0100 Subject: [PATCH 9/9] Fix value return in isFreeFormObject by checking in isObjectSchema() that it is not a MapSchema --- .../codegen/utils/ModelUtils.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index c90301c6151..330333671f7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -460,8 +460,8 @@ public class ModelUtils { // properties: // bark: // type: boolean - // Instead of using getJsonSchemaOneTypeOnly, get the type without checking the kind of Schema - if (schema != null && schema.getTypes() != null && schema.getTypes().size() == 1 && SchemaTypeUtil.OBJECT_TYPE.equals((String)schema.getTypes().iterator().next())) { + // Instead of using getJsonSchemaOneTypeOnly, get the type without checking the kind of Schema but still check that schema is not a MapSchema + if (SchemaTypeUtil.OBJECT_TYPE.equals(getTypesOnlyOneType(schema)) && !(schema instanceof MapSchema)) { return true; } @@ -592,6 +592,19 @@ public class ModelUtils { * Since swagger-core 2.2.0, getTypes can be defined for OpenAPI 3.1.0 * https://github.com/swagger-api/swagger-core/blob/v2.2.4/modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java#L453-L460 * https://github.com/swagger-api/swagger-parser/blob/v2.1.8/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java#L383-L390 + * + * @param schema the schema that we are checking + * @return String + */ + public static String getTypesOnlyOneType(Schema schema) { + if (schema != null && schema.getTypes() != null && schema.getTypes().size() == 1) { + return (String)schema.getTypes().iterator().next(); + } + return null; + } + + /** + * Return the first and only type defined in the field "types" if the schema is JsonSchema * Use the same way it is currently done in swagger-parser since 2.1.8: * https://github.com/swagger-api/swagger-parser/blob/v2.1.8/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java#L469-L477 * @@ -599,8 +612,8 @@ public class ModelUtils { * @return String */ public static String getJsonSchemaOneTypeOnly(Schema schema) { - if (schema != null && isJsonSchema(schema) && schema.getTypes() != null && schema.getTypes().size() == 1) { - return (String)schema.getTypes().iterator().next(); + if (isJsonSchema(schema)) { + return getTypesOnlyOneType(schema); } return null; } @@ -831,8 +844,8 @@ public class ModelUtils { return true; } - // composed schema is a model, consider very simple ObjectSchema a model - return isComposedSchema(schema) || schema instanceof ObjectSchema || "object".equals(getJsonSchemaOneTypeOnly(schema)); + // composed schema or object is a model + return isComposedSchema(schema) || isObjectSchema(schema); } /** @@ -919,7 +932,7 @@ public class ModelUtils { } // has at least one property - if ("object".equals(schema.getType()) || "object".equals(getJsonSchemaOneTypeOnly(schema))) { + if (SchemaTypeUtil.OBJECT_TYPE.equals(schema.getType()) || SchemaTypeUtil.OBJECT_TYPE.equals(getJsonSchemaOneTypeOnly(schema))) { // no properties if ((schema.getProperties() == null || schema.getProperties().isEmpty())) { Schema addlProps = getAdditionalProperties(openAPI, schema); -- GitLab