Java >> Java tutorial >  >> Tag >> Json

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;
}

Java tag