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 eb5d5c6a2fe0..c0aa817466ef 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 @@ -1203,12 +1203,11 @@ public static Schema getAdditionalProperties(OpenAPI openAPI, Schema schema) { */ } if (addProps == null || (addProps instanceof Boolean && (Boolean) addProps)) { - // Return ObjectSchema to specify any object (map) value is allowed. - // Set nullable to specify the value of additional properties may be - // the null value. - // Free-form additionalProperties don't need to have an inner - // additional properties, the type is already free-form. - return new ObjectSchema().additionalProperties(Boolean.FALSE).nullable(Boolean.TRUE); + // Return an empty schema as the properties can take on any type per + // the spec. See + // https://github.com/OpenAPITools/openapi-generator/issues/9282 for + // more details. + return new Schema(); } return null; } diff --git a/modules/openapi-generator/src/main/resources/typescript-axios/modelGeneric.mustache b/modules/openapi-generator/src/main/resources/typescript-axios/modelGeneric.mustache index 06da8db77a66..6444507b8ebe 100644 --- a/modules/openapi-generator/src/main/resources/typescript-axios/modelGeneric.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-axios/modelGeneric.mustache @@ -5,7 +5,7 @@ */ export interface {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{ {{#additionalPropertiesType}} - [key: string]: {{{additionalPropertiesType}}}{{#hasVars}} | any{{/hasVars}}; + [key: string]: {{{additionalPropertiesType}}}{{^additionalPropertiesIsAnyType}}{{#hasVars}} | any{{/hasVars}}{{/additionalPropertiesIsAnyType}}; {{/additionalPropertiesType}} {{#vars}} 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 d279f0a32b12..fa8f24872cab 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 @@ -447,7 +447,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese // extended with any undeclared properties. Schema addProps = ModelUtils.getAdditionalProperties(openAPI, componentSchema); Assert.assertNotNull(addProps); - Assert.assertTrue(addProps instanceof ObjectSchema); + Assert.assertEquals(addProps, new Schema()); CodegenModel cm = codegen.fromModel("AdditionalPropertiesClass", componentSchema); Assert.assertNotNull(cm.getAdditionalProperties()); @@ -492,7 +492,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese Assert.assertNull(map_with_undeclared_properties_anytype_1_sc.getAdditionalProperties()); addProps = ModelUtils.getAdditionalProperties(openAPI, map_with_undeclared_properties_anytype_1_sc); Assert.assertNotNull(addProps); - Assert.assertTrue(addProps instanceof ObjectSchema); + Assert.assertEquals(addProps, new Schema()); Assert.assertNotNull(map_with_undeclared_properties_anytype_1_cp.getAdditionalProperties()); // map_with_undeclared_properties_anytype_2 @@ -502,7 +502,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese Assert.assertNull(map_with_undeclared_properties_anytype_2_sc.getAdditionalProperties()); addProps = ModelUtils.getAdditionalProperties(openAPI, map_with_undeclared_properties_anytype_2_sc); Assert.assertNotNull(addProps); - Assert.assertTrue(addProps instanceof ObjectSchema); + Assert.assertEquals(addProps, new Schema()); Assert.assertNotNull(map_with_undeclared_properties_anytype_2_cp.getAdditionalProperties()); // map_with_undeclared_properties_anytype_3 @@ -515,7 +515,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese Assert.assertEquals(map_with_undeclared_properties_anytype_3_sc.getAdditionalProperties(), Boolean.TRUE); addProps = ModelUtils.getAdditionalProperties(openAPI, map_with_undeclared_properties_anytype_3_sc); Assert.assertNotNull(addProps); - Assert.assertTrue(addProps instanceof ObjectSchema); + Assert.assertEquals(addProps, new Schema()); Assert.assertNotNull(map_with_undeclared_properties_anytype_3_cp.getAdditionalProperties()); // empty_map @@ -2770,6 +2770,26 @@ public void testAdditionalPropertiesPresentInResponses() { } } + @Test + public void testAdditionalPropertiesAnyType() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_9282.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + CodegenProperty anyTypeSchema = codegen.fromProperty("", new Schema()); + + Schema sc; + CodegenModel cm; + + sc = openAPI.getComponents().getSchemas().get("AdditionalPropertiesTrue"); + cm = codegen.fromModel("AdditionalPropertiesTrue", sc); + assertEquals(cm.getVars().get(0).additionalProperties, anyTypeSchema); + + sc = openAPI.getComponents().getSchemas().get("AdditionalPropertiesAnyType"); + cm = codegen.fromModel("AdditionalPropertiesAnyType", sc); + assertEquals(cm.getVars().get(0).additionalProperties, anyTypeSchema); + } + @Test public void testIsXPresence() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7651.yaml"); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/AbstractGoCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/AbstractGoCodegenTest.java index 4bb8762268df..c232ff4d8eaa 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/AbstractGoCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/AbstractGoCodegenTest.java @@ -22,6 +22,7 @@ import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MapSchema; +import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenType; @@ -90,6 +91,13 @@ public void getTypeDeclarationTest() { ModelUtils.setGenerateAliasAsModel(true); defaultValue = codegen.getTypeDeclaration(schema); Assert.assertEquals(defaultValue, "map[string]NestedArray"); + + // Create object schema with additionalProperties set to true + schema = new ObjectSchema().additionalProperties(Boolean.TRUE); + + ModelUtils.setGenerateAliasAsModel(false); + defaultValue = codegen.getTypeDeclaration(schema); + Assert.assertEquals(defaultValue, "map[string]interface{}"); } private static class P_AbstractGoCodegen extends AbstractGoCodegen { diff --git a/modules/openapi-generator/src/test/resources/3_0/issue_9282.yaml b/modules/openapi-generator/src/test/resources/3_0/issue_9282.yaml new file mode 100644 index 000000000000..f3d9f38c778d --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue_9282.yaml @@ -0,0 +1,18 @@ +openapi: 3.0.0 +components: + schemas: + AdditionalPropertiesTrue: + description: additionalProperties set to true + type: object + properties: + child: + type: object + additionalProperties: true + + AdditionalPropertiesAnyType: + description: additionalProperties set to any type explicitly + type: object + properties: + child: + type: object + additionalProperties: {} diff --git a/samples/client/petstore/typescript-axios/builds/test-petstore/api.ts b/samples/client/petstore/typescript-axios/builds/test-petstore/api.ts index 7d715d7ea75b..84e004fa465c 100644 --- a/samples/client/petstore/typescript-axios/builds/test-petstore/api.ts +++ b/samples/client/petstore/typescript-axios/builds/test-petstore/api.ts @@ -59,10 +59,10 @@ export interface AdditionalPropertiesClass { 'map_with_undeclared_properties_anytype_2'?: object; /** * - * @type {{ [key: string]: object; }} + * @type {{ [key: string]: any; }} * @memberof AdditionalPropertiesClass */ - 'map_with_undeclared_properties_anytype_3'?: { [key: string]: object; }; + 'map_with_undeclared_properties_anytype_3'?: { [key: string]: any; }; /** * an object with no declared properties and no undeclared properties, hence it\'s an empty map. * @type {object} @@ -1706,7 +1706,7 @@ export interface Whale { * @interface Zebra */ export interface Zebra { - [key: string]: object | any; + [key: string]: any; /** * diff --git a/samples/client/petstore/typescript-axios/builds/with-fake-endpoints-models-for-testing-with-http-signature/api.ts b/samples/client/petstore/typescript-axios/builds/with-fake-endpoints-models-for-testing-with-http-signature/api.ts index 62742e15f671..48600fbd0985 100644 --- a/samples/client/petstore/typescript-axios/builds/with-fake-endpoints-models-for-testing-with-http-signature/api.ts +++ b/samples/client/petstore/typescript-axios/builds/with-fake-endpoints-models-for-testing-with-http-signature/api.ts @@ -173,7 +173,7 @@ export interface ArrayTest { * @interface Banana */ export interface Banana { - [key: string]: object | any; + [key: string]: any; /** *