Skip to content

Commit f6231d2

Browse files
authored
Remove restrictions for additional property types (#11802)
When a schema specifies additionalProperties: true, we need not restrict those properties to a particular type. This change sets the schemas for them to AnyType instead of object. From a generation perspective, this only changes the output for generators that differentiate between AnyType and object in their type mappings; most do not. This fixes at least one bug in the Go and TypeScript generators.
1 parent e783e9b commit f6231d2

7 files changed

Lines changed: 60 additions & 15 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,12 +1200,11 @@ public static Schema getAdditionalProperties(OpenAPI openAPI, Schema schema) {
12001200
*/
12011201
}
12021202
if (addProps == null || (addProps instanceof Boolean && (Boolean) addProps)) {
1203-
// Return ObjectSchema to specify any object (map) value is allowed.
1204-
// Set nullable to specify the value of additional properties may be
1205-
// the null value.
1206-
// Free-form additionalProperties don't need to have an inner
1207-
// additional properties, the type is already free-form.
1208-
return new ObjectSchema().additionalProperties(Boolean.FALSE).nullable(Boolean.TRUE);
1203+
// Return an empty schema as the properties can take on any type per
1204+
// the spec. See
1205+
// https://github.com/OpenAPITools/openapi-generator/issues/9282 for
1206+
// more details.
1207+
return new Schema();
12091208
}
12101209
return null;
12111210
}

