Skip to content
Open
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
2 changes: 2 additions & 0 deletions docs/generators/java-camel.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useFeignClientContextId|Whether to generate Feign client with contextId parameter.| |true|
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useJackson3|Set it in order to use jackson 3 dependencies (only allowed when `useSpringBoot4` is set and incompatible with `openApiNullable`).| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|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|
|useOptional|Use Optional container for optional parameters| |false|
|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|
|useSealed|Whether to generate sealed model interfaces and classes| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|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|
|useSpringBuiltInValidation|Disable `@Validated` at the class level when using built-in validation.| |false|
|useSpringController|Annotate the generated API as a Spring Controller| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
Expand Down
2 changes: 2 additions & 0 deletions docs/generators/spring.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useFeignClientContextId|Whether to generate Feign client with contextId parameter.| |true|
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useJackson3|Set it in order to use jackson 3 dependencies (only allowed when `useSpringBoot4` is set and incompatible with `openApiNullable`).| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|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|
|useOptional|Use Optional container for optional parameters| |false|
|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|
|useSealed|Whether to generate sealed model interfaces and classes| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|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|
|useSpringBuiltInValidation|Disable `@Validated` at the class level when using built-in validation.| |false|
|useSpringController|Annotate the generated API as a Spring Controller| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String GENERATE_GENERIC_RESPONSE_ENTITY = "generateGenericResponseEntity";
public static final String USE_ENUM_CASE_INSENSITIVE = "useEnumCaseInsensitive";
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
public static final String USE_SPRING_BOOT4 = "useSpringBoot4";
public static final String REQUEST_MAPPING_OPTION = "requestMappingMode";
public static final String USE_REQUEST_MAPPING_ON_CONTROLLER = "useRequestMappingOnController";
public static final String USE_REQUEST_MAPPING_ON_INTERFACE = "useRequestMappingOnInterface";
Expand All @@ -101,6 +102,7 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String USE_SPRING_BUILT_IN_VALIDATION = "useSpringBuiltInValidation";
public static final String USE_DEDUCTION_FOR_ONE_OF_INTERFACES = "useDeductionForOneOfInterfaces";
public static final String SPRING_API_VERSION = "springApiVersion";
public static final String USE_JACKSON_3 = "useJackson3";

@Getter
public enum RequestMappingMode {
Expand Down Expand Up @@ -154,6 +156,8 @@ public enum RequestMappingMode {
@Setter protected boolean useEnumCaseInsensitive = false;
@Getter @Setter
protected boolean useSpringBoot3 = false;
@Getter @Setter
protected boolean useSpringBoot4 = false;
protected boolean generatedConstructorWithRequiredArgs = true;
@Getter @Setter
protected RequestMappingMode requestMappingMode = RequestMappingMode.controller;
Expand All @@ -163,6 +167,8 @@ public enum RequestMappingMode {
protected boolean useSpringBuiltInValidation = false;
@Getter @Setter
protected boolean useDeductionForOneOfInterfaces = false;
@Getter @Setter
protected boolean useJackson3 = false;

public SpringCodegen() {
super();
Expand Down Expand Up @@ -278,6 +284,10 @@ public SpringCodegen() {
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3,
"Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.",
useSpringBoot3));
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT4,
"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`.",
useSpringBoot4));
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));
cliOptions.add(CliOption.newBoolean(GENERATE_CONSTRUCTOR_WITH_REQUIRED_ARGS,
"Whether to generate constructors with required args for models",
generatedConstructorWithRequiredArgs));
Expand Down Expand Up @@ -460,8 +470,13 @@ public void processOpts() {
additionalProperties.put("springHttpStatus", new SpringHttpStatusLambda());

convertPropertyToBooleanAndWriteBack(USE_ENUM_CASE_INSENSITIVE, this::setUseEnumCaseInsensitive);
convertPropertyToBooleanAndWriteBack(USE_JACKSON_3, this::setUseJackson3);
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT3, this::setUseSpringBoot3);
if (isUseSpringBoot3()) {
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT4, this::setUseSpringBoot4);
if(isUseSpringBoot3() && isUseSpringBoot4()){
throw new IllegalArgumentException("Choose between spring boot 3 and spring boot 4");
}
if (isUseSpringBoot3() || isUseSpringBoot4()) {
if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) {
throw new IllegalArgumentException(DocumentationProvider.SPRINGFOX.getPropertyName() + " is not supported with Spring Boot > 3.x");
}
Expand All @@ -471,15 +486,25 @@ public void processOpts() {
useJakartaEe = true;
applyJakartaPackage();
}
if(isUseJackson3() && !isUseSpringBoot4()){
throw new IllegalArgumentException("useJackson3 is only available with Spring Boot > 4.x");
}
if(isUseJackson3() && isOpenApiNullable()){
throw new IllegalArgumentException("openApiNullable cannot be set with useJackson3");
}
convertPropertyToStringAndWriteBack(RESOURCE_FOLDER, this::setResourceFolder);


