Skip to content

feat: migrate to jackson 3#5031

Open
vpelikh wants to merge 2 commits into
swagger-api:masterfrom
vpelikh:update-to-java-17
Open

feat: migrate to jackson 3#5031
vpelikh wants to merge 2 commits into
swagger-api:masterfrom
vpelikh:update-to-java-17

Conversation

@vpelikh

@vpelikh vpelikh commented Jan 1, 2026

Copy link
Copy Markdown

Description

This PR consists of two commits:

  • update to java 17 (minimum version for jackson 3)
  • update to jackson 3

Fixes: #4991

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • ♻️ Refactor (non-breaking change)
  • 🧪 Tests
  • 📝 Documentation
  • 🧹 Chore (build or tooling)

Checklist

  • I have added/updated tests as needed
  • I have added/updated documentation where applicable
  • The PR title is descriptive
  • The code builds and passes tests locally
  • I have linked related issues (if any)

Screenshots / Additional Context

@vpelikh vpelikh force-pushed the update-to-java-17 branch from 7633f49 to 7b93974 Compare January 1, 2026 13:48
@vpelikh vpelikh changed the title feat: migrate to java 17 feat: migrate to jackson 3 Jan 3, 2026
@cbot59

cbot59 commented Jan 4, 2026

Copy link
Copy Markdown

I think we need to introduce constructor for ModelResolver(JsonMapper) and deprecate the old constructor so the newer release requires user to Jackson3 instead.

currently I have such usage on ModelResolver when using springdoc-openapi
Screenshot 2026-01-04 at 10 17 11

my first attempt to migrate to Jackson3 would be

public ModelResolver modelResolver(JsonMapper jsonMapper) {
        return new ModelResolver(jsonMapper);
    }

as it is more straightforward

changes:
- update maven-compiler-plugin to latest 3.14.1
- update maven-javadoc-plugin to latest 3.12.0
- update jacoco-maven-plugin to latest 0.8.14
- set maven.compiler.release to 17
- set source to 17 and update link to javadoc for maven-javadoc-plugin configuration
- set java-version to 17 in github workflows
- set java version to 17 in swagger-gradle-plugin
@vpelikh vpelikh force-pushed the update-to-java-17 branch from 0de7198 to f60ee1e Compare January 4, 2026 13:36
@vpelikh

vpelikh commented Jan 4, 2026

Copy link
Copy Markdown
Author

I have removed many of the changes associated with java 17, so the PR is now much smaller.

@cbot59, thanks for the comment! JsonMapper is a descendant of ObjectMapper, so return new ModelResolver(jsonMapper); should work without a new constructor.

@WilliamAGH

Copy link
Copy Markdown

Hey everyone -- thanks to @vpelikh, we now have Jackson 3 and Java 17 support.

But I didn't want to wait, so I have it available here! His branch is available as a dependency, just add this to your build.gradle file or pom.xml equivalent:

configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute(module("io.swagger.core.v3:swagger-core-jakarta"))
            .using(module("com.github.WilliamAGH.swagger-core:swagger-core-jakarta:jackson-3-SNAPSHOT"))
        substitute(module("io.swagger.core.v3:swagger-models-jakarta"))
            .using(module("com.github.WilliamAGH.swagger-core:swagger-models-jakarta:jackson-3-SNAPSHOT"))
        substitute(module("io.swagger.core.v3:swagger-annotations-jakarta"))
            .using(module("com.github.WilliamAGH.swagger-core:swagger-annotations-jakarta:jackson-3-SNAPSHOT"))
    }

@piotrooo

Copy link
Copy Markdown

@cbot59, thanks for the comment! JsonMapper is a descendant of ObjectMapper, so return new ModelResolver(jsonMapper); should work without a new constructor.

No, it doesn't, because the ObjectMapper used by Swagger comes from the com.fasterxml.jackson.databind package (Jackson v2), while in v3 the JsonMapper comes from tools.jackson.databind.

