Java 不能让杰克逊和龙目岛一起工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39381474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can't make Hymanson and Lombok work together
提问by Victor Stafusa
I am experimenting in combining Hymanson and Lombok. Those are my classes:
我正在尝试结合Hyman逊和龙目岛。这些是我的课程:
package testelombok;
import com.fasterxml.Hymanson.annotation.JsonCreator;
import com.fasterxml.Hymanson.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.Hymanson.databind.ObjectMapper;
import com.xebia.Hymansonlombok.HymansonLombokAnnotationIntrospector;
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 HymansonLombokAnnotationIntrospector());
System.out.println(om.writeValueAsString(tf));
TestFoo tf2 = om.readValue(om.writeValueAsString(tf), TestFoo.class);
System.out.println(tf2);
}
}
Those are the JARs that I'm adding into the classpth:
这些是我添加到 classpth 中的 JAR:
Lombok: https://projectlombok.org/downloads/lombok.jar(version 1.16.10)
Hymanson annotations: http://repo1.maven.org/maven2/com/fasterxml/Hymanson/core/Hymanson-annotations/2.8.2/Hymanson-annotations-2.8.2.jar
Hymanson core: http://repo1.maven.org/maven2/com/fasterxml/Hymanson/core/Hymanson-core/2.8.2/Hymanson-core-2.8.2.jar
Hymanson databind: http://repo1.maven.org/maven2/com/fasterxml/Hymanson/core/Hymanson-databind/2.8.2/Hymanson-databind-2.8.2.jar
Hymanson-lombok: http://repo1.maven.org/maven2/io/paradoxical/Hymanson-lombok/1.1/Hymanson-lombok-1.1.jar
龙目岛:https://projectlombok.org/downloads/lombok.jar(版本 1.16.10)
Hyman逊注释:http: //repo1.maven.org/maven2/com/fasterxml/Hymanson/core/Hymanson-annotations/2.8.2/Hymanson-annotations-2.8.2.jar
Hyman逊核心:http: //repo1.maven.org/maven2/com/fasterxml/Hymanson/core/Hymanson-core/2.8.2/Hymanson-core-2.8.2.jar
Hyman逊数据绑定:http: //repo1.maven.org/maven2/com/fasterxml/Hymanson/core/Hymanson-databind/2.8.2/Hymanson-databind-2.8.2.jar
Hyman逊龙目岛:http://repo1.maven.org/maven2/io/paradoxical/Hymanson-lombok/1.1/Hymanson-lombok-1.1.jar
I am compiling it with Netbeans (I don't think that this is really relevant, but I am reporting this anyway to make it perfectly and faithfully reproducible). The five JARs above are kept in a folder called "lib
" inside the project folder (along with "src
", "nbproject
", "test
" and "build
"). I added them to Netbeans via the "Add JAR/Folder" button in the project properties and they are listed in the exact order as the list above. The project is a standard "Java application" type project.
我正在用 Netbeans 编译它(我不认为这真的很相关,但我无论如何都会报告这个以使其完美且忠实地重现)。上面的五个 JAR 保存在lib
项目文件夹内一个名为“ ”的文件夹中(以及“ src
”、“ nbproject
”、“ test
”和“ build
”)。我通过项目属性中的“添加 JAR/文件夹”按钮将它们添加到 Netbeans ,它们按照上面列表的确切顺序列出。该项目是一个标准的“Java 应用程序”类型的项目。
Further, the Netbeans project is configured to "do NOT compile on save", "generate debugging info", "report deprecated APIs", "track java dependencies", "activacte annotation proccessing" and "activacte annotation proccessing in the editor". No annotation processor or annotation processing option is explicitly configured in Netbeans. Also, the "-Xlint:all
" command line option is passed in the compiler command line, and the compiler runs on an external VM.
此外,Netbeans 项目被配置为“在保存时不编译”、“生成调试信息”、“报告不推荐使用的 API”、“跟踪 Java 依赖项”、“激活注释处理”和“在编辑器中激活注释处理”。Netbeans 中没有明确配置注释处理器或注释处理选项。此外,“ -Xlint:all
”命令行选项在编译器命令行中传递,编译器在外部 VM 上运行。
My javac's version is 1.8.0_72 and my java's version is 1.8.0_72-b15. My Netbeans is 8.1.
我的javac 版本是1.8.0_72,我的java 版本是1.8.0_72-b15。我的 Netbeans 是 8.1。
My project compiles fine. However, it throws an exception in its execution. The exception don't seems to be anything that looks easily or obvious fixable. Here is the output, including the stacktrace:
我的项目编译得很好。但是,它在执行过程中会抛出异常。例外似乎不是任何看起来容易或明显可以修复的东西。这是输出,包括堆栈跟踪:
TestFoo(x=b, z=5)
{"z":5,"xoom":"a"}
Exception in thread "main" com.fasterxml.Hymanson.databind.JsonMappingException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.Hymanson.annotation.JsonCreator=@com.fasterxml.Hymanson.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.Hymanson.databind.JsonMappingException.from(JsonMappingException.java:296)
at com.fasterxml.Hymanson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:269)
at com.fasterxml.Hymanson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.Hymanson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.Hymanson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:475)
at com.fasterxml.Hymanson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3890)
at com.fasterxml.Hymanson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3785)
at com.fasterxml.Hymanson.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.Hymanson.annotation.JsonCreator=@com.fasterxml.Hymanson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at com.fasterxml.Hymanson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(BasicDeserializerFactory.java:511)
at com.fasterxml.Hymanson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:323)
at com.fasterxml.Hymanson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:253)
at com.fasterxml.Hymanson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:219)
at com.fasterxml.Hymanson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
at com.fasterxml.Hymanson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
at com.fasterxml.Hymanson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
at com.fasterxml.Hymanson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
... 7 more
I already tried about randomly poking with the @Value
and @AllArgsConstructor
annotations, but I couldn't make it any better.
我已经尝试过使用@Value
和@AllArgsConstructor
注释随机戳,但我无法让它变得更好。
I google'd the exception and found an old bug report on Hymanson, and another one that is open, but seems to be related to something else. However, this still do not tells anything about what is this bug or how to fix it. Also, I could not find anything useful looking that somewhere else.
我用谷歌搜索了异常,发现了一个关于 Hymanson 的旧错误报告,另一个是开放的,但似乎与其他东西有关。但是,这仍然没有说明此错误是什么或如何修复它。另外,我在其他地方找不到任何有用的东西。
Since what I am trying to do is very basic usage of both lombok and Hymanson, it seems odd that I couldn't find any more useful information about how to workaround this issue. Maybe I missed something?
由于我正在尝试做的是 lombok 和 Hymanson 的非常基本的用法,因此我找不到有关如何解决此问题的更多有用信息似乎很奇怪。也许我错过了什么?
Other than just saying "don't use lombok" or "don't use Hymanson", do anybody has any idea about how to solve this?
除了只是说“不要使用 lombok”或“不要使用 Hymanson”之外,有人知道如何解决这个问题吗?
回答by David Ehrmann
You can get Hymanson to play with just about anything if you use its "mixin" pattern. Basically, it gives you a way to add Hymanson annotations onto an existing class without actually modifying that class. I'm leaning towards recommending it here rather than a Lombok solution because this is solves a problem Hymanson is having with a Hymanson feature, so it's more likely to work long-term.
如果你使用它的“mixin”模式,你可以让Hyman逊玩任何东西。基本上,它为您提供了一种将 Hymanson 注释添加到现有类的方法,而无需实际修改该类。我倾向于在这里推荐它而不是 Lombok 解决方案,因为这解决了 Hymanson 使用 Hymanson 功能时遇到的问题,因此它更有可能长期工作。
回答by Donovan Muller
I had exactly the same issue, "solved" it by adding the suppressConstructorProperties = true
parameter (using your example):
我遇到了完全相同的问题,通过添加suppressConstructorProperties = true
参数来“解决”它(使用您的示例):
@Value
@Wither
@AllArgsConstructor(suppressConstructorProperties = true)
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
Hymanson apparently does not like the java.beans.ConstructorProperties
annotation added to constructors. The suppressConstructorProperties = true
parameter tells Lomboknot to add it (it does by default).
Hyman逊显然不喜欢java.beans.ConstructorProperties
添加到构造函数的注释。该suppressConstructorProperties = true
参数告诉Lombok不要添加它(默认情况下会添加)。
回答by where_
I've all my classes annotated like this:
我所有的课程都这样注释:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
It worked with all Lombok and Hymanson versions for, at least, a couple of years.
它适用于所有 Lombok 和 Hymanson 版本至少几年。
Example:
例子:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
public class Person {
String id;
String first;
String last;
}
And that's it. Lombok and Hymanson play together like a charm.
就是这样。Lombok 和 Hymanson 在一起玩得很有魅力。
回答by Hector Delgado
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public class Person {
String id;
String first;
String last;
}
Additional to the Data Class, it should be correct configured the ObjectMapper. In this case, it is working ok with a ParameterNamesModule configuration, and setting visibility of Fields and Creator Methods
除了数据类之外,应该正确配置ObjectMapper。在这种情况下,使用 ParameterNamesModule 配置并设置字段和创建者方法的可见性可以正常工作
om.registerModule(new ParameterNamesModule());
om.setVisibility(FIELD, JsonAutoDetect.Visibility.ANY);
om.setVisibility(CREATOR, JsonAutoDetect.Visibility.ANY);
Then it should work as expected.
然后它应该按预期工作。
回答by yyy
@AllArgsConstructor(suppressConstructorProperties = true)
is deprecated. Define lombok.anyConstructor.suppressConstructorProperties=true
(https://projectlombok.org/features/configuration) and change POJO's lombok annotation from @Value
to @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
works for me.
@AllArgsConstructor(suppressConstructorProperties = true)
已弃用。定义lombok.anyConstructor.suppressConstructorProperties=true
(https://projectlombok.org/features/configuration)和变化POJO的距离Lombok标注@Value
到@Data
+ @NoArgsConstructor
+@AllArgsConstructor
为我工作。
回答by ganesan dharmalingam
If you want immutable but a json serializable POJO using lombok and Hymanson.
Use Hymansons new annotation on your lomboks builder @JsonPOJOBuilder(withPrefix = "")
I tried this solution and it works very well.
Sample usage
如果您想要不可变但使用 lombok 和 Hymanson 的 json 可序列化 POJO。在你的 lomboks builder 上使用 Hymansons new annotation@JsonPOJOBuilder(withPrefix = "")
我试过这个解决方案,它工作得很好。示例用法
import com.fasterxml.Hymanson.databind.annotation.JsonDeserialize;
import com.fasterxml.Hymanson.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 {
}
}
If you have too many classes with @Builder
and you want don't want the boilerplate code empty annotation you can override the annotation interceptor to have empty withPrefix
如果您有太多的类,@Builder
并且您不希望样板代码为空注释,则可以覆盖注释拦截器以使其为空withPrefix
mapper.setAnnotationIntrospector(new HymansonAnnotationIntrospector() {
@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", "");
}
});
And you can remove the empty builder class with @JsonPOJOBuilder
annotation.
您可以使用@JsonPOJOBuilder
注释删除空的构建器类。
回答by John B
I was having issues with getting Lombok to not add the ConstructorProperies
annotation so went the other way and disabled Hymanson from looking at that annotation.
我在让 Lombok 不添加ConstructorProperies
注释时遇到问题,所以反其道而行之,使 Hymanson 无法查看该注释。
The culprit is HymansonAnnotationIntrospector.findCreatorAnnotation. Notice:
罪魁祸首是HymansonAnnotationIntrospector.findCreatorAnnotation。注意:
if (_cfgConstructorPropertiesImpliesCreator
&& config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
Also notice HymansonAnnotationIntrospector.setConstructorPropertiesImpliesCreator:
还要注意HymansonAnnotationIntrospector.setConstructorPropertiesImpliesCreator:
public HymansonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b)
{
_cfgConstructorPropertiesImpliesCreator = b;
return this;
}
So two options, either set the MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
to false or create a HymansonAnnotationIntrospector
set setConstructorPropertiesImpliesCreator
to false
and set this AnnotationIntrospector
into the ObjectMapper
via ObjectMapper.setAnnotationIntrospector.
所以有两个选项,要么将 the 设置MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
为 false 要么创建一个HymansonAnnotationIntrospector
set setConstructorPropertiesImpliesCreator
tofalse
并将其设置AnnotationIntrospector
为ObjectMapper
via ObjectMapper.setAnnotationIntrospector。
Notice a couple things, I am using Hymanson 2.8.10 and in that version MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
does not exist. I am not sure in which version of Hymanson it was added. So if it is not there, use the HymansonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
mechanism.
请注意一些事情,我使用的是 Hymanson 2.8.10 并且在该版本MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
中不存在。我不确定它是在哪个版本的 Hymanson 中添加的。因此,如果它不存在,请使用该HymansonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
机制。
回答by Matt Broekhuis
You need to have this module as well. https://github.com/FasterXML/Hymanson-modules-java8
你也需要有这个模块。 https://github.com/FasterXML/Hymanson-modules-java8
then turn on -parameters flag for your compiler.
然后为您的编译器打开 -parameters 标志。
<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>
回答by fascynacja
For me it worked when I have updated lombok version to: 'org.projectlombok:lombok:1.18.0'
对我来说,当我将 lombok 版本更新为:'org.projectlombok:lombok:1.18.0' 时它起作用了
回答by Alex Efimov
Immutable + Lombok + Hymanson can be achieved in next way:
Immutable + Lombok + Hymanson 可以通过以下方式实现:
import com.fasterxml.Hymanson.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);
}
}