From ac03c2fc67ff749f99c75a9d451752b08ee9378b Mon Sep 17 00:00:00 2001 From: xil Date: Sun, 30 Mar 2025 20:50:09 +0000 Subject: [PATCH 1/2] Address map under composed schema Add explanation to code block --- .../languages/ProtobufSchemaCodegen.java | 26 ++++++- .../3_0/protobuf/petstore-complex.yaml | 70 ++++++++++--------- .../.openapi-generator/FILES | 1 + .../models/dog.proto | 3 + .../models/pet.proto | 17 +++++ .../models/tag_map.proto | 22 ++++++ 6 files changed, 103 insertions(+), 36 deletions(-) create mode 100644 samples/config/petstore/protobuf-schema-config-complex/models/tag_map.proto diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java index f22cda8c54eb..2cc50d184ce6 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java @@ -397,7 +397,7 @@ private void processNestedSchemas(Schema schema, Set visitedSchemas) { if (ModelUtils.isMapSchema(schema) && ModelUtils.getAdditionalProperties(schema) != null) { Schema mapValueSchema = ModelUtils.getAdditionalProperties(schema); mapValueSchema = ModelUtils.getReferencedSchema(openAPI, mapValueSchema); - if (ModelUtils.isArraySchema(mapValueSchema) || ModelUtils.isMapSchema(mapValueSchema)) { + if (ModelUtils.isArraySchema(mapValueSchema) || (!ModelUtils.isMapSchema(mapValueSchema) && !ModelUtils.isModel(mapValueSchema))) { Schema innerSchema = generateNestedSchema(mapValueSchema, visitedSchemas); schema.setAdditionalProperties(innerSchema); @@ -405,7 +405,7 @@ private void processNestedSchemas(Schema schema, Set visitedSchemas) { } else if (ModelUtils.isArraySchema(schema) && ModelUtils.getSchemaItems(schema) != null) { Schema arrayItemSchema = ModelUtils.getSchemaItems(schema); arrayItemSchema = ModelUtils.getReferencedSchema(openAPI, arrayItemSchema); - if (ModelUtils.isMapSchema(arrayItemSchema) || ModelUtils.isArraySchema(arrayItemSchema)) { + if ((ModelUtils.isMapSchema(arrayItemSchema) && !ModelUtils.isModel(arrayItemSchema)) || ModelUtils.isArraySchema(arrayItemSchema)) { Schema innerSchema = generateNestedSchema(arrayItemSchema, visitedSchemas); schema.setItems(innerSchema); } @@ -418,7 +418,7 @@ private void processNestedSchemas(Schema schema, Set visitedSchemas) { Schema innerSchema = generateNestedSchema(oneOfSchema, visitedSchemas); innerSchema.setTitle(oneOf.getTitle()); newOneOfs.add(innerSchema); - } else if (ModelUtils.isMapSchema(oneOfSchema)) { + } else if (ModelUtils.isMapSchema(oneOfSchema) && !ModelUtils.isModel(oneOfSchema)) { Schema innerSchema = generateNestedSchema(oneOfSchema, visitedSchemas); innerSchema.setTitle(oneOf.getTitle()); newOneOfs.add(innerSchema); @@ -1053,4 +1053,24 @@ public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.PROTOBUF; } + @Override + protected void addProperties(Map properties, List required, Schema schema, Set visitedSchemas){ + super.addProperties(properties, required, schema, visitedSchemas); + if(schema.getAdditionalProperties() != null) { + String addtionalPropertiesName = "default_map"; + if(schema.getTitle() != null) { + addtionalPropertiesName = schema.getTitle(); + } else { + Schema additionalProperties = ModelUtils.getAdditionalProperties(schema); + if (additionalProperties.getTitle() != null) { + addtionalPropertiesName = additionalProperties.getTitle(); + } else if (additionalProperties.get$ref() != null) { + String ref = ModelUtils.getSimpleRef(additionalProperties.get$ref()); + addtionalPropertiesName = toVarName(toModelName(ref)); + } + } + properties.put(addtionalPropertiesName, schema); + } + } + } diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf/petstore-complex.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf/petstore-complex.yaml index 95b6dd973a06..9162aa7699bb 100644 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf/petstore-complex.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf/petstore-complex.yaml @@ -34,13 +34,22 @@ externalDocs: components: schemas: Dog: - type: object - properties: - bark: - type: boolean - breed: - type: string - enum: [ Dingo, Husky, Retriever, Shepherd ] + allOf: + - type: object + properties: + bark: + type: boolean + breed: + type: string + enum: [Dingo, Husky, Retriever, Shepherd] + - type: object + propertyNames: + title: field + type: string + additionalProperties: + title: pet + $ref: '#/components/schemas/Pet' + minProperties: 1 Cat: type: object properties: @@ -100,31 +109,26 @@ components: format: int64 category: $ref: '#/components/schemas/Category' - name: - type: string - photoUrls: - type: array - xml: - name: photoUrl - wrapped: true - items: + name: type: string - tags: - type: array - xml: - name: tag - wrapped: true - items: + photoUrls: type: array - additionalProperties: - $ref: '#/components/schemas/Tag' - status: - type: string - description: pet status in the store - deprecated: true - enum: - - available - - pending - - sold - xml: - name: Pet \ No newline at end of file + xml: + name: photoUrl + wrapped: true + items: + type: string + tags: + type: array + items: + type: object + additionalProperties: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + deprecated: true + enum: + - available + - pending + - sold \ No newline at end of file diff --git a/samples/config/petstore/protobuf-schema-config-complex/.openapi-generator/FILES b/samples/config/petstore/protobuf-schema-config-complex/.openapi-generator/FILES index ab4367dbd511..8f82345a5158 100644 --- a/samples/config/petstore/protobuf-schema-config-complex/.openapi-generator/FILES +++ b/samples/config/petstore/protobuf-schema-config-complex/.openapi-generator/FILES @@ -6,5 +6,6 @@ models/pet.proto models/string_array.proto models/string_map.proto models/tag.proto +models/tag_map.proto models/tag_name.proto services/default_service.proto diff --git a/samples/config/petstore/protobuf-schema-config-complex/models/dog.proto b/samples/config/petstore/protobuf-schema-config-complex/models/dog.proto index e9849273a8b5..31945cde0be3 100644 --- a/samples/config/petstore/protobuf-schema-config-complex/models/dog.proto +++ b/samples/config/petstore/protobuf-schema-config-complex/models/dog.proto @@ -12,6 +12,7 @@ syntax = "proto3"; package petstore; +import public "models/pet.proto"; message Dog { @@ -27,5 +28,7 @@ message Dog { Breed breed = 2; + map pet = 3; + } diff --git a/samples/config/petstore/protobuf-schema-config-complex/models/pet.proto b/samples/config/petstore/protobuf-schema-config-complex/models/pet.proto index aba89d8b7018..4538eb9153be 100644 --- a/samples/config/petstore/protobuf-schema-config-complex/models/pet.proto +++ b/samples/config/petstore/protobuf-schema-config-complex/models/pet.proto @@ -13,6 +13,7 @@ syntax = "proto3"; package petstore; import public "models/category.proto"; +import public "models/tag_map.proto"; message Pet { @@ -20,5 +21,21 @@ message Pet { Category category = 2; + string name = 3; + + repeated string photo_urls = 4 [json_name="photoUrls"]; + + repeated TagMap tags = 5; + + // pet status in the store + enum Status { + STATUS_UNSPECIFIED = 0; + STATUS_AVAILABLE = 1; + STATUS_PENDING = 2; + STATUS_SOLD = 3; + } + + Status status = 6; + } diff --git a/samples/config/petstore/protobuf-schema-config-complex/models/tag_map.proto b/samples/config/petstore/protobuf-schema-config-complex/models/tag_map.proto new file mode 100644 index 000000000000..68e47eef5829 --- /dev/null +++ b/samples/config/petstore/protobuf-schema-config-complex/models/tag_map.proto @@ -0,0 +1,22 @@ +/* + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + + Generated by OpenAPI Generator: https://openapi-generator.tech +*/ + +syntax = "proto3"; + +package petstore; + +import public "models/tag.proto"; + +message TagMap { + + map tag_map = 1; + +} + From 13dafa9f2cf3ae086ff9a1771c0247d4d8b720b6 Mon Sep 17 00:00:00 2001 From: xil Date: Mon, 7 Apr 2025 10:52:57 -0700 Subject: [PATCH 2/2] add comment to explain the code block --- .../languages/ProtobufSchemaCodegen.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java index 2cc50d184ce6..a5fa241af139 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java @@ -397,7 +397,7 @@ private void processNestedSchemas(Schema schema, Set visitedSchemas) { if (ModelUtils.isMapSchema(schema) && ModelUtils.getAdditionalProperties(schema) != null) { Schema mapValueSchema = ModelUtils.getAdditionalProperties(schema); mapValueSchema = ModelUtils.getReferencedSchema(openAPI, mapValueSchema); - if (ModelUtils.isArraySchema(mapValueSchema) || (!ModelUtils.isMapSchema(mapValueSchema) && !ModelUtils.isModel(mapValueSchema))) { + if (ModelUtils.isArraySchema(mapValueSchema) || (ModelUtils.isMapSchema(mapValueSchema) && !ModelUtils.isModel(mapValueSchema))) { Schema innerSchema = generateNestedSchema(mapValueSchema, visitedSchemas); schema.setAdditionalProperties(innerSchema); @@ -1053,6 +1053,21 @@ public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.PROTOBUF; } + +/** + * Handles additionalProperties defined in composed schemas (e.g., allOf) by injecting into the model's properties. + * Example: + * components: + * schemas: + * Dog: + * allOf: + * - $ref: '#/components/schemas/DogBase' + * - type: object + * additionalProperties: + * title: pet + * $ref: '#/components/schemas/Pet' + * In this case, the second allOf that defines a map with string keys and Pet values will be part of model's property. + */ @Override protected void addProperties(Map properties, List required, Schema schema, Set visitedSchemas){ super.addProperties(properties, required, schema, visitedSchemas); @@ -1072,5 +1087,4 @@ protected void addProperties(Map properties, List requir properties.put(addtionalPropertiesName, schema); } } - }