@KP-EV

KP-EV commented Jan 27, 2026

Copy link
Copy Markdown

Any update on this?

@larsf96

larsf96 commented Jan 29, 2026

Copy link
Copy Markdown

Any chance that a maintainer takes a look here?
Is there any workaround to use Spring Boot 4 with SpringDoc 3 without waiting for this?

@WilliamAGH

Copy link
Copy Markdown

Any chance that a maintainer takes a look here? Is there any workaround to use Spring Boot 4 with SpringDoc 3 without waiting for this?

Yes, I’ve had this workaround in use in production for the last 2 weeks:

#5031 (comment)

@larsf96

larsf96 commented Jan 30, 2026

Copy link
Copy Markdown

configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("io.swagger.core.v3:swagger-core-jakarta"))
.using(module("com.github.WilliamAGH.swagger-core:swagger-core-jakarta:jackson-3-SNAPSHOT"))
substitute(module("io.swagger.core.v3:swagger-models-jakarta"))
.using(module("com.github.WilliamAGH.swagger-core:swagger-models-jakarta:jackson-3-SNAPSHOT"))
substitute(module("io.swagger.core.v3:swagger-annotations-jakarta"))
.using(module("com.github.WilliamAGH.swagger-core:swagger-annotations-jakarta:jackson-3-SNAPSHOT"))
}

This does not work for me:

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    org.springdoc.core.providers.ObjectMapperProvider.<init>(ObjectMapperProvider.java:75)

The following method did not exist:

    'com.fasterxml.jackson.databind.ObjectMapper io.swagger.v3.core.util.Json31.mapper()'

The calling method's class, org.springdoc.core.providers.ObjectMapperProvider, was loaded from the following location:

    jar:file:/application/BOOT-INF/lib/springdoc-openapi-starter-common-3.0.1.jar!/org/springdoc/core/providers/ObjectMapperProvider.class

The called method's class, io.swagger.v3.core.util.Json31, is available from the following locations:

    jar:file:/application/BOOT-INF/lib/swagger-core-jakarta-jackson-3-52d4c245bb-1.jar!/io/swagger/v3/core/util/Json31.class
    jar:file:/application/BOOT-INF/lib/swagger-core-jakarta-2.2.41.jar!/io/swagger/v3/core/util/Json31.class

The called method's class hierarchy was loaded from the following locations:

    io.swagger.v3.core.util.Json31: file:/application/BOOT-INF/lib/swagger-core-jakarta-jackson-3-52d4c245bb-1.jar


Action:

Correct the classpath of your application so that it contains compatible versions of the classes org.springdoc.core.providers.ObjectMapperProvider and io.swagger.v3.core.util.Json31

@vpelikh

vpelikh commented Feb 17, 2026

Copy link
Copy Markdown
Author

@daniel-kmiecik @Mattias-Sehlstedt @ewaostrowska, hey! I see you've done the last commits to this repository. Can anyone check out this PR?

@Mattias-Sehlstedt

Copy link
Copy Markdown
Contributor

Hi @vpelikh, I am only a contributor, so I can unfortunately not do anything to help. But the other two are maintainers and will hopefully assist you.

@piotrooo

Copy link
Copy Markdown

@MichakrawSB Is there any ETA for this feature? Can we please prioritize this?

@KP-EV

KP-EV commented Mar 4, 2026

Copy link
Copy Markdown

It would be really great if you could prioritize this 🙏

@fenston

fenston commented Mar 24, 2026

Copy link
Copy Markdown

Is this PR not progressing?

@lordarnoud

Copy link
Copy Markdown

Any information on this yet? Will this also make it work with the newest springboot and java 26?

@jochenberger

Copy link
Copy Markdown
Contributor

I'm running the current version with latest Spring Boot/Jackson 3 on Java 26 without issues.

@piotrooo

Copy link
Copy Markdown

I'm running the current version with latest Spring Boot/Jackson 3 on Java 26 without issues.

