Skip to content

Add OptBoolean valued @JsonProperty.isRequired to (eventually) replace @JsonProperty.required #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cowtowncoder opened this issue Mar 12, 2025 · 6 comments · Fixed by #285
Milestone

Comments

@cowtowncoder
Copy link
Member

One nasty issue with @JsonProperty annotation is that its required property is boolean-valued: and as such cannot indicate "use defaults" / "not defined" option -- and default being false, it means that:

@JsonProperty

is same as

@JsonProperty(required = false)

so that it is easy to accidentally specify that a property is NOT required. This is especially true when considering cases where there are more generic defaults (provided by modules, f.ex) at, levels like:

  • For Constructor (require-all)
  • Global defaults (default-unless-overriden)

in which case any use of @JsonProperty either:

  1. Overrides more general default, OR
  2. If only required = true case considered explicit, is impossible to disable "required-ness"

What we need, really, is third state: and use of OptBoolean enum offers that: it has 3 values:

  • TRUE (-> Boolean.TRUE)
  • FALSE (-> Boolean.FALSE)
  • DEFAULT (-> null)

However. We cannot really change type of required property, even with 2.x->3.0 transition -- because we do want to keep jackson-annotations backwards-compatible (in that jackson-annotations 2.x versions will work with 3.x, and (for most purposes) vice-versa).

What we can do is to:

  1. add new property, "isRequired" with OptBoolean value
  2. support combination of both new isRequired (higher precedence) and old required (lower precedence) via databind AnnotationIntrospector
  3. for Jackson 3.0, mark required as Deprecated (... and possibly later 2.x, but not in 2.19)
  4. Profit!

This issue is for addition of the new property: there will be new jackson-databind ticket for reminder of work.

@spyro2000
Copy link

spyro2000 commented Apr 28, 2025

I am at Spring Boot 3.4.5 and now I can't serialize classes anymore since 2.19. For all TOs with use of @JsonProperty I now got

Exception in thread "main" java.lang.NoSuchMethodError: 'com.fasterxml.jackson.annotation.OptBoolean com.fasterxml.jackson.annotation.JsonProperty.isRequired()'Exception in thread "main" java.lang.NoSuchMethodError: 'com.fasterxml.jackson.annotation.OptBoolean com.fasterxml.jackson.annotation.JsonProperty.isRequired()'

The TOs do not use isRequired.

Reproducer:

pom.xml

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
            <version>2.19.0</version>
        </dependency>
      

Code:

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper

val specTO = TestTO(
    someProperty = "hello"
)

val json = jacksonObjectMapper().writeValueAsString(specTO) // EXCEPTION

data class TestTO (
    @get:JsonProperty()
    val someProperty: String? = null
)

@cowtowncoder
Copy link
Member Author

@spyro2000 you must have matching minor versions: if -- for example, you upgrade to Kotlin module 2.19.0, you must also have 2.19 (or higher) version of:

  • jackson-databind (that Kotlin module directly depends on)
  • jackson-core (that jackson-databind directly depends on)
  • jackson-annotions (that jackson-databind directly depends on)

from exception it seems the last is not the case.

One good way to keep versions aligned is to depend on jackson-bom artifact which sets same version for all Jackson components.

@spyro2000
Copy link

spyro2000 commented Apr 29, 2025

Hi @cowtowncoder, thank you for your response :)
So that means, I should just replace

 <dependency>
   <groupId>com.fasterxml.jackson.module</groupId>
   <artifactId>jackson-module-kotlin</artifactId>
   <version>2.19.0</version>
</dependency>

with

 <dependency>
   <groupId>com.fasterxml.jackson.module</groupId>
   <artifactId>jackson-bom</artifactId>
   <version>2.19.0</version>
</dependency>

?

Or should I remove the version for jackson-module-kotlin and do it like this

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.fasterxml.jackson</groupId>
      <artifactId>jackson-bom</artifactId>
      <version>2.19.0</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>   
  </dependencies>
</dependencyManagement>

<!-- ... -->

 <dependency>
   <groupId>com.fasterxml.jackson.module</groupId>
   <artifactId>jackson-bom</artifactId>
</dependency>

?

Or should I remove the version alltogether (that's what helped for me at the moment, at least within a Spring project)

@cowtowncoder
Copy link
Member Author

You should import jackson-bom with specific version, like in second example, and then drop version from jackson-module-kotlin dependency. So you need:

  1. Managed dependency section (from jackson-bom) to define default version and
  2. Actual dependency without version (if you do specify version it will override managed dependency)

With Spring you may already be using its bom, but that has likely some older Jackson version as managed dependency.

@spyro2000
Copy link

spyro2000 commented Apr 30, 2025

Ok, thank you. Indeed it worked again after I just removed the version from jackson-module-kotlin (Spring seems to handle that internally).

@cowtowncoder
Copy link
Member Author

Yeah, these days frameworks set managed dependency versions to try to keep things consistent.
Works, although may complicated things if you want to change (upgrade) some of deps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants