Lombok @SuperBuilder eksempel med json-annoteringer
Opdateret 2018-11-10:Lombok 1.18.4 udgivet
Opdateret 2020-10-18:Lombok 1.18.16 frigivet
Lombok 1.18.16 indeholder den nye @Jacksonized
anmærkning. Med den kan du blot skrive:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = SubA.class),
@JsonSubTypes.Type(value = AnotherSub.class)
})
@Jacksonized
@SuperBuilder
// more annotations...
public abstract class AbstractA {
@JsonProperty
protected final String superProperty;
}
@Jacksonized
@SuperBuilder
@JsonTypeName("SubA")
// more annotations...
public class SubA extends AbstractA {
@JsonProperty
private final String fieldA;
}
Dette vil automatisk indsætte alle nødvendige Jackson-anmærkninger og foretage nogle justeringer af den genererede builder. Ingen grund til at tilpasse længere.
For tidligere Lombok-versioner mellem 1.18.4 og 1.18.12 , dette er vejen at gå:
Til Lomboks @Builder
og @SuperBuilder
for at arbejde med Jackson, skal du tilføje builder-klassens header manuelt og placere en @JsonPOJOBuilder(withPrefix="")
på det. Lombok vil så kun generere resten af bygmesterklassen. Dette er nødvendigt, fordi Jacksons standard er, at bygherrens indstillingsmetoder har "med" som præfiks, men Lomboks bygherrer har ikke noget præfiks (og Lombok er ikke og vil sandsynligvis aldrig kunne konfigureres i denne henseende).
Når @SuperBuilder
blev introduceret i Lombok 1.18.2, kunne den ikke tilpasses (dvs. du kunne ikke manuelt tilføje builder-klassens header). Som et resultat, ved hjælp af @SuperBuilder
med Jackson var ikke let muligt.
Dette ændrede sig med Lombok 1.18.4 (se denne pull-anmodning):@SuperBuilder
kan nu (i det mindste delvist) tilpasses, og dette giver os mulighed for at tilføje annoteringen. Vær opmærksom på, at koden genereret af @SuperBuilder
er ret kompleks og tungt fyldt med generiske lægemidler. For at undgå at ødelægge koden ved et uheld, bør du tage et kig på delombok output og kopier/indsæt klasseheaderen derfra. Her skal du tilføje builder-implementeringsklassens header og sætte annotationen på den:
@JsonPOJOBuilder(withPrefix="")
static final class SubABuilderImpl extends SubABuilder<SubA, SubABuilderImpl> {
}
Bemærk, at du skal udvide synligheden af SubABuilderImpl
til i det mindste pakke-privat.
@JsonDeserialize
annotering skal også henvise til builder-implementeringsklassen, ikke den abstrakte builder:
@JsonDeserialize(builder = SubA.SubABuilderImpl.class)
En fungerende løsning i Eclipse, bemærk, at Lombok IntelliJ-integrationen ikke understøtter alle funktioner, derfor kompileres koden fint i Eclipse og med javac, men IntelliJ tror, den er brudt, men udfører koden uden problemer.
public static ObjectMapper createObjectMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public JsonPOJOBuilder.Value findPOJOBuilderConfig(final AnnotatedClass ac) {
if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
return super.findPOJOBuilderConfig(ac);
}
return new JsonPOJOBuilder.Value("build", "");
}
});
return mapper;
}
public static void main(final String[] args) throws Exception {
final ObjectMapper objectMapper = createObjectMapper();
final String serializedForm = objectMapper.writeValueAsString(SubA.builder().build());
System.out.println(serializedForm);
final SubA anA = objectMapper.readValue(serializedForm, SubA.class);
System.out.println(anA);
}
@Getter
@EqualsAndHashCode(callSuper = true)
@Accessors(fluent = true, chain = true)
@SuperBuilder
@JsonDeserialize(builder = SubA.SubABuilderImpl.class)
@JsonTypeName("SubA")
public static class SubA extends AbstractA {
@JsonProperty
private final String fieldA;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = SubA.class)
})
@Getter
@Accessors(fluent = true, chain = true)
@SuperBuilder
public static abstract class AbstractA {
@JsonProperty
protected final String superProperty;
}