forked from loafle/openapi-generator-original
[Protobuf] Improve oneOf Handling by Unwrapping allOf for Complex Types (#22700)
* Improve Protobuf Generator's oneOf Handling allOf Unwrapping with Complex Types * Address cubic-dev-ai comment
This commit is contained in:
@@ -442,7 +442,19 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf
|
||||
List<Schema> oneOfs = schema.getOneOf();
|
||||
List<Schema> newOneOfs = new ArrayList<>();
|
||||
for (Schema oneOf : oneOfs) {
|
||||
Schema oneOfSchema = ModelUtils.getReferencedSchema(openAPI, oneOf);
|
||||
Schema oneOfSchema = oneOf;
|
||||
if (ModelUtils.isAllOf(oneOf) && oneOf.getAllOf() != null && oneOf.getAllOf().size() == 1) {
|
||||
Object allOfObj = oneOf.getAllOf().get(0);
|
||||
if (allOfObj instanceof Schema) {
|
||||
Schema allOfItem = (Schema) allOfObj;
|
||||
if (StringUtils.isNotEmpty(allOfItem.get$ref())) {
|
||||
oneOfSchema = ModelUtils.getReferencedSchema(openAPI, allOfItem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
oneOfSchema = ModelUtils.getReferencedSchema(openAPI, oneOf);
|
||||
}
|
||||
|
||||
if (ModelUtils.isArraySchema(oneOfSchema)) {
|
||||
Schema innerSchema = generateNestedSchema(oneOfSchema, visitedSchemas);
|
||||
innerSchema.setTitle(oneOf.getTitle());
|
||||
|
||||
@@ -18,8 +18,10 @@ package org.openapitools.codegen.protobuf;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.BooleanSchema;
|
||||
import io.swagger.v3.oas.models.media.IntegerSchema;
|
||||
import io.swagger.v3.oas.models.media.MapSchema;
|
||||
import io.swagger.v3.oas.models.media.NumberSchema;
|
||||
import io.swagger.v3.oas.models.media.ObjectSchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.media.StringSchema;
|
||||
@@ -45,6 +47,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import static org.openapitools.codegen.TestUtils.createCodegenModelWrapper;
|
||||
import static org.openapitools.codegen.languages.ProtobufSchemaCodegen.USE_SIMPLIFIED_ENUM_NAMES;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
@@ -142,6 +145,64 @@ public class ProtobufSchemaCodegenTest {
|
||||
output.deleteOnExit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCodeGenWithOneOfDiscriminator31() throws IOException {
|
||||
System.setProperty("line.separator", "\n");
|
||||
|
||||
File output = Files.createTempDirectory("test").toFile();
|
||||
|
||||
final CodegenConfigurator configurator = new CodegenConfigurator()
|
||||
.setGeneratorName("protobuf-schema")
|
||||
.setInputSpec("src/test/resources/3_1/oneOf.yaml")
|
||||
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
|
||||
|
||||
final ClientOptInput clientOptInput = configurator.toClientOptInput();
|
||||
DefaultGenerator generator = new DefaultGenerator();
|
||||
List<File> files = generator.opts(clientOptInput).generate();
|
||||
|
||||
TestUtils.ensureContainsFile(files, output, "models/fruit.proto");
|
||||
|
||||
// Get the processed OpenAPI with wrapper schemas
|
||||
OpenAPI openAPI = clientOptInput.getOpenAPI();
|
||||
ProtobufSchemaCodegen codegen = new ProtobufSchemaCodegen();
|
||||
codegen.setOpenAPI(openAPI);
|
||||
codegen.processOpts();
|
||||
|
||||
Schema fruitSchema = openAPI.getComponents().getSchemas().get("fruit");
|
||||
Assert.assertNotNull(fruitSchema, "fruit schema should exist");
|
||||
|
||||
CodegenModel fruitModel = codegen.fromModel("fruit", fruitSchema);
|
||||
codegen.postProcessModels(createCodegenModelWrapper(fruitModel));
|
||||
|
||||
Assert.assertNotNull(fruitModel.oneOf, "fruit model should have oneOf items");
|
||||
Assert.assertTrue(fruitModel.oneOf.size() >= 2, "fruit model should have at least 2 oneOf items");
|
||||
|
||||
Assert.assertNotNull(fruitModel.vars, "fruit model should have vars");
|
||||
Assert.assertTrue(fruitModel.vars.size() > 0, "fruit model should have at least one var");
|
||||
|
||||
Assert.assertEquals(fruitModel.vars.size(), 3, "fruit model should have 3 vars (one for each oneOf item)");
|
||||
|
||||
for (CodegenProperty var : fruitModel.vars) {
|
||||
Assert.assertNotNull(var.name, "var name should not be null");
|
||||
Assert.assertNotNull(var.dataType, "var dataType should not be null");
|
||||
Assert.assertTrue(var.isModel, "var " + var.name + " should be a model type (isModel=" + var.isModel + ")");
|
||||
Assert.assertFalse(var.isContainer, "var should not be a container (it references a model)");
|
||||
|
||||
// Check expected properties based on discriminator title
|
||||
if (var.name.equals("apple_list")) {
|
||||
Assert.assertEquals(var.dataType, "StringArray", "apple_list should reference StringArray");
|
||||
} else if (var.name.equals("banana_map")) {
|
||||
Assert.assertEquals(var.dataType, "FloatMap", "banana_map should reference FloatMap");
|
||||
} else if (var.name.equals("orange_choice")) {
|
||||
Assert.assertEquals(var.dataType, "Orange", "orange_choice should reference Orange");
|
||||
} else {
|
||||
Assert.fail("Unexpected var name: " + var.name + ". Expected one of: apple_list, banana_map, orange_choice");
|
||||
}
|
||||
}
|
||||
|
||||
output.deleteOnExit();
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with dollar signs")
|
||||
public void modelTest() {
|
||||
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/dollar-in-names-pull14359.yaml");
|
||||
|
||||
42
modules/openapi-generator/src/test/resources/3_1/oneOf.yaml
Normal file
42
modules/openapi-generator/src/test/resources/3_1/oneOf.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
openapi: 3.1.0
|
||||
|
||||
info:
|
||||
title: fruity
|
||||
version: 0.0.1
|
||||
|
||||
paths:
|
||||
/:
|
||||
get:
|
||||
responses:
|
||||
'200':
|
||||
description: desc
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/fruit'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
fruit:
|
||||
oneOf:
|
||||
- title: appleList
|
||||
$ref: '#/components/schemas/appleArray'
|
||||
- title: bananaMap
|
||||
$ref: '#/components/schemas/bananaMap'
|
||||
- title: orangeChoice
|
||||
$ref: '#/components/schemas/orange'
|
||||
appleArray:
|
||||
type: array
|
||||
items:
|
||||
title: appleaArray
|
||||
type: string
|
||||
bananaMap:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: number
|
||||
orange:
|
||||
title: orange
|
||||
type: object
|
||||
properties:
|
||||
sweet:
|
||||
type: boolean
|
||||
Reference in New Issue
Block a user