Yes, it works. However, you probably need to add Jackson 2 compatibility support using the deprecated classes. It does work, but it is not an ideal solution.

@mzhafez

mzhafez commented Apr 15, 2026

Copy link
Copy Markdown

Is there any plan on merging this or maybe adding this to the next major version instead?

@lbenedetto

Copy link
Copy Markdown

Going to be forced to ditch swagger and find another solution soon 😅

Spring Boot 3.5.x OSS Support (End of Life) ends on June 30, 2026. After this date, community-driven security patches and bug fixes will cease.

@BranislavMalo

Copy link
Copy Markdown

Hey, any update on this?

this has been open since january 1st and there’s a lot of interest here compared to most PRs, but it’s still just sitting in “review required” while multiple releases went out

is this actually planned to be merged anytime soon or is it blocked on something?

@jochenberger

Copy link
Copy Markdown
Contributor

Yes, it works. However, you probably need to add Jackson 2 compatibility support using the deprecated classes.

No, you don't. Just upgrade Spring Boot and migrate your code to Jackson 3. As long as swagger-core depends on Jackson 2, they will pull it in and just use it.

I wonder how many people give up before even trying to do the update.

@zqq90

zqq90 commented Apr 23, 2026

Copy link
Copy Markdown

I'm running the current version with latest Spring Boot/Jackson 3 on Java 26 without issues.

@jochenberger

I suspect you might not have used certain annotations from the jackson-databind package, such as JsonNaming.

Or you may have added both Jackson 2 and Jackson 3 annotations at the same time during the migration.

For example:

@tools.jackson.databind.annotation.JsonNaming(tools.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy.class)
@com.fasterxml.jackson.databind.annotation.JsonNaming(com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy.class)
public class SampleVO {

If that's the case, it's really a nagging annoyance.

@jochenberger

Copy link
Copy Markdown
Contributor

Good point @zqq90, I'm indeed not using any of those.

@KP-EV

KP-EV commented May 6, 2026

Copy link
Copy Markdown

@ewaostrowska is it possible to prioritize this higher? Alot of teams are waiting for this :)

@EnvyIT

EnvyIT commented May 6, 2026

Copy link
Copy Markdown

Hey folks,

first of all, thanks for your work and all the continuous improvements — really appreciated.

As mentioned earlier, do you have an idea when this fix will be released or merged? At the moment, the available workarounds are quite cumbersome, and we’d really like to remove Jackson 2.x entirely from our codebase if possible.

If there’s anything we can help with to speed up the process (testing, feedback, etc.), happy to support.

Thanks a lot in advance for your time and help!

@WilliamAGH

Copy link
Copy Markdown

I've had this instance running exclusively on Jackson 3 / Spring Boot 4 for the last several months in a large production environment (the same one mentioned above 4 months ago), you're welcome to use it. It's a pretty simple fix and already available:

vpelikh/swagger-core@master...WilliamAGH:swagger-core:master

@KP-EV

KP-EV commented May 20, 2026

Copy link
Copy Markdown

@djankows sorry for being annoying, but we are closer and closer approaching the deprecation of spring boot 3 and we would really like to do the migration :) Alot of people are waiting on this. Do you need any help?

@pikmin86

Copy link
Copy Markdown

