question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Do not try to set @JsonUnwrapped fields if using a @JsonCreator constructor

See original GitHub issue

Hi,

After discussing this matter on the mailing list, I was redirected to creating an issue to ease some use case of @JsonUnwrapped.

Basically, my objective is to avoid using mutable objects and exploit as much as possible constructors to construct objects.

Taking this example:

class Location {
    public final int latitude, longitude;

    public Location(int latitude, int longitude) { ... }
}

class Place {
    public final String name;
    @JsonUnwrapped public final Location location;

    @JsonCreator
    public Place(@JsonProperty("name") String name,
                 @JsonProperty("latitude") int latitude, 
                 @JsonProperty("longitude") int longitude) {
        this.name = name;
        this.location = new Location(latitude, longitude);
    }
}

Currently, deserializing a Place object fails because Jackson first builds the Place object (successfully, including the location with the correct values) and then tries to set the location field. The latter fails because the latitude and longitude properties were already used to construct the Place, and thus are not used to construct the Location. At the end of the deserialization process, the location field is initialised with an object with null values for latitude and longitude!

I would expect Jackson not to try to set the location field after a Place object was successfully constructed since a constructor is expected to build fully constructed objects?

Apparently (according to the discussion on the mailing list), the following code should have worked:

class Location {
    public final int latitude, longitude;

    public Location(int latitude, int longitude) { ... }
}

class Place {
    public final String name;
    @JsonUnwrapped public final Location location;

    @JsonCreator
    public Place(@JsonProperty("name") String name) {
        this.name = name;
        this.location = null;
    }
}

I.e., the Place object is partially created, and then Jackson would set the location field. In practice it didn’t work, not sure why. But with respect to my proposed solution to the first problem of this issue, I’m not sure it is a so good idea that this second way of doing things work: for me a constructor is meant to fully build an object!

FYI, the only solution I found to work is to have a parameter-less constructor and let Jackson handle everything its way. I feel there is some use case where a constructor would really be needed, for example if the properties must be reworked a bit before being set to the object (keeping in mind I don’t want to use setters 😃.

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:6
  • Comments:14 (3 by maintainers)

github_iconTop GitHub Comments

6reactions
dbolotincommented, May 10, 2017

Possible solution that I found to make @JsonUnwrap affect only serialisation, and be able to provide custom @JsonCreator is to add @JsonProperty(access = READ_ONLY) annotation to the “unwrapped” properties.

3reactions
phraktlecommented, Oct 7, 2021

@cowtowncoder any suggestions on a workaround to make @JsonUnwrapped work with record classes?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Deserializing @JsonUnwrapped fields with @JsonCreator ...
I thought it should at least worked with the first case (i.e. if there is a constructor for the object, then Jackson should...
Read more >
JsonUnwrapped and @JsonCreate for same field causes issues
But when I remove the @JsonUnwrapped the field gets deserialised ok but is not flatten during serialisation. How to assure that Father field...
Read more >
SUSE-SU-2022:1678-1: important: Security update for jackson ...
getNullValue()' + DeserializationProblemHandler is not invoked when trying to deserialize String + Fix failing 'double' JsonCreators in ...
Read more >
Jackson JSON - Using @JsonUnwrapped to serialize ...
JsonUnwrapped is used to indicate that a property should be serialized unwrapped, i.e. the target property will not be serialized as JSON ...
Read more >
FasterXML/jackson-databind - Gitter
@marceloverdijk Yes, "Default Typing" can do that for arbitrary sets of ... we noticed when we use @JsonCreator and @JsonProperty we see a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found