Skip to content

Commit ab0f29f

Browse files
committed
Use deduction for interface on java generators
1 parent 33ef2a0 commit ab0f29f

7 files changed

Lines changed: 33 additions & 5 deletions

File tree

docs/generators/java.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
9595
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
9696
|useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, restclient, libraries| |false|
9797
|useBeanValidation|Use BeanValidation API annotations| |false|
98+
|useDeductionForOneOfInterfaces|whether to use deduction for generated oneOf interfaces| |false|
9899
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
99100
|useGzipFeature|Send gzip-encoded requests| |false|
100101
|useJackson3|Use Jackson 3 instead of Jackson 2. Supported for 'native' and 'apache-httpclient' libraries (requires Java 17+) and for Spring 'resttemplate', 'webclient', and 'restclient' libraries (require useSpringBoot4=true).| |false|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
118118
public static final String DEFAULT_TEST_FOLDER = "${project.build.directory}/generated-test-sources/openapi";
119119
public static final String GENERATE_CONSTRUCTOR_WITH_ALL_ARGS = "generateConstructorWithAllArgs";
120120
public static final String GENERATE_BUILDERS = "generateBuilders";
121+
public static final String USE_DEDUCTION_FOR_ONE_OF_INTERFACES = "useDeductionForOneOfInterfaces";
121122

122123
@Getter @Setter
123124
protected String dateLibrary = "java8";
@@ -225,6 +226,8 @@ protected enum ENUM_PROPERTY_NAMING_TYPE {MACRO_CASE, legacy, original}
225226
@Setter
226227
protected boolean useJspecify;
227228
protected JSpecifyNullableLambda jSpecifyNullableLambda;
229+
@Getter @Setter
230+
protected boolean useDeductionForOneOfInterfaces = false;
228231

229232
private Map<String, String> schemaKeyToModelNameCache = new HashMap<>();
230233

