How to use Jackson to deserialize external Lombok builder class
Solution 1:
You can customize your ObjectMapper
as follows:
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public Class<?> findPOJOBuilder(AnnotatedClass ac) {
if (ExternalClass.class.equals(ac.getRawType())) {
return ExternalClass.ExternalClassBuilder.class;
}
return super.findPOJOBuilder(ac);
}
@Override
public Value findPOJOBuilderConfig(AnnotatedClass ac) {
if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
return super.findPOJOBuilderConfig(ac);
}
return new JsonPOJOBuilder.Value("build", "");
}
});
This will
- explicitly configure that deserialization for
ExternalClass
uses its builder, and - set the default prefix for builder setter methods to
""
(except when the@JsonPOJOBuilder
annotation is present).
If you do not want to list all external classes explicitly in findPOJOBuilder()
, you can of course programmatically look into the class to check whether it has a inner class that looks like a builder.
Solution 2:
This can be accomplished by creating two mixins: one for ExternalClass
(specifying the builder to use) and one for ExternalClass.ExternalClassBuilder
(specifying the lack of a prefix in the builder methods).
@JsonDeserialize(builder = ExternalClass.ExternalClassBuilder.class)
public interface ExternalClassMixin {
}
@JsonPOJOBuilder(withPrefix="")
public interface ExternalClassBuilderMixin {
}
This serializes and deserializes the JSON in the desired manner:
String json = "{\"name\": \"The Name\", \"data\": \"The Data\"}";
ObjectMapper mapper = new ObjectMapper()
.addMixIn(ExternalClass.class, ExternalClassMixin.class)
.addMixIn(ExternalClass.ExternalClassBuilder.class, ExternalClassBuilderMixin.class);
System.out.println(mapper.readValue(json, ExternalClass.class));
System.out.println(mapper.writeValueAsString(mapper.readValue(json, ExternalClass.class)));
Output:
ExternalClass(name=The Name, data=The Data)
{"name":"The Name","data":"The Data"}