java - 为什么我的基于字段的 Jackson mixin 在使用 Lombok @Data 时会中断?

标签 java jackson lombok jackson-databind

我有一个项目同时使用 JacksonLombok 。它使用两者的当前最新版本(Jackson 2.12.2 和 Lombok 1.18.18)。我有以下包含 Jackson 映射对象的类,以及关联的 Jackson mixin ,允许反序列化是否忽略给定字段,具体取决于 mixin 是否传递给 ObjectMapper:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.json.JsonMapper;

public class IssueDemonstration {
    public static void main(String[] args) throws JsonProcessingException {
        JsonMapper jsonMapper = JsonMapper.builder().build();
        JsonMapper mixinMapper = JsonMapper.builder()
                .addMixIn(Example.class, ExampleMixin.class).build();

        String json = "{\"value\": \"Some Value\"}";
        System.out.println(
                "Default: " + jsonMapper.readValue(json, Example.class).getValue());
        System.out.println(
                "Mixin: " + mixinMapper.readValue(json, Example.class).getValue());
    }

    private static class Example {
        @JsonProperty(access = JsonProperty.Access.READ_ONLY)
        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

    private abstract static class ExampleMixin {
        @JsonProperty(access = JsonProperty.Access.READ_WRITE)
        private String value;
    }
}

上面的代码给出了预期的结果:

Default: null
Mixin: Some Value

但是,如果我将 Example 更改为使用 Lombok 的 @Data要自动生成 getter 和 setter,mixin 不再起作用:

@Data
private static class Example {
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private String value;
}

输出:

Default: null
Mixin: null

为什么当我切换到使用 @Data 时这不起作用?我在 jackson 身上什么也没看到@Data@Getter and @Setter表明这应该以这种方式运行的文档。

最佳答案

问题是 Lombok 正在复制 Jackson @JsonProperty对生成的 setter 进行注释。在 Jackson 中,访问器方法上的注释优先于字段上的相同注释。因此,对 getValue() 进行注释Example中的方法类正在覆盖 value 上的注释领域 ExampleMixin .

可以通过多种方式解决此问题。 mixin 可以更改为具有 Jackson 注释的 setter(从而触发 Lombok setter 的覆盖),可以手动或通过使用 @Setter 注释 mixin 字段。 :

private interface ExampleMixin {
    @JsonProperty(access = JsonProperty.Access.READ_WRITE)
    void setValue(String value);
}
private abstract static class ExampleMixin {
    @Setter
    @JsonProperty(access = JsonProperty.Access.READ_WRITE)
    private String value;
}

或者,可以将反序列化的类更改为除了带注释的字段之外还为其创建一个未注释的手动 setter ,从而防止 Lombok 创建带注释的 setter :

@Data
private static class Example {
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private String value;

    public void setValue(String value) {
        this.value = value;
    }
}

关于整个情况的一个棘手的事情是,Lombok 中没有记录将 Jackson 注释复制到 setter 的事实。 documentation提到可空性注释被复制,但没有提及复制的 Jackson 注释:

lombok.copyableAnnotations = [A list of fully qualified types] (default: empty list) Lombok will copy any of these annotations from the field to the setter parameter, and to the getter method. Note that lombok ships with a bunch of annotations 'out of the box' which are known to be copyable: All popular nullable/nonnull annotations.

Various well-known annotations about nullability, such as org.eclipse.jdt.annotation.NonNull, are automatically copied over to the right place (method for getters, parameter for setters). You can specify additional annotations that should always be copied via lombok configuration key lombok.copyableAnnotations.

看看Lombok source code但是,显示了复制的 Jackson 注释:

COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
    "com.fasterxml.jackson.annotation.JacksonInject",
    "com.fasterxml.jackson.annotation.JsonAlias",
    "com.fasterxml.jackson.annotation.JsonFormat",
    "com.fasterxml.jackson.annotation.JsonIgnore",
    "com.fasterxml.jackson.annotation.JsonIgnoreProperties",
    "com.fasterxml.jackson.annotation.JsonProperty",
    "com.fasterxml.jackson.annotation.JsonSetter",
    "com.fasterxml.jackson.annotation.JsonSubTypes",
    "com.fasterxml.jackson.annotation.JsonTypeInfo",
    "com.fasterxml.jackson.annotation.JsonView",
    "com.fasterxml.jackson.databind.annotation.JsonDeserialize",
    "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty",
}));

mixin 字段问题(包括缺乏文档)被捕获为问题 #2769在 Lombok 问题跟踪器中。

关于java - 为什么我的基于字段的 Jackson mixin 在使用 Lombok @Data 时会中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66597368/

相关文章:

游戏的 Java 2D 数组对角线

java - 使用 lucene 的荧光笔和完整性的问题。

java - 在 Java 中使用 BigIntegers 进行 BitShifting

java - 使用 Jackson 处理 @RequestBody 中的 Null 和 Default 值

java - 在设置变量之前检查 null - 没有 if-else

java - IDE 不显示 Lombok 为 Jackson 注解的类生成的 getter 和 setter

Java批量重启不处理步骤

java - 如何在 webflux 中异步解析/写入 json? ObjectMapper 方法是阻塞的

Java Spring Web - 使用 validator 将子属性转换为对象

java - 在 Java 中使用注释使所有参数成为最终参数