I am experimenting in combining Jackson and Lombok. Those are my classes:
package testelombok;
import com.fasterxml
I struggled with this for a moment as well. But looking through the documentation here I can see that the onConstructor annotation parameter is considered experimental and is not supported well on my IDE (STS 4). According to the Jackson documentation, private members are not (de)serialized by default. There are quick ways to resolve this.
Add JsonAutoDetect annotation and set it appropriately to detect protected/private members. This is convenient for DTOs
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class SomeClass
Add a factory function with @JsonCreator annotation, this works best if you need some object validation or additional transforms.
public class SomeClass {
// some code here
@JsonCreator
public static SomeClass factory(/* params here dressing them in @JsonProperty annotations*/) {
return new SomeClass();
}
}
Of course you could just manually add the constructor in yourself also as well.
Immutable + Lombok + Jackson can be achieved in next way:
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Value;
@Value
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor
public class LocationDto {
double longitude;
double latitude;
}
class ImmutableWithLombok {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String stringJsonRepresentation = objectMapper.writeValueAsString(new LocationDto(22.11, 33.33));
System.out.println(stringJsonRepresentation);
LocationDto locationDto = objectMapper.readValue(stringJsonRepresentation, LocationDto.class);
System.out.println(locationDto);
}
}
I tried several of the above and they were all temperamental. What really worked for me is the the answer I found here.
on your project's root directory add a lombok.config file (if you haven't done already)
lombok.config
and inside paste this
lombok.anyConstructor.addConstructorProperties=true
Then you can define your pojos like the following:
@Data
@AllArgsConstructor
public class MyPojo {
@JsonProperty("Description")
private String description;
@JsonProperty("ErrorCode")
private String errorCode;
}
I had a different issue and it was with the boolean primitive types.
private boolean isAggregate;
It was throwing the following error as a result
Exception: Unrecognized field "isAggregate" (class
Lambok converts isAggregate
to isAggregate()
as a getter making the property internally to lombok as aggregate
instead isAggregate
. The Jackson library doesn't like it and it needs isAggregate
property instead.
I updated the primitive boolean to Wrapper Boolean to work around this issue. There are other options for you if you are dealing with boolean
types, see the reference below.
Sol:
private Boolean isAggregate;
ref: https://www.baeldung.com/lombok-getter-boolean
If you want immutable but a json serializable POJO using lombok and jackson.
Use jacksons new annotation on your lomboks builder @JsonPOJOBuilder(withPrefix = "")
I tried this solution and it works very well.
Sample usage
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Value;
@JsonDeserialize(builder = Detail.DetailBuilder.class)
@Value
@Builder
public class Detail {
private String url;
private String userName;
private String password;
private String scope;
@JsonPOJOBuilder(withPrefix = "")
public static class DetailBuilder {
}
}
If you have too many classes with @Builder
and you want don't want the boilerplate code empty annotation you can override the annotation interceptor to have empty withPrefix
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
if (ac.hasAnnotation(JsonPOJOBuilder.class)) {//If no annotation present use default as empty prefix
return super.findPOJOBuilderConfig(ac);
}
return new JsonPOJOBuilder.Value("build", "");
}
});
And you can remove the empty builder class with @JsonPOJOBuilder
annotation.
From Jan Rieke's Answer
Since lombok 1.18.4, you can configure what annotations are copied to the constructor parameters. Insert this into your
lombok.config
:lombok.copyableAnnotations += com.fasterxml.jackson.annotation.JsonProperty
Then just add
@JsonProperty
to your fields:...
You'll need a @JsonProperty on every field even if the name matches, but that is a good practice to follow anyway. You can also set your fields to public final using this, which I prefer over getters.
@ToString
@EqualsAndHashCode
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
public final String x;
@JsonProperty("z")
public final int z;
}
It should also work with getters (+setters) though.