不能让jackson和龙目岛一起工作

我正在尝试结合jackson和龙目岛。 这些是我的课程:

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

这些是我在classpth中添加的JAR:

  • 龙目岛: https ://projectlombok.org/downloads/lombok.jar(版本1.16.10)

  • jackson注释: http : //repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.8.2/jackson-annotations-2.8.2.jar

  • 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

我正在使用Netbeans进行编译(我不认为这是真的相关,但无论如何我都要报告这一点,以使其完美且忠实地再现)。 上面的五个JAR保存在项目文件夹中名为“ lib ”的文件夹中(以及“ src ”,“ nbproject ”,“ test ”和“ build ”)。 我通过项目属性中的“ 添加JAR /文件夹 ”按钮将它们添加到Netbeans中,它们按照上面列表的确切顺序列出。 该项目是标准的“Java应用程序”类型项目。

此外,Netbeans项目配置为“ 不保存时编译 ”,“ 生成调试信息 ”,“ 报告已弃用的API ”,“ 跟踪java依赖项 ”,“ 激活注释过程 ”和“ 在编辑器中激活注释过程 ”。 Netbeans中未明确配置注释处理器或注释处理选项。 此外,“- -Xlint:all ”命令行选项在编译器命令行中传递,编译器在外部VM上运行。

我的javac版本是1.8.0_72,我的java版本是1.8.0_72-b15。 我的Netbeans是8.1。

我的项目编译得很好。 但是,它会在执行时抛出exception。 exception似乎不是任何容易或明显可修复的东西。 这是输出,包括堆栈跟踪:

 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 

我已经尝试过使用@Value@AllArgsConstructor注释随机戳,但我无法做得更好。

我谷歌的例外, 发现了一个关于jackson的旧bug报告 , 另一个是开放的,但似乎与其他东西有关 。 但是,这仍然没有说明这个错误是什么或如何解决它。 此外,我找不到任何其他有用的东西。

因为我想要做的是lombok和jackson的非常基本的用法,我似乎找不到有关如何解决这个问题的更多有用信息似乎很奇怪。 也许我错过了什么?

除了说“ 不要使用lombok ”或“ 不要使用jackson ”之外,有没有人知道如何解决这个问题?

如果你想使用lombok和jackson的不可变但是json可序列化的POJO。 在你的lomboks构建器@JsonPOJOBuilder(withPrefix = "")上使用jacksons new注释@JsonPOJOBuilder(withPrefix = "")我试过这个解决方案并且效果很好。 样品用法

 import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import lombok.Builder; import lombok.Value; @JsonDeserialize(builder = Detail.DetailBuilder.class) @Value @Builder public class Detail { private String url; private String userName; private String password; private String scope; @JsonPOJOBuilder(withPrefix = "") public static class DetailBuilder { } } 

如果你有太多的@Builder类,并且你想要不需要样板代码空注释,你可以覆盖注释拦截器以使其具有空的withPrefix

 mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() { @Override public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) { if (ac.hasAnnotation(JsonPOJOBuilder.class)) {//If no annotation present use default as empty prefix return super.findPOJOBuilderConfig(ac); } return new JsonPOJOBuilder.Value("build", ""); } }); 

您可以使用@JsonPOJOBuilder注释删除空的构建器类。

我有完全相同的问题,通过添加suppressConstructorProperties = true参数(使用您的示例)“解决”它:

 @Value @Wither @AllArgsConstructor(suppressConstructorProperties = true) public class TestFoo { @JsonProperty("xoom") private String x; private int z; } 

jackson显然不喜欢将java.beans.ConstructorProperties注释添加到构造函数中。 suppressConstructorProperties = true参数告诉Lombok不要添加它(默认情况下它)。

不推荐使用@AllArgsConstructor(suppressConstructorProperties = true) 。 定义lombok.anyConstructor.suppressConstructorProperties=truehttps://projectlombok.org/features/configuration )并将POJO的@Value注释从@Value@Data + @NoArgsConstructor + @AllArgsConstructor适合我。

如果你使用“mixin”模式,你可以让Jackson玩几乎任何东西。 基本上,它为您提供了一种方法,可以将Jackson注释添加到现有类中,而无需实际修改该类。 我倾向于在这里推荐它而不是Lombok解决方案,因为这解决了jackson在Jacksonfunction方面遇到的问题,所以它更有可能长期工作。

你也需要这个模块。 https://github.com/FasterXML/jackson-modules-java8

然后打开编译器的-parameters标志。

     org.apache.maven.plugins maven-compiler-plugin 3.7.0   -parameters    

对我来说,当我将lombok版本更新为:’org.projectlombok:lombok:1.18.0’时,它才有用

我的所有课程都注释如下:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor 

它至少在几年内与所有Lombok和Jackson版本一起使用。

例:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor public class Person { String id; String first; String last; } 

就是这样。 龙目岛和jackson一起玩耍就像一个魅力。

 @JsonInclude(JsonInclude.Include.NON_NULL) @Data public class Person { String id; String first; String last; } 

除了Data Class之外,它应该正确配置ObjectMapper。 在这种情况下,它可以正常使用ParameterNamesModule配置,并设置Fields和Creator Methods的可见性

  om.registerModule(new ParameterNamesModule()); om.setVisibility(FIELD, JsonAutoDetect.Visibility.ANY); om.setVisibility(CREATOR, JsonAutoDetect.Visibility.ANY); 

然后它应该按预期工作。

我遇到了让Lombok不添加ConstructorProperies注释的问题,所以走了另一条道路并禁止Jackson查看该注释。

罪魁祸首是JacksonAnnotationIntrospector.findCreatorAnnotation 。 注意:

 if (_cfgConstructorPropertiesImpliesCreator && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES) 

另请注意JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator :

 public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b) { _cfgConstructorPropertiesImpliesCreator = b; return this; } 

因此有两个选项,要么将MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES设置为false,要么将JacksonAnnotationIntrospector设置为setConstructorPropertiesImpliesCreatorfalse并通过ObjectMapper.setAnnotationIntrospector将此AnnotationIntrospector设置为ObjectMapper 。

注意一些事情,我使用的是Jackson 2.8.10,在那个版本中MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES不存在。 我不确定它添加了哪个版本的Jackson。 因此,如果不存在,请使用JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator机制。