modules/openapi-generator/src/main/resources/typescript-axios/modelGeneric.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
export interface {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{
77
{{#additionalPropertiesType}}
8-
[key: string]: {{{additionalPropertiesType}}}{{#hasVars}} | any{{/hasVars}};
8+
[key: string]: {{{additionalPropertiesType}}}{{^additionalPropertiesIsAnyType}}{{#hasVars}} | any{{/hasVars}}{{/additionalPropertiesIsAnyType}};
99

1010
{{/additionalPropertiesType}}
1111
{{#vars}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese
449449
// extended with any undeclared properties.
450450
Schema addProps = ModelUtils.getAdditionalProperties(openAPI, componentSchema);
451451
Assert.assertNotNull(addProps);
452-
Assert.assertTrue(addProps instanceof ObjectSchema);
452+
Assert.assertEquals(addProps, new Schema());
453453
CodegenModel cm = codegen.fromModel("AdditionalPropertiesClass", componentSchema);
454454
Assert.assertNotNull(cm.getAdditionalProperties());
455455

@@ -494,7 +494,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese
494494
Assert.assertNull(map_with_undeclared_properties_anytype_1_sc.getAdditionalProperties());
495495
addProps = ModelUtils.getAdditionalProperties(openAPI, map_with_undeclared_properties_anytype_1_sc);
496496
Assert.assertNotNull(addProps);
497-
Assert.assertTrue(addProps instanceof ObjectSchema);
497+
Assert.assertEquals(addProps, new Schema());
498498
Assert.assertNotNull(map_with_undeclared_properties_anytype_1_cp.getAdditionalProperties());
499499

500500
// map_with_undeclared_properties_anytype_2
@@ -504,7 +504,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese
504504
Assert.assertNull(map_with_undeclared_properties_anytype_2_sc.getAdditionalProperties());
505505
addProps = ModelUtils.getAdditionalProperties(openAPI, map_with_undeclared_properties_anytype_2_sc);
506506
Assert.assertNotNull(addProps);
507-
Assert.assertTrue(addProps instanceof ObjectSchema);
507+
Assert.assertEquals(addProps, new Schema());
508508
Assert.assertNotNull(map_with_undeclared_properties_anytype_2_cp.getAdditionalProperties());
509509

510510
// map_with_undeclared_properties_anytype_3
@@ -517,7 +517,7 @@ public void testAdditionalPropertiesV3SpecDisallowAdditionalPropertiesIfNotPrese
517517
Assert.assertEquals(map_with_undeclared_properties_anytype_3_sc.getAdditionalProperties(), Boolean.TRUE);
518518
addProps = ModelUtils.getAdditionalProperties(openAPI, map_with_undeclared_properties_anytype_3_sc);
519519
Assert.assertNotNull(addProps);
520-
Assert.assertTrue(addProps instanceof ObjectSchema);
520+
Assert.assertEquals(addProps, new Schema());
521521
Assert.assertNotNull(map_with_undeclared_properties_anytype_3_cp.getAdditionalProperties());
522522

523523
// empty_map
@@ -2769,6 +2769,26 @@ public void testAdditionalPropertiesPresentInResponses() {
27692769
}
27702770
}
27712771

2772+
@Test
2773+
public void testAdditionalPropertiesAnyType() {
2774+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_9282.yaml");
2775+
final DefaultCodegen codegen = new DefaultCodegen();
2776+
codegen.setOpenAPI(openAPI);
2777+
2778+
CodegenProperty anyTypeSchema = codegen.fromProperty("", new Schema());
2779+
2780+
Schema sc;
2781+
CodegenModel cm;
2782+
2783+
sc = openAPI.getComponents().getSchemas().get("AdditionalPropertiesTrue");
2784+
cm = codegen.fromModel("AdditionalPropertiesTrue", sc);
2785+
assertEquals(cm.getVars().get(0).additionalProperties, anyTypeSchema);
2786+
2787+
sc = openAPI.getComponents().getSchemas().get("AdditionalPropertiesAnyType");
2788+
cm = codegen.fromModel("AdditionalPropertiesAnyType", sc);
2789+
assertEquals(cm.getVars().get(0).additionalProperties, anyTypeSchema);
2790+
}
2791+
27722792
@Test
27732793
public void testIsXPresence() {
27742794
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7651.yaml");

modules/openapi-generator/src/test/java/org/openapitools/codegen/go/AbstractGoCodegenTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.swagger.v3.oas.models.media.ArraySchema;
2323
import io.swagger.v3.oas.models.media.IntegerSchema;
2424
import io.swagger.v3.oas.models.media.MapSchema;
25+
import io.swagger.v3.oas.models.media.ObjectSchema;
2526
import io.swagger.v3.oas.models.media.Schema;
2627
import org.openapitools.codegen.CodegenConstants;
2728
import org.openapitools.codegen.CodegenType;
@@ -90,6 +91,13 @@ public void getTypeDeclarationTest() {
9091
ModelUtils.setGenerateAliasAsModel(true);
9192
defaultValue = codegen.getTypeDeclaration(schema);
9293
Assert.assertEquals(defaultValue, "map[string]NestedArray");
94+
95+
// Create object schema with additionalProperties set to true
96+
schema = new ObjectSchema().additionalProperties(Boolean.TRUE);
97+
98+
ModelUtils.setGenerateAliasAsModel(false);
99+
defaultValue = codegen.getTypeDeclaration(schema);
100+
Assert.assertEquals(defaultValue, "map[string]interface{}");
93101
}
94102

95103
private static class P_AbstractGoCodegen extends AbstractGoCodegen {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
openapi: 3.0.0
2+
components:
3+
schemas:
4+
AdditionalPropertiesTrue:
5+
description: additionalProperties set to true
6+
type: object
7+
properties:
8+
child:
9+
type: object
10+
additionalProperties: true
11+
12+
AdditionalPropertiesAnyType:
13+
description: additionalProperties set to any type explicitly
14+
type: object
15+
properties:
16+
child:
17+
type: object
18+
additionalProperties: {}

samples/client/petstore/typescript-axios/builds/test-petstore/api.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ export interface AdditionalPropertiesClass {
5959
'map_with_undeclared_properties_anytype_2'?: object;
6060
/**
6161
*
62-
* @type {{ [key: string]: object; }}
62+
* @type {{ [key: string]: any; }}
6363
* @memberof AdditionalPropertiesClass
6464
*/
65-
'map_with_undeclared_properties_anytype_3'?: { [key: string]: object; };
65+
'map_with_undeclared_properties_anytype_3'?: { [key: string]: any; };
6666
/**
6767
* an object with no declared properties and no undeclared properties, hence it\'s an empty map.
6868
* @type {object}
@@ -1706,7 +1706,7 @@ export interface Whale {
17061706
* @interface Zebra
17071707
*/
17081708
export interface Zebra {
1709-
[key: string]: object | any;
1709+
[key: string]: any;
17101710

17111711
/**
17121712
*

samples/client/petstore/typescript-axios/builds/with-fake-endpoints-models-for-testing-with-http-signature/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export interface ArrayTest {
173173
* @interface Banana
174174
*/
175175
export interface Banana {
176-
[key: string]: object | any;
176+
[key: string]: any;
177177

178178
/**
179179
*

0 commit comments

Comments
 (0)