From 7c47980db228db217469faf55088de88c144f86b Mon Sep 17 00:00:00 2001 From: Jan Skrasek Date: Thu, 26 Mar 2026 15:09:45 +0100 Subject: [PATCH] fix discriminator model lookup when used with model name suffix --- .../codegen/CodegenDiscriminator.java | 11 ++++- .../openapitools/codegen/DefaultCodegen.java | 11 ++--- .../codegen/DefaultCodegenTest.java | 41 +++++++++++++++++++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java index 753c63e3fc8e..c7cdf3e1187a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java @@ -76,18 +76,27 @@ public static class MappedModel implements Comparable { // is converted to a sanitized, internal representation within codegen. @Getter @Setter private String modelName; + // The raw schema name as it appears in the OAS document, before any + // modelNamePrefix/Suffix transformation. + @Getter + private String schemaName; @Getter @Setter private CodegenModel model; private final boolean explicitMapping; - public MappedModel(String mappingName, String modelName, boolean explicitMapping) { + public MappedModel(String mappingName, String modelName, String schemaName, boolean explicitMapping) { this.mappingName = mappingName; this.modelName = modelName; + this.schemaName = schemaName; this.explicitMapping = explicitMapping; } + public MappedModel(String mappingName, String modelName, boolean explicitMapping) { + this(mappingName, modelName, null, explicitMapping); + } + public boolean isExplicitMapping() { return explicitMapping; } 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 1ff331cbe6dd..efacc311118f 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 @@ -507,7 +507,8 @@ public Map postProcessAllModels(Map objs) // add the model to the discriminator's mapping so templates have access to more than just the string to string mapping if (model.discriminator != null && model.discriminator.getMappedModels() != null) { for (CodegenDiscriminator.MappedModel mappedModel : model.discriminator.getMappedModels()) { - CodegenModel mappedCodegenModel = ModelUtils.getModelByName(mappedModel.getModelName(), objs); + String lookupName = mappedModel.getSchemaName() != null ? mappedModel.getSchemaName() : mappedModel.getModelName(); + CodegenModel mappedCodegenModel = ModelUtils.getModelByName(lookupName, objs); mappedModel.setModel(mappedCodegenModel); } } @@ -3574,7 +3575,7 @@ protected List getOneOfAnyOfDescendants(String composedSchemaName, once(LOGGER).warn("'{}' defines discriminator '{}', but the referenced schema '{}' is incorrect. {}", composedSchemaName, discPropName, modelName, msgSuffix); } - MappedModel mm = new MappedModel(modelName, toModelName(modelName)); + MappedModel mm = new MappedModel(modelName, toModelName(modelName), modelName, false); descendentSchemas.add(mm); Schema cs = ModelUtils.getSchema(openAPI, modelName); if (cs == null) { // cannot lookup the model based on the name @@ -3583,7 +3584,7 @@ protected List getOneOfAnyOfDescendants(String composedSchemaName, Map vendorExtensions = cs.getExtensions(); if (vendorExtensions != null && !vendorExtensions.isEmpty() && vendorExtensions.containsKey(X_DISCRIMINATOR_VALUE)) { String xDiscriminatorValue = (String) vendorExtensions.get(X_DISCRIMINATOR_VALUE); - mm = new MappedModel(xDiscriminatorValue, toModelName(modelName), true); + mm = new MappedModel(xDiscriminatorValue, toModelName(modelName), modelName, true); descendentSchemas.add(mm); } } @@ -3641,7 +3642,7 @@ protected List getAllOfDescendants(String thisSchemaName) { .map(ve -> ve.get(X_DISCRIMINATOR_VALUE)) .map(discriminatorValue -> (String) discriminatorValue) .orElse(currentSchemaName); - MappedModel mm = new MappedModel(mappingName, toModelName(currentSchemaName), !mappingName.equals(currentSchemaName)); + MappedModel mm = new MappedModel(mappingName, toModelName(currentSchemaName), currentSchemaName, !mappingName.equals(currentSchemaName)); descendentSchemas.add(mm); } return descendentSchemas; @@ -3687,7 +3688,7 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch } else { name = e.getValue(); } - uniqueDescendants.add(new MappedModel(e.getKey(), toModelName(name), true)); + uniqueDescendants.add(new MappedModel(e.getKey(), toModelName(name), name, true)); } } 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 32eee9f1969a..1f0e4a8f8fc6 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 @@ -1680,6 +1680,47 @@ public void testComposedSchemaOneOfDiscriminatorMapPreAndPostFix() { assertThat(cm.discriminator.getPropertyType()).isEqualTo("TransferFruitTypeEnumDto"); } + @Test + public void testDiscriminatorMappedModelWithModelNameSuffix() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/oneOfDiscriminator.yaml"); + DefaultCodegen codegen = new DefaultCodegen(); + codegen.setLegacyDiscriminatorBehavior(false); + codegen.setOpenAPI(openAPI); + codegen.setModelNameSuffix("Dto"); + + // Build allProcessedModels map keyed by raw schema name (as DefaultGenerator does) + Map allProcessedModels = new TreeMap<>(); + String[] schemaNames = {"FruitReqDisc", "AppleReqDisc", "BananaReqDisc"}; + for (String name : schemaNames) { + Schema schema = openAPI.getComponents().getSchemas().get(name); + CodegenModel cm = codegen.fromModel(name, schema); + ModelMap mo = new ModelMap(); + mo.setModel(cm); + ModelsMap models = new ModelsMap(); + models.setModels(Collections.singletonList(mo)); + allProcessedModels.put(name, models); + } + + // Verify schemaName is stored and differs from modelName + CodegenModel fruitModel = ModelUtils.getModelByName("FruitReqDisc", allProcessedModels); + assertNotNull(fruitModel.discriminator); + for (CodegenDiscriminator.MappedModel mm : fruitModel.discriminator.getMappedModels()) { + assertNotNull(mm.getSchemaName(), + "MappedModel.getSchemaName() should not be null for " + mm.getModelName()); + assertNotEquals(mm.getSchemaName(), mm.getModelName(), + "schemaName should differ from modelName when modelNameSuffix is set"); + } + + // Verify postProcessAllModels resolves MappedModel.model via schemaName + Map result = codegen.postProcessAllModels(allProcessedModels); + fruitModel = ModelUtils.getModelByName("FruitReqDisc", result); + for (CodegenDiscriminator.MappedModel mm : fruitModel.discriminator.getMappedModels()) { + assertNotNull(mm.getModel(), + "MappedModel.getModel() should not be null for " + mm.getModelName() + + " (mappingName=" + mm.getMappingName() + ")"); + } + } + @Test public void testComposedSchemaMyPetsOneOfDiscriminatorMap() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/allOf_composition_discriminator.yaml");