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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:05:23  来源:igfitidea点击:

Can't make Hymanson and Lombok work together

javanetbeansHymansonlombok

提问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:

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 @Valueand @AllArgsConstructorannotations, 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 = trueparameter (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.ConstructorPropertiesannotation added to constructors. The suppressConstructorProperties = trueparameter 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 @Valueto @Data+ @NoArgsConstructor+ @AllArgsConstructorworks for me.

@AllArgsConstructor(suppressConstructorProperties = true)已弃用。定义lombok.anyConstructor.suppressConstructorProperties=truehttps://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 @Builderand 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 @JsonPOJOBuilderannotation.

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

回答by John B

I was having issues with getting Lombok to not add the ConstructorProperiesannotation 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_PROPERTIESto false or create a HymansonAnnotationIntrospectorset setConstructorPropertiesImpliesCreatorto falseand set this AnnotationIntrospectorinto the ObjectMappervia ObjectMapper.setAnnotationIntrospector.

所以有两个选项,要么将 the 设置MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES为 false 要么创建一个HymansonAnnotationIntrospectorset setConstructorPropertiesImpliesCreatortofalse并将其设置AnnotationIntrospectorObjectMappervia ObjectMapper.setAnnotationIntrospector

Notice a couple things, I am using Hymanson 2.8.10 and in that version MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIESdoes not exist. I am not sure in which version of Hymanson it was added. So if it is not there, use the HymansonAnnotationIntrospector.setConstructorPropertiesImpliesCreatormechanism.

请注意一些事情,我使用的是 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);
    }
}