Quelle est la méthode préférée pour créer une classe qui est
De préférence, j'aurais aimé que quelque chose comme ça marche:
@Data(onConstructor = @__(@JsonCreator))
et puis tous les champs à être private final
. Cependant, cela ne compile même pas (et je ne sais pas pourquoi). En utilisant
@AllArgsConstructor(onConstructor = @__(@JsonCreator))
compilera mais seulement les rendements
InvalidDefinitionException: No serializer found for class
Une autre alternative qui:
est d'ajouter ConstructorProperties :
lombok.config
dans un emplacement approprié avec la ligne suivante: lombok.anyConstructor.addConstructorProperties = true
@Value
à votre classe pour la rendre immuableEnsuite, la sérialisation et la désérialisation par Jackson fonctionnent comme prévu.
Vous pouvez utiliser @Builder
annotation de Lombok pour générer un générateur pour votre classe POJO immuable. Mais rendre le générateur généré par Lombok utilisable par la désérialisation de Jackson est un peu délicat.
@JsonDeserialize(builder = ...)
Pour indiquer à Jackson quelle est la classe de générateur à utiliser.@JsonPOJOBuilder(withPrefix = "")
Pour indiquer à Jackson que ses méthodes de définition font not commencent par with
.Exemple:
Une classe immuable de POJO:
@Data
@Builder(builderClassName = "PointBuilder")
@JsonDeserialize(builder = Point.PointBuilder.class)
public class Point {
private final int x;
private final int y;
@JsonPOJOBuilder(withPrefix = "")
public static class PointBuilder {
// Lombok will add constructor, setters, build method
}
}
Voici un test JUnit pour vérifier la sérialisation/désérialisation:
public class PointTest extends Assert {
private ObjectMapper objectMapper = new ObjectMapper();
@Test
public void testSerialize() throws IOException {
Point point = new Point(10, 20);
String json = objectMapper.writeValueAsString(point);
assertEquals("{\"x\":10,\"y\":20}", json);
}
@Test
public void testDeserialize() throws IOException {
String json = "{\"x\":10,\"y\":20}";
Point point = objectMapper.readValue(json, Point.class);
assertEquals(new Point(10, 20), point);
}
}
Une autre alternative beaucoup moins verbeuse:
@Data
@Setter(AccessLevel.NONE)
public class Clazz {
private String field;
}
Bien sûr, vous pouvez toujours avoir une méthode privée qui modifie le champ directement, mais il serait très improbable d'avoir même du code dans un POJO @Data, donc cela ne se produirait pas.
Disclaimer: Ceci aura pour effet secondaire (peut-être bénéfique) de ne pas laisser le code Java normal créer l'objet car il n'y a qu'un constructeur par défaut sans mutateurs. Pour permettre une construction normale, vous aurez besoin de 2 annotations supplémentaires:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Setter(AccessLevel.NONE)
public class Clazz {
private String field;
}