J'expérimente en combinant Jackson et Lombok. Ce sont mes cours:
package testelombok;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.experimental.Wither;
@Value
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
package testelombok;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xebia.jacksonlombok.JacksonLombokAnnotationIntrospector;
import java.io.IOException;
public class TestLombok {
public static void main(String[] args) throws IOException {
TestFoo tf = new TestFoo("a", 5);
System.out.println(tf.withX("b"));
ObjectMapper om = new ObjectMapper().setAnnotationIntrospector(new JacksonLombokAnnotationIntrospector());
System.out.println(om.writeValueAsString(tf));
TestFoo tf2 = om.readValue(om.writeValueAsString(tf), TestFoo.class);
System.out.println(tf2);
}
}
Ce sont les JAR que j'ajoute à la classe:
Lombok: https://projectlombok.org/downloads/lombok.jar (version 1.16.10)
Annotations de Jackson: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.8.2/jackson-annotations-2.8.2.jar
Noyau de Jackson: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.8.2/jackson-core-2.8.2.jar
Jackson databind: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.8.2/jackson-databind-2.8.2.jar
Jackson-lombok: http://repo1.maven.org/maven2/io/paradoxical/jackson-lombok/1.1/jackson-lombok-1.1.jar
Je le compile avec Netbeans (je ne pense pas que ce soit vraiment pertinent, mais je le rapporte quand même pour le rendre parfaitement et fidèlement reproductible). Les cinq fichiers JAR ci-dessus sont conservés dans un dossier appelé " lib
" à l'intérieur du dossier du projet (avec " src
", " nbproject
", " test
" et " build
"). Je les ai ajoutés à Netbeans via le bouton " Ajouter JAR / Dossier " dans les propriétés du projet et ils sont répertoriés dans l'ordre exact de la liste ci-dessus. Le projet est un projet standard de type "application Java".
De plus, le projet Netbeans est configuré pour " NE PAS compiler lors de la sauvegarde ", " générer des informations de débogage ", " signaler les API obsolètes ", " suivre les dépendances java ", "le traitement des annotations activacte " et "le traitement des annotations activacte dans l'éditeur ". Aucun processeur d'annotation ou option de traitement d'annotation n'est explicitement configuré dans Netbeans. En outre, l' -Xlint:all
option de ligne de commande " " est transmise dans la ligne de commande du compilateur et le compilateur s'exécute sur une machine virtuelle externe.
La version de mon javac est 1.8.0_72 et la version de ma java est 1.8.0_72-b15. Mon Netbeans est 8.1.
Mon projet se compile bien. Cependant, il lève une exception dans son exécution. L'exception ne semble pas être tout ce qui semble facilement réparable ou évident. Voici la sortie, y compris le stacktrace:
TestFoo(x=b, z=5)
{"z":5,"xoom":"a"}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at [Source: {"z":5,"xoom":"a"}; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:296)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:269)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:475)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3890)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3785)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)
at testelombok.TestLombok.main(TestLombok.java:14)
Caused by: java.lang.IllegalArgumentException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(BasicDeserializerFactory.java:511)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:323)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:253)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:219)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
... 7 more
J'ai déjà essayé de piquer au hasard avec les annotations @Value
et @AllArgsConstructor
, mais je ne pouvais pas faire mieux.
J'ai cherché l'exception sur Google et j'ai trouvé un ancien rapport de bogue sur jackson , et un autre qui est ouvert, mais semble être lié à autre chose . Cependant, cela ne dit toujours rien sur ce qu'est ce bogue ou comment le corriger. De plus, je n'ai rien trouvé d'utile à chercher ailleurs.
Étant donné que ce que j'essaie de faire est une utilisation très basique de lombok et de jackson, il semble étrange que je ne puisse pas trouver d'informations plus utiles sur la façon de contourner ce problème. Peut-être ai-je manqué quelque chose?
À part simplement de dire « n'utilisez pas lombok » ou « n'utilisez pas jackson », est-ce que quelqu'un a une idée sur la façon de résoudre ce problème?
Immutable + Lombok + Jackson peut être réalisé de la manière suivante:
import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.Value; @Value @NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) @AllArgsConstructor public class LocationDto { double longitude; double latitude; } class ImmutableWithLombok { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); String stringJsonRepresentation = objectMapper.writeValueAsString(new LocationDto(22.11, 33.33)); System.out.println(stringJsonRepresentation); LocationDto locationDto = objectMapper.readValue(stringJsonRepresentation, LocationDto.class); System.out.println(locationDto); } }
la source
AllArgsConstructor
déjà partie de l'@Value
annotation?@NoArgsConstructor
remplace le constructeur qui est généré par l'@Value
annotation, vous devez donc ajouter le supplément@AllArgsConstructor
J'ai essayé plusieurs des solutions ci-dessus et elles étaient toutes capricieuses. Ce qui a vraiment fonctionné pour moi, c'est la réponse que j'ai trouvée ici .
sur le répertoire racine de votre projet, ajoutez un fichier lombok.config (si vous ne l'avez pas déjà fait)
et à l'intérieur, collez ceci
lombok.anyConstructor.addConstructorProperties=true
Ensuite, vous pouvez définir vos pojos comme suit:
@Data @AllArgsConstructor public class MyPojo { @JsonProperty("Description") private String description; @JsonProperty("ErrorCode") private String errorCode; }
la source
J'ai eu exactement le même problème, je l'ai "résolu" en ajoutant le
suppressConstructorProperties = true
paramètre (en utilisant votre exemple):@Value @Wither @AllArgsConstructor(suppressConstructorProperties = true) public class TestFoo { @JsonProperty("xoom") private String x; private int z; }
Jackson n'aime apparemment pas l'
java.beans.ConstructorProperties
annotation ajoutée aux constructeurs. LesuppressConstructorProperties = true
paramètre dit à Lombok de ne pas l'ajouter (il le fait par défaut).la source
suppressConstructorProperties
est maintenant obsolète :-(false
.@AllArgsConstructor(suppressConstructorProperties = true)
est obsolète. Définirlombok.anyConstructor.suppressConstructorProperties=true
( https://projectlombok.org/features/configuration ) et changer l'annotation lombok de POJO de@Value
en@Data
+@NoArgsConstructor
+@AllArgsConstructor
fonctionne pour moi.la source
Pour moi, cela a fonctionné lorsque j'ai mis à jour la version de lombok vers: 'org.projectlombok: lombok: 1.18.0'
la source
D'après la réponse de Jan Rieke
Vous aurez besoin d'un @JsonProperty sur chaque champ même si le nom correspond, mais c'est une bonne pratique à suivre quand même. Vous pouvez également définir vos champs en public final en utilisant ceci, ce que je préfère aux getters.
@ToString @EqualsAndHashCode @Wither @AllArgsConstructor(onConstructor=@__(@JsonCreator)) public class TestFoo { @JsonProperty("xoom") public final String x; @JsonProperty("z") public final int z; }
Cela devrait également fonctionner avec les getters (+ setters).
la source
Can not deserialize instance of java.lang.String out of START_OBJECT token
... Et cela l'a corrigé! J'ai besoin d'avoir cette@JsonProperty
annotation pour chaque paramètre du constructeur et cet ajout au@AllArgsConstructor
permet à lombok d'instrumenter cela.Vous pouvez faire jouer à Jackson à peu près n'importe quoi si vous utilisez son motif "mixin" . Fondamentalement, cela vous donne un moyen d'ajouter des annotations Jackson sur une classe existante sans modifier réellement cette classe. Je préfère la recommander ici plutôt qu'une solution Lombok, car cela résout un problème que Jackson rencontre avec une fonctionnalité Jackson, donc il est plus susceptible de fonctionner à long terme.
la source
J'ai toutes mes classes annotées comme ceci:
@JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor
Cela a fonctionné avec toutes les versions de Lombok et Jackson pendant au moins quelques années.
Exemple:
@JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor public class Person { String id; String first; String last; }
Et c'est tout. Lombok et Jackson jouent ensemble comme un charme.
la source
@JsonInclude(JsonInclude.Include.NON_NULL) @Data public class Person { String id; String first; String last; }
En plus de la classe de données, il doit être correctement configuré l'ObjectMapper. Dans ce cas, cela fonctionne bien avec une configuration ParameterNamesModule et la définition de la visibilité des champs et des méthodes de créateur
om.registerModule(new ParameterNamesModule()); om.setVisibility(FIELD, JsonAutoDetect.Visibility.ANY); om.setVisibility(CREATOR, JsonAutoDetect.Visibility.ANY);
Ensuite, cela devrait fonctionner comme prévu.
la source
J'avais des problèmes pour que Lombok n'ajoute pas l'
ConstructorProperies
annotation, alors je suis allé dans l'autre sens et j'ai désactivé Jackson de regarder cette annotation.Le coupable est JacksonAnnotationIntrospector.findCreatorAnnotation . Remarquer:
if (_cfgConstructorPropertiesImpliesCreator && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
Notez également JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator :
public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b) { _cfgConstructorPropertiesImpliesCreator = b; return this; }
Donc, deux options, définissez le
MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
sur false ou créez unJacksonAnnotationIntrospector
ensemblesetConstructorPropertiesImpliesCreator
surfalse
et définissez celaAnnotationIntrospector
dansObjectMapper
via ObjectMapper.setAnnotationIntrospector .Remarquez quelques choses, j'utilise Jackson 2.8.10 et dans cette version
MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
n'existe pas. Je ne sais pas dans quelle version de Jackson il a été ajouté. Donc, si ce n'est pas là, utilisez leJacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
mécanisme.la source
Vous devez également avoir ce module. https://github.com/FasterXML/jackson-modules-java8
puis activez l'indicateur -parameters pour votre compilateur.
<build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin>
la source
J'ai également eu du mal avec ça pendant un moment. Mais en parcourant la documentation ici, je peux voir que le paramètre d'annotation onConstructor est considéré comme expérimental et n'est pas bien pris en charge sur mon IDE (STS 4). Selon la documentation de Jackson, les membres privés ne sont pas (dé) sérialisés par défaut. Il existe des moyens rapides de résoudre ce problème.
Ajoutez l'annotation JsonAutoDetect et définissez-la de manière appropriée pour détecter les membres protégés / privés. Ceci est pratique pour les DTO
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class SomeClass
Ajoutez une fonction de fabrique avec l'annotation @JsonCreator, cela fonctionne mieux si vous avez besoin d'une validation d'objet ou de transformations supplémentaires.
public class SomeClass { // some code here @JsonCreator public static SomeClass factory(/* params here dressing them in @JsonProperty annotations*/) { return new SomeClass(); } }
Bien sûr, vous pouvez également ajouter manuellement le constructeur en vous-même.
la source
J'ai eu un problème différent et c'était avec les types primitifs booléens.
private boolean isAggregate;
Il lançait l'erreur suivante en conséquence
Exception: Unrecognized field "isAggregate" (class
Lambok convertis
isAggregate
àisAggregate()
un getter rendant la propriété à l' intérieur comme LOMBOK à laaggregate
placeisAggregate
. La bibliothèque Jackson ne l'aime pas et elle a besoin deisAggregate
propriété à la place.J'ai mis à jour le booléen primitif en Wrapper Boolean pour contourner ce problème. Il existe d'autres options pour vous si vous traitez avec des
boolean
types, voir la référence ci-dessous.Sol:
private Boolean isAggregate;
réf: https://www.baeldung.com/lombok-getter-boolean
la source