Skip to content
Advertisement

When is a @JsonCreator method required for parsing?

When I try to parse the following object:

JavaScript

I get the error

JavaScript

And I solved this by adding a creator to the User class like this:

JavaScript

This works fine.

So now I go and parse the following object:

JavaScript

and I don’t get an error… why? why it doesn’t require me to use a constructor here?

Here’s the class where the parsing takes place

JavaScript

Advertisement

Answer

The property alias of your User is marked as final, which means it can’t be initialized through a setter. Because in order to assign a value to the field through a setter it should be already initialized with the default value (null, 0, false depending on the type), but final variable can’t be reassigned.

Reminder: the mechanism which Jackson uses by default is to instantiate the class using no-args constructor and then assign the fields via setters. But it can’t be done if one of the fields is final, they such fields need to be provided through constructor, because final means – “assign only once”.

There are two ways to instruct Jackson to use a parametrized constructor:

1. The first option is to point at the constructor explicitly by annotating it with @JsonCreator and apply @JsonProperty on each of the constructor arguments as specified in the documentation.

2. Another option is to add a dependency to Jackson Modules: Java 8 (link to Maven repository), which is an umbrella multi-module that consists of several modules including Parameter names module.

And then you need to configure ObjectMapper. For that, you need to place ParameterNamesModule as a Bean into the Spring’s Context, and it would be grabbed at the application start-up and applied while ObjectMapper would be configured.

JavaScript

But there’s a caveat. A quote from the documentation of the JsonCreator.Mode.PROPERTIES:

Mode that indicates that the argument(s) for creator are to be bound from matching properties of incoming Object value, using creator argument names (explicit or implicit) to match incoming Object properties to arguments.

Note that this mode is currently (2.5) always used for multiple-argument creators; the only ambiguous case is that of a single-argument creator.

I.e. this option would not work if your constructor has exactly one argument.

To make the Jackson recognize a single-arg constructor, you need to apply @JsonProperty on the argument.

This behavior explained here and also mentioned in the module-description at the very bottom of the page:

Preconditions:

  • if class Person has a single argument constructor, its argument needs to be annotated with @JsonProperty("propertyName"). This is to preserve legacy behavior
Advertisement