Skip to content
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

2.15.0-rc1 regression: transient fields are serialized #3874

Closed
emlun opened this issue Apr 11, 2023 · 4 comments
Closed

2.15.0-rc1 regression: transient fields are serialized #3874

emlun opened this issue Apr 11, 2023 · 4 comments
Labels
to-evaluate Issue that has been received but not yet evaluated

Comments

@emlun
Copy link

emlun commented Apr 11, 2023

Describe the bug

In 2.14.2 and earlier, transient fields (with or without @JsonIgnore) with a getter (without @JsonIgnore) are ignored during serialization and do not emit a JSON property.

In 2.15.0-rc1 and 2.15.0-rc2, they do emit a JSON property.

Example

Given this data class:

public class Foo1 {
    private final Integer a;
    @JsonIgnore private final transient Integer minusA;

    @JsonCreator
    public Foo1(@JsonProperty("a") Integer a) {
        this.a = a;
        this.minusA = a == null ? null : -a;
    }

    public Integer getA() { return a; }
    public Integer getMinusA() { return minusA; }
}

and this ObjectMapper:

ObjectMapper json =
    new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
        .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
        .setSerializationInclusion(Include.NON_ABSENT);

Jackson 2.14.2 serializes a Foo1 instance to {"a":0} while Jackson 2.15.0-rc1 serializes the same value to {"a":0,"minusA":0}.

Version information

Issue is not present in 2.14.2.

Issue is present in 2.15.0-rc1.

To Reproduce

  1. Check out commit f40ff286 in Yubico/java-webauthn-server (branch jackson-regression-2-15-rc1 - might not persist after this issue is closed).
  2. Run: ./gradlew :test-success-2-14:test. Observe that the test succeeds.
  3. Run: ./gradlew :test-fail-2-15:test. Observe that the test fails.
  4. Run: ./gradlew :test-success-2-14:dependencies. Observe that the resolved Jackson version is 2.14.2.
  5. Run: ./gradlew :test-fail-2-15:dependencies. Observe that the resolved Jackson version is 2.15.0-rc1.
  6. Run: git diff --no-index lib/src/main/java/org/example/Foo1.java lib/src/main/java/org/example/Foo2.java. Observe that the only (relevant) difference is that Foo1.minusA is transient while Foo2.minusA is not.

After running the above, you can see the failed test report at test-fail-2-15/build/reports/tests/test/index.html.

Additional context

One might run into this when using Lombok's @Value annotation on classes with transient fields - even if the field has @JsonIgnore, the generated getter does not inherit the @JsonIgnore annotation.

@emlun emlun added the to-evaluate Issue that has been received but not yet evaluated label Apr 11, 2023
@pjfanning
Copy link
Member

this is possibly because of public Integer getMinusA() { return minusA; } -- fields that are exposed when serializing can include getters

@cowtowncoder
Copy link
Member

cowtowncoder commented Apr 11, 2023

I think this is a side effect of some change related to pruning of transient fields during processing.

First of all: note that the reason 2.14 and earlier did not include minusA is NOT due to transient marker but rather @JsonIgnore that is used to remove "whole" property minusA (both field and getter).
Why this isn't happening 2.15.0-rc1/rc2 is unclear but I suspect Field is dropped first and linkage not established to drop getter as well.

But there are at least 2 changes that should make things work in a way that'd work in both 2.15 and 2.14 (and earlier):

  1. Enable MapperFeature.PROPAGATE_TRANSIENT_MARKER and leave out @JsonIgnore from field
  2. Move @JsonIgnore on getter; not sure why it is added to Field in the first place (getter is what would be used)

I suggest doing one of above; changes are behavior of 2.15 will remain the way rc2 has it (due to timing of things) so that is safer set up.

@emlun
Copy link
Author

emlun commented Apr 12, 2023

Yeah, it would make sense that this would have changed if @JsonIgnore is processed before removing transient fields in 2.14, but that order is reversed in 2.15.

[...] changes are behavior of 2.15 will remain the way rc2 has it [...]

Ok, I guess this was an unintentional "feature". Issue #296 appears to also deal with this. I'll admit I didn't look up whether Jackson promises anything about transient fields before I added the modifier. The docs for PROPAGATE_TRANSIENT_MARKER for 2.9 (the version used at the time) do indeed say (emphasis added):

Feature is disabled by default, meaning that existence of transient for a field does not necessarily lead to ignoral of getters or setters but just ignoring the use of field for access.

So yeah, looks like this is a "regression" of a feature that was not promised. Thanks for the replies!

@emlun emlun closed this as completed Apr 12, 2023
@cowtowncoder
Copy link
Member

@emlun Yes -- ideally behavior would not have changed, but it is bit of an edge case. I do consider it a regression but given how complicated the logic in that part is, it may be difficult to return handling of such cases.
transient is interesting in its own right; as well as what is intended to be relationship between fields, getters, setters etc etc.

But I hope your use case works with some modifications. Thank you for follow up!

phiz71 added a commit to gravitee-io/gravitee-api-management that referenced this issue Jul 11, 2023
Need to add @JsonIgnore too because transient + @JsonIgnore on the property does not work anymore in 2.15
See FasterXML/jackson-databind#3874 (comment)
Before 2.15, it was an unexpected feature.
phiz71 added a commit to gravitee-io/gravitee-api-management that referenced this issue Jul 11, 2023
Need to add @JsonIgnore too because transient + @JsonIgnore on the property does not work anymore in 2.15
See FasterXML/jackson-databind#3874 (comment)
Before 2.15, it was an unexpected feature.
mergify bot pushed a commit to gravitee-io/gravitee-api-management that referenced this issue Jul 11, 2023
Need to add @JsonIgnore too because transient + @JsonIgnore on the property does not work anymore in 2.15
See FasterXML/jackson-databind#3874 (comment)
Before 2.15, it was an unexpected feature.

(cherry picked from commit 867cb6b)
phiz71 added a commit to gravitee-io/gravitee-api-management that referenced this issue Jul 12, 2023
Need to add @JsonIgnore too because transient + @JsonIgnore on the property does not work anymore in 2.15
See FasterXML/jackson-databind#3874 (comment)
Before 2.15, it was an unexpected feature.

(cherry picked from commit 867cb6b)
gaetanmaisse pushed a commit to gravitee-io/gravitee-api-management that referenced this issue Jul 12, 2023
Need to add @JsonIgnore too because transient + @JsonIgnore on the property does not work anymore in 2.15
See FasterXML/jackson-databind#3874 (comment)
Before 2.15, it was an unexpected feature.

(cherry picked from commit 867cb6b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
to-evaluate Issue that has been received but not yet evaluated
Projects
None yet
Development

No branches or pull requests

3 participants