sorry @djankows to re-up the subject but spring boot 3 ends in a month :(

@lbenedetto

lbenedetto commented Jun 2, 2026

Copy link
Copy Markdown

Hey guys, I've gone ahead and proceeded with upgrading to SB4 without this being fixed. I think for most people, it won't be too inconvenient. My setup looks like this:

@Configuration
public class ApiJsonConfiguration {
  @Bean
  @Primary
  public JsonMapper jsonMapper() {
    return JsonMapper.builder()
        .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
        .changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(JsonInclude.Include.NON_ABSENT))
        .changeDefaultPropertyInclusion(incl -> incl.withContentInclusion(JsonInclude.Include.NON_ABSENT))
        .addModule(new SimpleModule().addSerializer(Identity.class, new IdentityToStringSerializer()))
        .addModule(new IdentityDeserializationModule())
        .build();
  }

  @Bean
  @SuppressWarnings("removal") // For now, ModelResolver from swagger-core only supports Jackson 2.x
  // In the future, swagger might support Jackson 3, and then we should just pass in the JsonMapper from above
  public ModelResolver modelResolver() {
    return new ModelResolver(new org.springframework.http.converter.json.Jackson2ObjectMapperBuilder()
        .propertyNamingStrategy(com.fasterxml.jackson.databind.PropertyNamingStrategies.SNAKE_CASE)
        .serializerByType(Identity.class, new IdentityToStringSerializerJackson2())
        .build());
  }
}

Its annoying, but you simply need to provide a jackson2 mapper to the ModelResolver, only configuring the settings relevant to Swagger (basically just the naming convention). Obviously, if you have tons of custom serialization logic, this might not be practical.

@mzhafez

mzhafez commented Jun 2, 2026

Copy link
Copy Markdown

Hey guys, I've gone ahead and proceeded with upgrading to SB4 without this being fixed. I think for most people, it won't be too inconvenient. My setup looks like this:

@Configuration
public class ApiJsonConfiguration {
  @Bean
  @Primary
  public JsonMapper jsonMapper() {
    return JsonMapper.builder()
        .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
        .changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(JsonInclude.Include.NON_ABSENT))
        .changeDefaultPropertyInclusion(incl -> incl.withContentInclusion(JsonInclude.Include.NON_ABSENT))
        .addModule(new SimpleModule().addSerializer(Identity.class, new IdentityToStringSerializer()))
        .addModule(new IdentityDeserializationModule())
        .build();
  }

  @Bean
  @SuppressWarnings("removal") // For now, ModelResolver from swagger-core only supports Jackson 2.x
  // In the future, swagger might support Jackson 3, and then we should just pass in the JsonMapper from above
  public ModelResolver modelResolver() {
    return new ModelResolver(new org.springframework.http.converter.json.Jackson2ObjectMapperBuilder()
        .propertyNamingStrategy(com.fasterxml.jackson.databind.PropertyNamingStrategies.SNAKE_CASE)
        .serializerByType(Identity.class, new IdentityToStringSerializerJackson2())
        .build());
  }
}

Its annoying, but you simply need to provide a jackson2 mapper to the ModelResolver, only configuring the settings relevant to Swagger (basically just the naming convention). Obviously, if you have tons of custom serialization logic, this might not be practical.

I think I speak for most people here; we realize theres a work around but supporting multiple versions of jackson isn't really ideal for any of us here.

We also recognize that we can simply use jackson 2.x in spring boot apps, but that also seems a bit unsafe as jackson 3 has been out for a year and we're unsure of whether jackson 2 will continue to receive the support that it needs, especially in these times where a CVE pops up every other day.

@vpelikh

vpelikh commented Jun 3, 2026

Copy link
Copy Markdown
Author

Hi, I've released Jackson 3 compatible version of all swagger-core dependencies under the group io.github.vpelikh.

You can find all artifacts here:
https://central.sonatype.com/search?q=io.github.vpelikh

For example, the swagger-core artifact:

<dependency>
    <groupId>io.github.vpelikh</groupId>
    <artifactId>swagger-core</artifactId>
    <version>3.0.0</version>
</dependency>

Also if you use springdoc-openapi:

<dependency>
    <groupId>io.github.vpelikh</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
    <version>4.0.0</version>
 </dependency>

Hope this helps while official Jackson 3 support is being worked on!

@KP-EV

KP-EV commented Jun 24, 2026

Copy link
Copy Markdown

@djankows Could we get any official clarification on the jackson3 integration? This merge request is already 6months old and it feels like there is zero progress on actually updating to jackson3. Just a small response would be great already :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Support Jackson 3.x release line