Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added feature to set schema mappings when generation clients. #846

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public enum ConfigName {
ADDITIONAL_API_TYPE_ANNOTATIONS("additional-api-type-annotations"),
TYPE_MAPPINGS("type-mappings"),
IMPORT_MAPPINGS("import-mappings"),
SCHEMA_MAPPINGS("schema-mappings"),
NORMALIZER("open-api-normalizer"),
RETURN_RESPONSE("return-response"),
ENABLE_SECURITY_GENERATION("enable-security-generation"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public class CommonItemConfig {
@ConfigItem(name = "import-mappings")
public Map<String, String> importMappings;

/**
* Schema Mapping is an OpenAPI Generator configuration specifying which Java types (the values) should be
* imported when a given schema type (the keys of this map) is used
*/
@ConfigItem(name = "schema-mappings")
public Map<String, String> schemaMappings;

/**
* The specified annotations will be added to the generated model files
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ protected void generate(OpenApiGeneratorOptions options) {
getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.IMPORT_MAPPINGS, String.class, String.class)
.ifPresent(generator::withImportMappings);

getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.SCHEMA_MAPPINGS, String.class, String.class)
.ifPresent(generator::withSchemaMappings);

getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.NORMALIZER, String.class, String.class)
.ifPresent(generator::withOpenApiNormalizer);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ public OpenApiClientGeneratorWrapper withImportMappings(final Map<String, String
return this;
}

public OpenApiClientGeneratorWrapper withSchemaMappings(final Map<String, String> typeMappings) {
typeMappings.forEach(configurator::addSchemaMapping);
return this;
}

public OpenApiClientGeneratorWrapper withOpenApiNormalizer(final Map<String, String> openApiNormalizer) {
configurator.setOpenapiNormalizer(openApiNormalizer);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ components:
UserId:
type: string
format: uuid
YearMonth:
type: object
properties:
year:
format: int32
type: integer
month:
format: int32
type: integer
prolepticMonth:
format: int64
type: integer
monthValue:
format: int32
type: integer
leapYear:
type: boolean

MultipartRequestBody:
type: object
Expand All @@ -46,5 +63,7 @@ components:
$ref: '#/components/schemas/SomeDateTime'
binaryStringFile:
$ref: '#/components/schemas/BinaryStringFile'
yearMonth:
$ref: '#/components/schemas/YearMonth'


Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.type-mappings.UUID=String
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.type-mappings.File=InputStream
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.import-mappings.File=java.io.InputStream
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.schema-mappings.YearMonth=java.time.YearMonth
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.base-package=org.acme.openapi.typemapping
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.additional-api-type-annotations=@org.eclipse.microprofile.rest.client.annotation.RegisterProvider(io.quarkiverse.openapi.generator.it.type.mapping.OffsetDateTimeParamConverterProvider.class)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.YearMonth;
import java.time.ZoneOffset;

import jakarta.inject.Inject;
Expand Down Expand Up @@ -41,10 +42,12 @@ class TypeAndImportMappingRestEasyClassicTest {
public void canMapTypesAndImportToDifferentValues() {
final String testUuid = "00112233-4455-6677-8899-aabbccddeeff";
final InputStream testFile = new ByteArrayInputStream("Content of the file".getBytes(StandardCharsets.UTF_8));
final YearMonth testYearMonth = YearMonth.parse("2024-06");

TypeMappingApi.PostTheDataMultipartForm requestBody = new TypeMappingApi.PostTheDataMultipartForm();
requestBody.id = testUuid; // String instead of UUID
requestBody.binaryStringFile = testFile; // InputStream instead of File
requestBody.yearMonth = testYearMonth; // YearMonth instead of String
// dateTime remains OffsetDateTime (as is default)
requestBody.dateTime = OffsetDateTime.of(2000, 2, 13, 4, 5, 6, 0, ZoneOffset.UTC);

Expand All @@ -63,6 +66,10 @@ public void canMapTypesAndImportToDifferentValues() {
.withName("binaryStringFile")
.withHeader("Content-Disposition", containing("filename="))
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.APPLICATION_OCTET_STREAM))
.withBody(equalTo("Content of the file")).build()));
.withBody(equalTo("Content of the file")).build())
.withRequestBodyPart(new MultipartValuePatternBuilder()
.withName("yearMonth")
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.APPLICATION_JSON))
.withBody(equalTo("\"2024-06\"")).build()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.YearMonth;
import java.time.ZoneOffset;

import jakarta.inject.Inject;
Expand Down Expand Up @@ -37,10 +38,12 @@ public class TypeAndImportMappingRestEasyReactiveTest {
public void canMapTypesAndImportToDifferentValues() {
final String testUuid = "00112233-4455-6677-8899-aabbccddeeff";
final InputStream testFile = new ByteArrayInputStream("Content of the file".getBytes(StandardCharsets.UTF_8));
final YearMonth testYearMonth = YearMonth.parse("2024-06");

TypeMappingApi.PostTheDataMultipartForm requestBody = new TypeMappingApi.PostTheDataMultipartForm();
requestBody.id = testUuid; // String instead of UUID
requestBody.binaryStringFile = testFile; // InputStream instead of File
requestBody.yearMonth = testYearMonth; // YearMonth instead of String
// dateTime remains OffsetDateTime (as is default)
requestBody.dateTime = OffsetDateTime.of(2000, 2, 13, 4, 5, 6, 0, ZoneOffset.UTC);

Expand All @@ -52,6 +55,12 @@ public void canMapTypesAndImportToDifferentValues() {
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.TEXT_PLAIN + "; charset=UTF-8"))
.withBody(equalTo(testUuid)).build()));

typeMappingServer.verify(postRequestedFor(urlEqualTo("/type-mapping"))
.withRequestBodyPart(new MultipartValuePatternBuilder()
.withName("yearMonth")
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.APPLICATION_JSON))
.withBody(equalTo("\"2024-06\"")).build()));

typeMappingServer.verify(postRequestedFor(urlEqualTo("/type-mapping"))
.withRequestBodyPart(new MultipartValuePatternBuilder()
.withName("dateTime")
Expand Down
7 changes: 5 additions & 2 deletions docs/modules/ROOT/pages/client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ See the module `integration-tests/register-provider` for an example of how to us

Use the property key `quarkus.openapi-generator.codegen.validateSpec=false` to disable validating the input specification file before code generation. By default, invalid specifications will result in an error.

== Type and import mappings
== Type, schema and import mappings

It's possible to remap types in the generated files. For example, instead of a `File` you can configure the code generator to use `InputStream` for all file upload parts of multipart request, or you could change all `UUID` types to `String`. You can configure this in your `application.properties` using the following configuration keys:

Expand All @@ -129,6 +129,9 @@ It's possible to remap types in the generated files. For example, instead of a `
|Import Mapping
|`quarkus.openapi-generator.codegen.spec.[filename].import-mappings.[type]`
|`quarkus.openapi-generator.codegen.spec.my_spec_yml.import-mappings.File=java.io.InputStream` will replace the default `import java.io.File` with `import java.io.InputStream`
|Schema Mapping
|`quarkus.openapi-generator.codegen.spec.[filename].schema-mappings.[type]`
|`quarkus.openapi-generator.codegen.spec.my_spec_yml.schema-mappings.YearMonth=java.time.YearMonth` will use `java.time.YearMonth` as type for all schemas of the chosen type in the file.
|===

Note that these configuration properties are maps. For the type-mapping the keys are OAS data types and the values are Java types.
Expand All @@ -141,7 +144,7 @@ quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.DateTime=Instan
quarkus.openapi-generator.codegen.spec.my_spec_yml.import-mappings.Instant=java.time.Instant
----

It's also possible to only use a type mapping with a fully qualified name, for instance `quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.File=java.io.InputStream`. For more information and a list of all types see the OpenAPI generator documentation on https://openapi-generator.tech/docs/usage/#type-mappings-and-import-mappings[Type Mappings and Import Mappings].
It's also possible to only use a type mapping with a fully qualified name, for instance `quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.File=java.io.InputStream`. For more information and a list of all types see the OpenAPI generator documentation on https://openapi-generator.tech/docs/usage/#type-mappings-and-import-mappings[Type Mappings and Import Mappings] and https://openapi-generator.tech/docs/customization#schema-mapping[Schema mapping].

See the module https://github.com/quarkiverse/quarkus-openapi-generator/tree/main/integration-tests/type-mapping[type-mapping] for an example of how to use this feature.

Expand Down