Skip to content

Commit 8a3c101

Browse files
committed
feature(jackson3) add jackson3 support for spring generator
* add 'useJackson3' option * add 'useSpringBoot4' option * add support for RestClient in spring-http-interfaces * add 'jacksonPackage' template variable set from useJackson3 option See #22294
1 parent a973d91 commit 8a3c101

File tree

35 files changed

+811
-102
lines changed

35 files changed

+811
-102
lines changed

docs/generators/java-camel.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
106106
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
107107
|useFeignClientContextId|Whether to generate Feign client with contextId parameter.| |true|
108108
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
109+
|useJackson3|Set it in order to use jackson 3 dependencies (only allowed when `useSpringBoot4` is set and incompatible with `openApiNullable`).| |false|
109110
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
110111
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |true|
111112
|useOptional|Use Optional container for optional parameters| |false|
112113
|useResponseEntity|Use the `ResponseEntity` type to wrap return values of generated API methods. If disabled, method are annotated using a `@ResponseStatus` annotation, which has the status of the first response declared in the Api definition| |true|
113114
|useSealed|Whether to generate sealed model interfaces and classes| |false|
114115
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot ≥ 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
116+
|useSpringBoot4|Generate code and provide dependencies for use with Spring Boot 4.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
115117
|useSpringBuiltInValidation|Disable `@Validated` at the class level when using built-in validation.| |false|
116118
|useSpringController|Annotate the generated API as a Spring Controller| |false|
117119
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|

docs/generators/spring.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
9999
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
100100
|useFeignClientContextId|Whether to generate Feign client with contextId parameter.| |true|
101101
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
102+
|useJackson3|Set it in order to use jackson 3 dependencies (only allowed when `useSpringBoot4` is set and incompatible with `openApiNullable`).| |false|
102103
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
103104
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |true|
104105
|useOptional|Use Optional container for optional parameters| |false|
105106
|useResponseEntity|Use the `ResponseEntity` type to wrap return values of generated API methods. If disabled, method are annotated using a `@ResponseStatus` annotation, which has the status of the first response declared in the Api definition| |true|
106107
|useSealed|Whether to generate sealed model interfaces and classes| |false|
107108
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot ≥ 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
109+
|useSpringBoot4|Generate code and provide dependencies for use with Spring Boot 4.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
108110
|useSpringBuiltInValidation|Disable `@Validated` at the class level when using built-in validation.| |false|
109111
|useSpringController|Annotate the generated API as a Spring Controller| |false|
110112
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|

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

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public class SpringCodegen extends AbstractJavaCodegen
9393
public static final String GENERATE_GENERIC_RESPONSE_ENTITY = "generateGenericResponseEntity";
9494
public static final String USE_ENUM_CASE_INSENSITIVE = "useEnumCaseInsensitive";
9595
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
96+
public static final String USE_SPRING_BOOT4 = "useSpringBoot4";
9697
public static final String REQUEST_MAPPING_OPTION = "requestMappingMode";
9798
public static final String USE_REQUEST_MAPPING_ON_CONTROLLER = "useRequestMappingOnController";
9899
public static final String USE_REQUEST_MAPPING_ON_INTERFACE = "useRequestMappingOnInterface";
@@ -101,6 +102,10 @@ public class SpringCodegen extends AbstractJavaCodegen
101102
public static final String USE_SPRING_BUILT_IN_VALIDATION = "useSpringBuiltInValidation";
102103
public static final String USE_DEDUCTION_FOR_ONE_OF_INTERFACES = "useDeductionForOneOfInterfaces";
103104
public static final String SPRING_API_VERSION = "springApiVersion";
105+
public static final String USE_JACKSON_3 = "useJackson3";
106+
public static final String JACKSON2_PACKAGE = "com.fasterxml.jackson";
107+
public static final String JACKSON3_PACKAGE = "tools.jackson";
108+
public static final String JACKSON_PACKAGE = "jacksonPackage";
104109