@@ -608,6 +611,7 @@ public void processOpts() {
608611
convertPropertyToBooleanAndWriteBack(USE_ONE_OF_INTERFACES, this::setUseOneOfInterfaces);
609612
convertPropertyToStringAndWriteBack(CodegenConstants.ENUM_PROPERTY_NAMING, this::setEnumPropertyNaming);
610613
convertPropertyToBooleanAndWriteBack(USE_JSPECIFY, this::setUseJspecify);
614+
convertPropertyToBooleanAndWriteBack(USE_DEDUCTION_FOR_ONE_OF_INTERFACES, this::setUseDeductionForOneOfInterfaces);
611615

612616
if (!StringUtils.isEmpty(parentGroupId) && !StringUtils.isEmpty(parentArtifactId) && !StringUtils.isEmpty(parentVersion)) {
613617
additionalProperties.put("parentOverridden", true);

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ public JavaClientCodegen() {
285285
cliOptions.add(CliOption.newBoolean(USE_SEALED_ONE_OF_INTERFACES, "Generate the oneOf interfaces as sealed interfaces. Only supported for WebClient and RestClient.", this.useSealedOneOfInterfaces));
286286
cliOptions.add(CliOption.newBoolean(USE_UNARY_INTERCEPTOR, "If true it will generate ResponseInterceptors using a UnaryOperator. This can be usefull for manipulating the request before it gets passed, for example doing your own decryption", this.useUnaryInterceptor));
287287
cliOptions.add(CliOption.newBoolean(USE_JSPECIFY, "Use Jspecify for null checks. Only supported for " + JSPECIFY_SUPPORTED_LIBRARIES, useJspecify));
288+
cliOptions.add(CliOption.newBoolean(USE_DEDUCTION_FOR_ONE_OF_INTERFACES, "whether to use deduction for generated oneOf interfaces", useDeductionForOneOfInterfaces));
288289

289290
supportedLibraries.put(JERSEY2, "HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.17.1");
290291
supportedLibraries.put(JERSEY3, "HTTP client: Jersey client 3.1.1. JSON processing: Jackson 2.17.1");

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ public class SpringCodegen extends AbstractJavaCodegen
110110
public static final String USE_SEALED = "useSealed";
111111
public static final String OPTIONAL_ACCEPT_NULLABLE = "optionalAcceptNullable";
112112
public static final String USE_SPRING_BUILT_IN_VALIDATION = "useSpringBuiltInValidation";
113-
public static final String USE_DEDUCTION_FOR_ONE_OF_INTERFACES = "useDeductionForOneOfInterfaces";
114113
public static final String SPRING_API_VERSION = "springApiVersion";
115114
public static final String USE_JACKSON_3 = "useJackson3";
116115
public static final String JACKSON2_PACKAGE = "com.fasterxml.jackson";
@@ -187,8 +186,6 @@ public enum RequestMappingMode {
187186
@Getter @Setter
188187
protected boolean useSpringBuiltInValidation = false;
189188
@Getter @Setter
190-
protected boolean useDeductionForOneOfInterfaces = false;
191-
@Getter @Setter
192189
protected boolean useJackson3 = false;
193190
@Getter @Setter
194191
protected boolean additionalNotNullAnnotations = false;
@@ -557,7 +554,6 @@ public void processOpts() {
557554
}
558555
convertPropertyToBooleanAndWriteBack(OPTIONAL_ACCEPT_NULLABLE, this::setOptionalAcceptNullable);
559556
convertPropertyToBooleanAndWriteBack(USE_SPRING_BUILT_IN_VALIDATION, this::setUseSpringBuiltInValidation);
560-
convertPropertyToBooleanAndWriteBack(USE_DEDUCTION_FOR_ONE_OF_INTERFACES, this::setUseDeductionForOneOfInterfaces);
561557

562558
additionalProperties.put("springHttpStatus", new SpringHttpStatusLambda());
563559

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{{^discriminator}}
2+
{{#jackson}}
3+
{{#useDeductionForOneOfInterfaces}}
4+
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
5+
@JsonSubTypes({
6+
{{#interfaceModels}}
7+
@JsonSubTypes.Type(value = {{classname}}.class){{^-last}}, {{/-last}}
8+
{{/interfaceModels}}
9+
})
10+
{{/useDeductionForOneOfInterfaces}}
11+
{{/jackson}}
12+
{{/discriminator}}

modules/openapi-generator/src/main/resources/Java/oneof_interface.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{{>additionalOneOfTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}}
1+
{{>additionalOneOfTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>deductionAnnotation}}{{>xmlAnnotation}}
22
{{#vendorExtensions.x-class-extra-annotation}}
33
{{{vendorExtensions.x-class-extra-annotation}}}
44
{{/vendorExtensions.x-class-extra-annotation}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4452,4 +4452,18 @@ void oneOf_issue_912() {
44524452
.recursivelyContainsWithNameAndAttributes("JsonSubTypes.Type", Map.of("value", "Source.class", "name", "\"source\""));
44534453
}
44544454

4455+
@Test
4456+
public void testUseDeductionForOneInterfaces() {
4457+
final Map<String, File> files = generateFromContract("src/test/resources/3_1/oneof_polymorphism_and_inheritance.yaml", RESTCLIENT,
4458+
Map.of(USE_ONE_OF_INTERFACES, "true", USE_DEDUCTION_FOR_ONE_OF_INTERFACES, "true"));
4459+
JavaFileAssert.assertThat(files.get("Animal.java")).fileContains("@JsonSubTypes")
4460+
.isInterface()
4461+
.assertTypeAnnotations().containsWithName("JsonSubTypes")
4462+
.recursivelyContainsWithNameAndAttributes("JsonSubTypes.Type", Map.of("value", "Dog.class"))
4463+
.recursivelyContainsWithNameAndAttributes("JsonSubTypes.Type", Map.of("value", "Cat.class"))
4464+
.containsWithNameAndAttributes("JsonTypeInfo", Map.of("use", "JsonTypeInfo.Id.DEDUCTION"));
4465+
4466+
}
4467+
4468+
44554469
}

0 commit comments

Comments
 (0)