web-dev-qa-db-fra.com

Exemple Lombok @SuperBuilder avec annotations json

quelqu'un peut-il me fournir un exemple de travail avec l'annotation expérimentale lombok @SuperBuilder?

Je ne peux pas le faire fonctionner et il n'y a pas d'exemple de code comme documentation disponible.

Actuellement, mon code ressemble à ceci:

Superclasse:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = SubA.class),
  @JsonSubTypes.Type(value = AnotherSub.class)
})
@Getter
@Accessors(fluent = true, chain = true)
@SuperBuilder
public abstract class AbstractA {

    @JsonProperty
    protected final String superProperty;
}

Et la sous-classe:

@Getter
@EqualsAndHashCode(callSuper = true)
@Accessors(fluent = true, chain = true)
@SuperBuilder
@JsonDeserialize(builder = SubA.SubABuilder.class) // class not found?
@JsonTypeName("SubA")
public class SubA extends AbstractA {

    @JsonProperty
    private final String fieldA;
}

Merci

9
Sebastian Thees

Une solution qui fonctionne dans Eclipse, notez que l'intégration de Lombok IntelliJ ne prend pas en charge toutes les fonctionnalités, donc le code compile bien dans Eclipse et avec javac mais IntelliJ pense qu'il est cassé mais exécute le code sans problème.

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

Mise à jour le 2018-11-10: Lombok 1.18.4 est sorti

Pour que @Builder Et @SuperBuilder De Lombok fonctionnent avec Jackson, vous devez ajouter manuellement l'en-tête de classe de générateur et y placer une @JsonPOJOBuilder(withPrefix=""). Lombok ne générera alors que le reste de la classe constructeur. Ceci est nécessaire parce que la valeur par défaut de Jackson est que les méthodes de définition du constructeur ont "avec" comme préfixe, mais les constructeurs de Lombok n'ont pas de préfixe (et Lombok n'est pas et ne sera probablement jamais configurable à cet égard).

Lorsque @SuperBuilder A été introduit dans Lombok 1.18.2, il n'était pas personnalisable (c'est-à-dire que vous ne pouviez pas ajouter manuellement l'en-tête de classe de générateur). Par conséquent, l'utilisation de @SuperBuilder Avec Jackson n'était pas facilement possible.

Cela a changé avec Lombok 1.18.4 (voir cette demande de tirage ): @SuperBuilder Est maintenant (au moins partiellement) personnalisable, ce qui nous permet d'ajouter l'annotation. Attention, le code généré par @SuperBuilder Est assez complexe et lourdement chargé en génériques. Pour éviter de gâcher accidentellement le code, vous devriez jeter un œil à la sortie delombok et copier/coller l'en-tête de classe à partir de là. Ici, vous devez ajouter l'en-tête de classe d'implémentation du générateur et y placer l'annotation:

@JsonPOJOBuilder(withPrefix="")
static final class SubABuilderImpl extends SubABuilder<SubA, SubABuilderImpl> {
}

Notez que vous devez élargir la visibilité de SubABuilderImpl à au moins package-private.

L'annotation @JsonDeserialize Doit également faire référence à la classe d'implémentation du générateur, pas au générateur abstrait:

@JsonDeserialize(builder = SubA.SubABuilderImpl.class)
7
Jan Rieke