Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable Lombok annotated class with Jackson

What is the preferred way to create class that is

  • Immutable
  • Can be serialized/deserialized with Jackson
  • Human-readable and with low level of boilerplate

Preferably, I would have liked something like this to work:

@Data(onConstructor = @__(@JsonCreator)) 

and then have all fields to be private final. However, this does not even compile (and I'm not sure why). Using

@AllArgsConstructor(onConstructor = @__(@JsonCreator)) 

will compile but only yields

InvalidDefinitionException: No serializer found for class 
like image 693
Christian Neverdal Avatar asked Apr 24 '18 10:04

Christian Neverdal


People also ask

Does Lombok work with Jackson?

Lombok @Jacksonized. Using @Jacksonized annotation is the simplest solution if you are using Jackson for deserialization purposes. Just annotate the @Builder class with @Jacksonized annotation and we are good for converting the JSON string to Java object.

Is JsonProperty required?

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.

What is Jacksonized?

Overview. The @Jacksonized annotation is an add-on annotation for @Builder and @SuperBuilder . It automatically configures the generated builder class to be used by Jackson's deserialization. It only has an effect if present at a context where there is also a @Builder or a @SuperBuilder ; a warning is emitted otherwise ...

What is the difference between @data and @value in Lombok?

The big difference between @Value and @Data annotation is that @Value is mainly used to create immutable objects. @Value is a also an all-in-one annotation that combines: @Getter, @AllArgsConstructor, @ToString and @EqualsAndHashCode and @FieldDefaults(makeFinal = true, level = AccessLevel.


2 Answers

add ConstructorProperties:

  • Create a lombok.config file in an appropriate location with the line: lombok.anyConstructor.addConstructorProperties = true
  • Add lombok @Value annotation to your class to make it immutable

Then serialization and deserialization by Jackson works as expected.

This method:

  • meets the criteria
  • has less boilerplace than the previous top answer
  • works on v1.16.20 (January 9th, 2018) and later

Edit: 2020-08-16

  • Note: Using @Builder with @Value causes this solution to fail. (Thanks to comment from @guilherme-blanco below.) However, if you also add e.g. @AllArgsConstructor it does still work as expected.

Edit: 2021-08-19

  • Note: When you add or change a lombok.config file the change is not picked up unless you do a rebuild (clean then build). I have been caught out by this a few times.
  • @Jacksonized annotation solution is another method to achieve the desired outcome for the specific classes annotated. However, I personally prefer not to need to remember to annotate every class used for deserialization. Using lombok.config removes this overhead.
like image 90
robSE13 Avatar answered Sep 28 '22 00:09

robSE13


As of 15 October 2020 (Lombok v1.18.16), you should simply be able to use the @Jacksonized annotation.

@Jacksonized @Builder @JsonIgnoreProperties(ignoreUnknown = true) public class JacksonExample {   private List<Foo> foos; } 

As described in the linked documentation, this annotation:

  • configures Jackson to use the builder for deserialisation,
  • copies field-specific configuration down from the annotated class to the generated builder (e.g. @JsonIgnoreProperties), and
  • aligns the Jackson prefix used on builder methods (e.g. builder().withField(field) vs builder.field(field) to the one configured in Lombok.
like image 22
jr. Avatar answered Sep 28 '22 01:09

jr.