// override parent one
importMapping.put("JsonDeserialize", useJackson3 ? "tools.jackson.databind.annotation.JsonDeserialize" : "com.fasterxml.jackson.databind.annotation.JsonDeserialize");
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: useJackson3 only remaps JsonDeserialize; JsonProperty/JsonValue/JsonCreator still map to com.fasterxml, causing mixed Jackson 2/3 annotations in generated models when useJackson3 is enabled.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java, line 499:

<comment>useJackson3 only remaps JsonDeserialize; JsonProperty/JsonValue/JsonCreator still map to com.fasterxml, causing mixed Jackson 2/3 annotations in generated models when useJackson3 is enabled.</comment>

<file context>
@@ -471,15 +486,25 @@ public void processOpts() {
 
+
+        // override parent one
+        importMapping.put("JsonDeserialize", useJackson3 ? "tools.jackson.databind.annotation.JsonDeserialize" : "com.fasterxml.jackson.databind.annotation.JsonDeserialize");
+
         typeMapping.put("file", "org.springframework.core.io.Resource");
</file context>
Fix with Cubic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cubic-dev-ai according to Jackson 3 migration guide, Jackson annotations remain in 2 under com.fasterxml.
Only those in jackson-databind (JsonDeserialize for instance) are migrated in Jackson 3 libraries.

Copy link
Contributor Author

@antechrestos antechrestos Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cubic-dev-ai see the migration guide . It clearly says that all annotation but JsonSerialize and JsonDeserialize remains in jackson annotation 2.20.


typeMapping.put("file", "org.springframework.core.io.Resource");
importMapping.put("Nullable", "org.springframework.lang.Nullable");
importMapping.put("org.springframework.core.io.Resource", "org.springframework.core.io.Resource");
importMapping.put("DateTimeFormat", "org.springframework.format.annotation.DateTimeFormat");
importMapping.put("ApiIgnore", "springfox.documentation.annotations.ApiIgnore");
importMapping.put("ParameterObject", "org.springdoc.api.annotations.ParameterObject");
if (isUseSpringBoot3()) {
if (isUseSpringBoot3() || isUseSpringBoot4()) {
importMapping.put("ParameterObject", "org.springdoc.core.annotations.ParameterObject");
}

Expand All @@ -488,7 +513,9 @@ public void processOpts() {
additionalProperties.put("delegate-method", true);
}

if (isUseSpringBoot3()) {
if (isUseSpringBoot4()) {
supportingFiles.add(new SupportingFile("pom-sb4.mustache", "", "pom.xml"));
} else if (isUseSpringBoot3()) {
supportingFiles.add(new SupportingFile("pom-sb3.mustache", "", "pom.xml"));
} else {
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
{{#sourceDocumentationProvider}}
{{#useJackson3}}
import tools.jackson.dataformat.yaml.YAMLMapper;
{{/useJackson3}}
{{^useJackson3}}
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
{{/useJackson3}}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.util.StreamUtils;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package {{basePackage}};

{{#useJackson3}}
import tools.jackson.databind.util.StdDateFormat;
{{/useJackson3}}
{{^useJackson3}}
import com.fasterxml.jackson.databind.util.StdDateFormat;
{{/useJackson3}}

import java.text.DateFormat;
import java.text.FieldPosition;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package {{basePackage}};

{{#openApiNullable}}
{{^useJackson3}}
import com.fasterxml.jackson.databind.Module;
{{/useJackson3}}
import org.openapitools.jackson.nullable.JsonNullableModule;
{{/openApiNullable}}
import org.springframework.boot.SpringApplication;
Expand All @@ -25,10 +27,12 @@ public class OpenApiGeneratorApplication {
}

{{#openApiNullable}}
{{^useJackson3}}
@Bean(name = "{{basePackage}}.OpenApiGeneratorApplication.jsonNullableModule")
public Module jsonNullableModule() {
return new JsonNullableModule();
}
{{/useJackson3}}
{{/openApiNullable}}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.3</version>
<version>3.2.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
{{/parentOverridden}}
Expand Down
Loading
Loading