Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why when a constructor is annotated with @JsonCreator, its arguments must be annotated with @JsonProperty?

People also ask

Is JsonProperty annotation necessary?

You definitely don't need all those @jsonProperty . Jackson mapper can be initialized to sereliazie/deserialize according to getters or private members, you of course need only the one you are using.

Why we use @JsonProperty?

The @JsonProperty annotation is used to map property names with JSON keys during serialization and deserialization. By default, if you try to serialize a POJO, the generated JSON will have keys mapped to the fields of the POJO.

What is the purpose of the @JsonCreator annotation?

@JsonCreator. We can use the @JsonCreator annotation to tune the constructor/factory used in deserialization. It's very useful when we need to deserialize some JSON that doesn't exactly match the target entity we need to get.

What is difference between JsonProperty and JsonAlias?

@JsonProperty can change the visibility of logical property using its access element during serialization and deserialization of JSON. @JsonAlias defines one or more alternative names for a property to be accepted during deserialization.


Jackson has to know in what order to pass fields from a JSON object to the constructor. It is not possible to access parameter names in Java using reflection - that's why you have to repeat this information in annotations.


Parameter names are normally not accessible by the Java code at runtime (because it's drop by the compiler), so if you want that functionality you need to either use Java 8's built-in functionality or use a library such as ParaNamer in order to gain access to it.

So in order to not having to utilize annotations for the constructor arguments when using Jackson, you can make use of either of these 2 Jackson modules:

jackson-module-parameter-names

This module allows you to get annotation-free constructor arguments when using Java 8. In order to use it you first need to register the module:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ParameterNamesModule());

Then compile your code using the -parameters flag:

javac -parameters ...

Link: https://github.com/FasterXML/jackson-modules-java8/tree/master/parameter-names

jackson-module-paranamer

This other one simply requires you to register the module or configure an annotation introspection (but not both as pointed out by the comments). It allows you to use annotation-free constructor arguments on versions of Java prior to 1.8.

ObjectMapper mapper = new ObjectMapper();
// either via module
mapper.registerModule(new ParanamerModule());
// or by directly assigning annotation introspector (but not both!)
mapper.setAnnotationIntrospector(new ParanamerOnJacksonAnnotationIntrospector());

Link: https://github.com/FasterXML/jackson-modules-base/tree/master/paranamer


It is possible to avoid constructor annotations with jdk8 where optionally the compiler will introduce metadata with the names of the constructor parameters. Then with jackson-module-parameter-names module Jackson can use this constructor. You can see an example at post Jackson without annotations

  • The Java™ Tutorials - Obtaining Names of Method Parameters

One can simply use java.bean.ConstructorProperties annotation - it's much less verbose and Jackson also accepts it. For example :

  import java.beans.ConstructorProperties;

  @ConstructorProperties({"answer","closed","language","interface","operation"})
  public DialogueOutput(String answer, boolean closed, String language, String anInterface, String operation) {
    this.answer = answer;
    this.closed = closed;
    this.language = language;
    this.anInterface = anInterface;
    this.operation = operation;
  }