我有一个项目同时使用 Jackson和 Lombok 。它使用两者的当前最新版本(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 keylombok.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/