[java][spring] Add option optionalAcceptNullable to accept null values (#20746)

* add option to rollback accept null values

* update doc

* update tests
This commit is contained in:
William Cheng 2025-02-27 17:21:51 +08:00 committed by GitHub
parent fc00a663e1
commit 1c3eade94d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 55 additions and 2 deletions

View File

@ -12,3 +12,4 @@ additionalProperties:
useSwaggerUI: "false"
hideGenerationTimestamp: "true"
documentationProvider: none
#optionalAcceptNullable: "false" # default to true

View File

@ -73,6 +73,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|licenseUrl|The URL of the license| |http://unlicense.org|
|modelPackage|package for generated models| |org.openapitools.model|
|openApiNullable|Enable OpenAPI Jackson Nullable library. Not supported by `microprofile` library.| |true|
|optionalAcceptNullable|Use `ofNullable` instead of just `of` to accept null values when using Optional.| |true|
|parentArtifactId|parent artifactId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentVersion|parent version in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|

View File

@ -66,6 +66,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|licenseUrl|The URL of the license| |http://unlicense.org|
|modelPackage|package for generated models| |org.openapitools.model|
|openApiNullable|Enable OpenAPI Jackson Nullable library. Not supported by `microprofile` library.| |true|
|optionalAcceptNullable|Use `ofNullable` instead of just `of` to accept null values when using Optional.| |true|
|parentArtifactId|parent artifactId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentVersion|parent version in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|

View File

@ -114,6 +114,7 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String USE_REQUEST_MAPPING_ON_CONTROLLER = "useRequestMappingOnController";
public static final String USE_REQUEST_MAPPING_ON_INTERFACE = "useRequestMappingOnInterface";
public static final String USE_SEALED = "useSealed";
public static final String OPTIONAL_ACCEPT_NULLABLE = "optionalAcceptNullable";
@Getter public enum RequestMappingMode {
api_interface("Generate the @RequestMapping annotation on the generated Api Interface."),
@ -167,6 +168,8 @@ public class SpringCodegen extends AbstractJavaCodegen
protected boolean generatedConstructorWithRequiredArgs = true;
@Getter @Setter
protected RequestMappingMode requestMappingMode = RequestMappingMode.controller;
@Getter @Setter
protected boolean optionalAcceptNullable = true;
public SpringCodegen() {
super();
@ -271,6 +274,9 @@ public class SpringCodegen extends AbstractJavaCodegen
"Whether to generate constructors with required args for models",
generatedConstructorWithRequiredArgs));
cliOptions.add(new CliOption(RESOURCE_FOLDER, RESOURCE_FOLDER_DESC).defaultValue(this.getResourceFolder()));
cliOptions.add(CliOption.newBoolean(OPTIONAL_ACCEPT_NULLABLE,
"Use `ofNullable` instead of just `of` to accept null values when using Optional.",
optionalAcceptNullable));
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
supportedLibraries.put(SPRING_CLOUD_LIBRARY,
@ -434,6 +440,8 @@ public class SpringCodegen extends AbstractJavaCodegen
convertPropertyToBooleanAndWriteBack(UNHANDLED_EXCEPTION_HANDLING, this::setUnhandledException);
convertPropertyToBooleanAndWriteBack(USE_RESPONSE_ENTITY, this::setUseResponseEntity);
convertPropertyToBooleanAndWriteBack(OPTIONAL_ACCEPT_NULLABLE, this::setOptionalAcceptNullable);
additionalProperties.put("springHttpStatus", new SpringHttpStatusLambda());
convertPropertyToBooleanAndWriteBack(USE_ENUM_CASE_INSENSITIVE, this::setUseEnumCaseInsensitive);

View File

@ -156,7 +156,7 @@ public {{>sealed}}class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}
{{! begin feature: fluent setter methods }}
public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
{{#openApiNullable}}
this.{{name}} = {{#isNullable}}JsonNullable.of({{/isNullable}}{{#useOptional}}{{^required}}{{^isNullable}}{{^isContainer}}Optional.ofNullable({{/isContainer}}{{/isNullable}}{{/required}}{{/useOptional}}{{name}}{{#isNullable}}){{/isNullable}}{{#useOptional}}{{^required}}{{^isNullable}}{{^isContainer}}){{/isContainer}}{{/isNullable}}{{/required}}{{/useOptional}};
this.{{name}} = {{#isNullable}}JsonNullable.of({{/isNullable}}{{#useOptional}}{{^required}}{{^isNullable}}{{^isContainer}}Optional.of{{#optionalAcceptNullable}}Nullable{{/optionalAcceptNullable}}({{/isContainer}}{{/isNullable}}{{/required}}{{/useOptional}}{{name}}{{#isNullable}}){{/isNullable}}{{#useOptional}}{{^required}}{{^isNullable}}{{^isContainer}}){{/isContainer}}{{/isNullable}}{{/required}}{{/useOptional}};
{{/openApiNullable}}
{{^openApiNullable}}
this.{{name}} = {{name}};

View File

@ -5324,4 +5324,46 @@ public class SpringCodegenTest {
" @Nullable List<String> nullableContainer)"
);
}
}
@Test
public void shouldNotAcceptNullValues() throws IOException {
SpringCodegen codegen = new SpringCodegen();
codegen.setLibrary(SPRING_BOOT);
codegen.setUseSpringBoot3(true);
codegen.setUseOptional(true);
codegen.setOptionalAcceptNullable(false);
Map<String, File> files = generateFiles(codegen, "src/test/resources/3_0/petstore.yaml");
var file = files.get("Category.java");
JavaFileAssert.assertThat(file)
.fileContains(
"this.name = Optional.of(name);"
);
JavaFileAssert.assertThat(file)
.fileDoesNotContain(
"this.name = Optional.ofNullable(name);"
);
}
@Test
public void shouldAcceptNullValues() throws IOException {
SpringCodegen codegen = new SpringCodegen();
codegen.setLibrary(SPRING_BOOT);
codegen.setUseSpringBoot3(true);
codegen.setUseOptional(true);
//codegen.setOptionalAcceptNullable(true); // default to true
Map<String, File> files = generateFiles(codegen, "src/test/resources/3_0/petstore.yaml");
var file = files.get("Category.java");
JavaFileAssert.assertThat(file)
.fileContains(
"this.name = Optional.ofNullable(name);"
);
JavaFileAssert.assertThat(file)
.fileDoesNotContain(
"this.name = Optional.of(name);"
);
}
}