105110
@Getter
106111
public enum RequestMappingMode {
@@ -154,6 +159,8 @@ public enum RequestMappingMode {
154159
@Setter protected boolean useEnumCaseInsensitive = false;
155160
@Getter @Setter
156161
protected boolean useSpringBoot3 = false;
162+
@Getter @Setter
163+
protected boolean useSpringBoot4 = false;
157164
protected boolean generatedConstructorWithRequiredArgs = true;
158165
@Getter @Setter
159166
protected RequestMappingMode requestMappingMode = RequestMappingMode.controller;
@@ -163,6 +170,8 @@ public enum RequestMappingMode {
163170
protected boolean useSpringBuiltInValidation = false;
164171
@Getter @Setter
165172
protected boolean useDeductionForOneOfInterfaces = false;
173+
@Getter @Setter
174+
protected boolean useJackson3 = false;
166175

167176
public SpringCodegen() {
168177
super();
@@ -278,6 +287,10 @@ public SpringCodegen() {
278287
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3,
279288
"Generate code and provide dependencies for use with Spring Boot ≥ 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.",
280289
useSpringBoot3));
290+
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT4,
291+
"Generate code and provide dependencies for use with Spring Boot 4.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.",
292+
useSpringBoot4));
293+
cliOptions.add(CliOption.newBoolean(USE_JACKSON_3, "Set it in order to use jackson 3 dependencies (only allowed when `" + USE_SPRING_BOOT4 + "` is set and incompatible with `"+OPENAPI_NULLABLE+"`).", useJackson3));
281294
cliOptions.add(CliOption.newBoolean(GENERATE_CONSTRUCTOR_WITH_REQUIRED_ARGS,
282295
"Whether to generate constructors with required args for models",
283296
generatedConstructorWithRequiredArgs));
@@ -460,8 +473,13 @@ public void processOpts() {
460473
additionalProperties.put("springHttpStatus", new SpringHttpStatusLambda());
461474

462475
convertPropertyToBooleanAndWriteBack(USE_ENUM_CASE_INSENSITIVE, this::setUseEnumCaseInsensitive);
476+
convertPropertyToBooleanAndWriteBack(USE_JACKSON_3, this::setUseJackson3);
463477
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT3, this::setUseSpringBoot3);
464-
if (isUseSpringBoot3()) {
478+
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT4, this::setUseSpringBoot4);
479+
if(isUseSpringBoot3() && isUseSpringBoot4()){
480+
throw new IllegalArgumentException("Choose between spring boot 3 and spring boot 4");
481+
}
482+
if (isUseSpringBoot3() || isUseSpringBoot4()) {
465483
if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) {
466484
throw new IllegalArgumentException(DocumentationProvider.SPRINGFOX.getPropertyName() + " is not supported with Spring Boot > 3.x");
467485
}
@@ -471,15 +489,30 @@ public void processOpts() {
471489
useJakartaEe = true;
472490
applyJakartaPackage();
473491
}
492+
if(isUseJackson3() && !isUseSpringBoot4()){
493+
throw new IllegalArgumentException("useJackson3 is only available with Spring Boot > 4.x");
494+
}
495+
if(isUseJackson3() && isOpenApiNullable()){
496+
throw new IllegalArgumentException("openApiNullable cannot be set with useJackson3");
497+
}
498+
if(this.useJackson3){
499+
this.applyJackson3Package();
500+
} else {
501+
this.applyJackson2Package();
502+
}
474503
convertPropertyToStringAndWriteBack(RESOURCE_FOLDER, this::setResourceFolder);
475504

505+
506+
// override parent one
507+
importMapping.put("JsonDeserialize", (useJackson3 ? JACKSON3_PACKAGE : JACKSON2_PACKAGE) + ".databind.annotation.JsonDeserialize");
508+
476509
typeMapping.put("file", "org.springframework.core.io.Resource");
477510
importMapping.put("Nullable", "org.springframework.lang.Nullable");
478511
importMapping.put("org.springframework.core.io.Resource", "org.springframework.core.io.Resource");
479512
importMapping.put("DateTimeFormat", "org.springframework.format.annotation.DateTimeFormat");
480513
importMapping.put("ApiIgnore", "springfox.documentation.annotations.ApiIgnore");
481514
importMapping.put("ParameterObject", "org.springdoc.api.annotations.ParameterObject");
482-
if (isUseSpringBoot3()) {
515+
if (isUseSpringBoot3() || isUseSpringBoot4()) {
483516
importMapping.put("ParameterObject", "org.springdoc.core.annotations.ParameterObject");
484517
}
485518

@@ -488,7 +521,9 @@ public void processOpts() {
488521
additionalProperties.put("delegate-method", true);
489522
}
490523

491-
if (isUseSpringBoot3()) {
524+
if (isUseSpringBoot4()) {
525+
supportingFiles.add(new SupportingFile("pom-sb4.mustache", "", "pom.xml"));
526+
} else if (isUseSpringBoot3()) {
492527
supportingFiles.add(new SupportingFile("pom-sb3.mustache", "", "pom.xml"));
493528
} else {
494529
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
@@ -654,6 +689,14 @@ public void processOpts() {
654689
supportsAdditionalPropertiesWithComposedSchema = true;
655690
}
656691

692+
protected void applyJackson2Package() {
693+
writePropertyBack(JACKSON_PACKAGE, JACKSON2_PACKAGE);
694+
}
695+
696+
protected void applyJackson3Package() {
697+
writePropertyBack(JACKSON_PACKAGE, JACKSON3_PACKAGE);
698+
}
699+
657700
private boolean supportLibraryUseTags() {
658701
return SPRING_BOOT.equals(library) || SPRING_CLOUD_LIBRARY.equals(library);
659702
}

modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import org.springframework.context.annotation.Bean;
44
import org.springframework.stereotype.Controller;
55
import org.springframework.web.bind.annotation.RequestMapping;
66
{{#sourceDocumentationProvider}}
7-
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
7+
import {{jacksonPackage}}.dataformat.yaml.YAMLMapper;
88
import org.springframework.beans.factory.annotation.Value;
99
import org.springframework.core.io.Resource;
1010
import org.springframework.util.StreamUtils;

modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/RFC3339DateFormat.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package {{basePackage}};
22

3-
import com.fasterxml.jackson.databind.util.StdDateFormat;
3+
import {{jacksonPackage}}.databind.util.StdDateFormat;
44

55
import java.text.DateFormat;
66
import java.text.FieldPosition;

modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/openapi2SpringBoot.mustache

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package {{basePackage}};
22

33
{{#openApiNullable}}
4+
{{^useJackson3}}
45
import com.fasterxml.jackson.databind.Module;
6+
{{/useJackson3}}
57
import org.openapitools.jackson.nullable.JsonNullableModule;
68
{{/openApiNullable}}
79
import org.springframework.boot.SpringApplication;
@@ -25,10 +27,12 @@ public class OpenApiGeneratorApplication {
2527
}
2628

2729
{{#openApiNullable}}
30+
{{^useJackson3}}
2831
@Bean(name = "{{basePackage}}.OpenApiGeneratorApplication.jsonNullableModule")
2932
public Module jsonNullableModule() {
3033
return new JsonNullableModule();
3134
}
35+
{{/useJackson3}}
3236
{{/openApiNullable}}
3337

3438
}

modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
<parent>
3737
<groupId>org.springframework.boot</groupId>
3838
<artifactId>spring-boot-starter-parent</artifactId>
39-
<version>3.1.3</version>
39+
<version>3.2.0</version>
4040
<relativePath/> <!-- lookup parent from repository -->
4141
</parent>
4242
{{/parentOverridden}}

0 commit comments

Comments
 (0)