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.
@JsonPOJOBuilder The @JsonPOJOBuilder annotation is used to configure a builder class to customize deserialization of a JSON document to recover POJOs when the naming convention is different from the default.
Lombok is just a tool to make your life easy. It does not provide any assistance or support for clean code. If clean code and design principles are not of importance (trust me it's not that bad as it sounds in most of the cases), then using Lombok to simplify development process is the best option.
@JsonDeserialize is used to specify custom deserializer to unmarshall the json object.
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.
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 exactly the same issue, "solved" it by adding the suppressConstructorProperties = true
parameter (using your example):
@Value
@Wither
@AllArgsConstructor(suppressConstructorProperties = true)
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
Jackson apparently does not like the java.beans.ConstructorProperties
annotation added to constructors. The suppressConstructorProperties = true
parameter tells Lombok not to add it (it does by default).
@AllArgsConstructor(suppressConstructorProperties = true)
is deprecated. Define lombok.anyConstructor.suppressConstructorProperties=true
(https://projectlombok.org/features/configuration) and change POJO's lombok annotation from @Value
to @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
works for me.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With