Skip to content

Commit 4e804ae

Browse files
committed
Fix: Handle additionalProperties false correctly - do not generate Map field
When additionalProperties is explicitly set to false, the generator should not create a Map field. Previously, any presence of additionalProperties would generate a Map regardless of its boolean value. Changes: - ModelBuilder.java: Updated processAdditionalProperties() to check if boolean false and skip Map generation - ModelBuilder.java: Updated setFieldType() to handle boolean false case - ModelBuilder.java: Updated getMapTypeObject() to safely handle boolean nodes - Added testAdditionalPropertiesFalse test case with YAML, expected DTO, and API - Bump patch version to 6.3.2 (bug fix) Fixes issue #367: additionalProperties false generates invalid Java code"
1 parent 7fadac7 commit 4e804ae

File tree

6 files changed

+62
-19
lines changed

6 files changed

+62
-19
lines changed

multiapi-engine/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.sngular</groupId>
66
<artifactId>multiapi-engine</artifactId>
7-
<version>6.3.1</version>
7+
<version>6.3.2</version>
88
<packaging>jar</packaging>
99

1010
<properties>

multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -539,13 +539,17 @@ private static List<SchemaFieldObject> processAdditionalProperties(
539539
final var fieldObjectArrayList = new ArrayList<SchemaFieldObject>();
540540

541541
final var addPropObj = ApiTool.getAdditionalProperties(schema);
542-
if (TypeConstants.isBoolean(addPropObj.asText())) {
543-
fieldObjectArrayList
544-
.add(SchemaFieldObject
545-
.builder()
546-
.baseName(fieldName)
547-
.dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, TypeConstants.OBJECT))
548-
.build());
542+
if (Objects.nonNull(addPropObj) && addPropObj.isBoolean()) {
543+
if (addPropObj.asBoolean()) {
544+
fieldObjectArrayList
545+
.add(SchemaFieldObject
546+
.builder()
547+
.baseName(fieldName)
548+
.dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, TypeConstants.OBJECT))
549+
.build());
550+
} else {
551+
return fieldObjectArrayList;
552+
}
549553
} else if (ApiTool.hasRef(addPropObj)) {
550554
final String refSchemaName = MapperUtil.getPojoNameFromRef(addPropObj, specFile, null);
551555
fieldObjectArrayList.add(processRef(fieldName, addPropObj,
@@ -633,12 +637,20 @@ private static void setFieldType(
633637
field.setDataType(SchemaFieldObjectType.fromTypeList(TypeConstants.ARRAY, typeArray));
634638
field.setImportClass(getImportClass(typeArray));
635639
} else if (ApiTool.hasAdditionalProperties(schemaProperty)) {
636-
final String typeObject = getMapTypeObject(schemaProperty, specFile);
637-
field.setDataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, typeObject));
638-
field.setImportClass(getImportClass(typeObject));
639-
640+
final JsonNode apNode = ApiTool.getAdditionalProperties(schemaProperty);
641+
if (Objects.nonNull(apNode) && apNode.isBoolean()) {
642+
if (apNode.asBoolean()) {
643+
final String typeObject = TypeConstants.OBJECT;
644+
field.setDataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, typeObject));
645+
field.setImportClass(getImportClass(typeObject));
646+
} // if boolean false -> do not set map type
647+
} else {
648+
final String typeObject = getMapTypeObject(schemaProperty, specFile);
649+
field.setDataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, typeObject));
650+
field.setImportClass(getImportClass(typeObject));
651+
}
640652
} else if (ApiTool.isObject(schemaProperty)) {
641-
var typeObject = ApiTool.getType(schemaProperty);
653+
String typeObject = ApiTool.getType(schemaProperty);
642654
if (ApiTool.hasRef(schemaProperty)) {
643655
typeObject = MapperUtil.getPojoNameFromRef(schema, specFile, null);
644656
}
@@ -649,10 +661,10 @@ private static void setFieldType(
649661

650662
private static String getMapTypeObject(final JsonNode schema, final CommonSpecFile specFile) {
651663
final String type;
652-
if (ApiTool.isBoolean(ApiTool.getAdditionalProperties(schema))) {
664+
final JsonNode additionalProperties = ApiTool.getAdditionalProperties(schema);
665+
if (Objects.nonNull(additionalProperties) && additionalProperties.isBoolean()) {
653666
type = TypeConstants.OBJECT;
654667
} else {
655-
final JsonNode additionalProperties = ApiTool.getAdditionalProperties(schema);
656668
if (ApiTool.hasRef(additionalProperties)) {
657669
type = MapperUtil.getPojoNameFromRef(additionalProperties, specFile, null);
658670
} else if (ApiTool.isObject(schema)) {

multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorFixtures.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,18 @@ public final class OpenApiGeneratorFixtures {
297297
.build()
298298
);
299299

300+
static final List<SpecFile> TEST_ADDITIONAL_PROPERTIES_FALSE = List.of(
301+
SpecFile
302+
.builder()
303+
.filePath("openapigenerator/testAdditionalPropertiesFalse/api-test.yml")
304+
.apiPackage("com.sngular.multifileplugin.testadditionalpropertiesFalse")
305+
.modelPackage("com.sngular.multifileplugin.testadditionalpropertiesFalse.model")
306+
.clientPackage("com.sngular.multifileplugin.testadditionalpropertiesFalse.client")
307+
.modelNameSuffix("DTO")
308+
.useLombokModelAnnotation(true)
309+
.build()
310+
);
311+
300312
static final List<SpecFile> TEST_ADDITIONAL_PROPERTIES_WITH_SCHEMA = List.of(
301313
SpecFile
302314
.builder()
@@ -1112,6 +1124,23 @@ static Function<Path, Boolean> validateAdditionalProperties() {
11121124
return path -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), null);
11131125
}
11141126

1127+
static Function<Path, Boolean> validateAdditionalPropertiesFalse() {
1128+
1129+
final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testadditionalpropertiesFalse";
1130+
1131+
final String DEFAULT_MODEL_API = "generated/com/sngular/multifileplugin/testadditionalpropertiesFalse/model";
1132+
1133+
final String COMMON_PATH = "openapigenerator/testAdditionalPropertiesFalse/";
1134+
1135+
final String ASSETS_PATH = COMMON_PATH + "assets/";
1136+
1137+
final List<String> expectedTestApiFile = List.of(ASSETS_PATH + "TestApi.java");
1138+
1139+
final List<String> expectedTestApiModelFiles = List.of(ASSETS_PATH + "TestDTO.java");
1140+
1141+
return path -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), null);
1142+
}
1143+
11151144
static Function<Path, Boolean> validateAdditionalPropertiesWithSchema() {
11161145

11171146
final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testadditionalpropertiesWithSchema";

multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ static Stream<Arguments> fileSpecToProcess() {
8989
OpenApiGeneratorFixtures.validateOneOfInResponse()),
9090
Arguments.of("testAdditionalProperties", OpenApiGeneratorFixtures.TEST_ADDITIONAL_PROPERTIES,
9191
OpenApiGeneratorFixtures.validateAdditionalProperties()),
92+
Arguments.of("testAdditionalPropertiesFalse", OpenApiGeneratorFixtures.TEST_ADDITIONAL_PROPERTIES_FALSE,
93+
OpenApiGeneratorFixtures.validateAdditionalPropertiesFalse()),
9294
Arguments.of("testAdditionalPropertiesWithSchema", OpenApiGeneratorFixtures.TEST_ADDITIONAL_PROPERTIES_WITH_SCHEMA,
9395
OpenApiGeneratorFixtures.validateAdditionalPropertiesWithSchema()),
9496
Arguments.of("testAdditionalPropertiesWithUnnamedObject", OpenApiGeneratorFixtures.TEST_ADDITIONAL_PROPERTIES_WITH_UNNAMED_OBJECT,

scs-multiapi-gradle-plugin/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ repositories {
2121
}
2222

2323
group = 'com.sngular'
24-
version = '6.3.0'
24+
version = '6.3.2'
2525

2626
def SCSMultiApiPluginGroupId = group
2727
def SCSMultiApiPluginVersion = version
@@ -31,7 +31,7 @@ dependencies {
3131
shadow localGroovy()
3232
shadow gradleApi()
3333

34-
implementation 'com.sngular:multiapi-engine:6.3.1'
34+
implementation 'com.sngular:multiapi-engine:6.3.2'
3535
testImplementation 'org.assertj:assertj-core:3.24.2'
3636
testImplementation 'com.puppycrawl.tools:checkstyle:10.12.3'
3737
testImplementation 'org.junit.platform:junit-platform-launcher:1.9.2'

scs-multiapi-maven-plugin/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.sngular</groupId>
66
<artifactId>scs-multiapi-maven-plugin</artifactId>
7-
<version>6.3.1</version>
7+
<version>6.3.2</version>
88
<packaging>maven-plugin</packaging>
99

1010
<name>AsyncApi - OpenApi Code Generator Maven Plugin</name>
@@ -271,7 +271,7 @@
271271
<dependency>
272272
<groupId>com.sngular</groupId>
273273
<artifactId>multiapi-engine</artifactId>
274-
<version>6.3.1</version>
274+
<version>6.3.2</version>
275275
</dependency>
276276
<dependency>
277277
<groupId>org.apache.maven</groupId>

0 commit comments

Comments
 (0)