当前位置: 首页 > 知识库问答 >
问题:

为什么在使用Lombok@数据时,我的基于字段的Jackson混音会中断?

诸彬郁
2023-03-14

我有一个同时使用Jackson和Lombok的项目。它正在使用两者的当前最新版本(Jackson 2.12.2

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

但是,如果我更改示例以使用Lombok的@Data自动生成getter

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

输出:

Default: null
Mixin: null

当我切换到使用数据时,为什么这不起作用?我在Jackson的数据或Getter和Setter文档中没有看到任何东西表明这应该以这种方式进行。

共有2个答案

公西兴业
2023-03-14

Lombok@Data等效于@Getter@Setter@必需ArgsConstructor@ToString@EqualsAndHashCode。

默认构造函数没有参数,lombok@Data有参数。您需要添加@noargsconstuctor。

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

    @Data
    @NoArgsConstructor
    private abstract static class ExampleMixin {
        @JsonProperty(access = JsonProperty.Access.READ_WRITE)
        private String value;
    }
夏侯兴怀
2023-03-14

问题是Lombok正在将Jackson@JsonProperty注释复制到生成的setter。在Jackson中,访问器方法上的注释优先于字段上的相同注释。因此,示例类中getValue()方法上的注释正在覆盖value字段上的注释。

这可以通过多种方式修复。可以手动或使用@Setter注释混音字段来更改混音以具有Jackson注释的setter(从而触发Lombok setter的覆盖):

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

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

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

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

整个情况的一个棘手之处是,将Jackson注释复制到setter的事实在Lombok中没有记录。留档提到可空性注释被复制,但没有提到复制的Jackson注释:

龙目岛。copyableAnnotations=[完全限定类型的列表](默认值:空列表)Lombok将把这些注释中的任何一个从字段复制到setter参数和getter方法。请注意,lombok附带了一组“开箱即用”的注释,这些注释都是可复制的:所有流行的可空/非空注释。

关于可空性的各种著名注释,如org。日食jdt。注释。非null会自动复制到正确的位置(getters的方法,setters的参数)。您可以指定应始终通过lombok配置键复制的其他注释。可复制批注。

然而,查看Lombok源代码会发现复制的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现场问题,包括缺乏文档,在Lombok问题跟踪程序中被捕获为问题#2769。

 类似资料:
  • 目前,我正在尝试在这里实现汽车示例的变体: https://www.elastic.co/blog/managing-relations-inside-elasticsearch 如果我运行: 代码工作正常。 但是如果我删除索引并将2015从字符串更改为数字: 我收到以下错误消息: {“error”:{“root\u-cause”:[{“type”:“非法\u-argument\u-excepti

  • 我有一个带有索引的ISODate()类型字段的数据库(我也用字符串字段尝试了这个实验——结果相同)。我使用的是MongoDB(4. x)的开源版本,当我进行查询/排序以查找最大_finish_time时,除非我指定提示,否则不会使用索引。 我的问题是: 这解释为: 扫描整个收藏。当我为可用索引指定提示时,如: 我得到了查询计划: 它使用索引。我不想在查询中添加hint(),我对它为什么拒绝使用索引

  • 问题内容: 考虑具有一个字符串和两个数组的JSON表示形式。例如, 在上述情况下,需要现场,但和被 有条件地 基于所述值所需的反序列化。换句话说,如果只需要有值和如果只要求有一个值。 当前,我在Jackson和Java中工作,并且能够通过创建以下代码来实现使字段成为强制性的: 但我不能只是附加其他到或因为它依赖的价值。 我怎么能有条件地要求和反序列化基础上的价值? 另外,我将要执行额外的检查,例如

  • 问题内容: 我有一个具有字段()的Spring 类(),但是该字段是我尝试使用它时所用的。日志显示该bean和该bean都在创建,但是每当我尝试在服务bean上调用该方法时,都会得到一个a 。Spring为什么不自动接线该领域? 控制器类: 服务等级: 应该自动连接的服务bean,但不是: 当我尝试时,出现以下异常: 问题答案: 本文向大家介绍为什么我的Spring @Autowired字段为空?

  • 这是我的班级: Lombok将添加所有参数构造函数。 我需要将一个字符串反序列化为一个POJO对象。 我创建了以下包含所有三个属性的Jackson mixin: 我这样描述: 但是我得到了这个错误:

  • 问题内容: 基数实际上是什么意思?我们为什么需要它? 问题答案: 您可能并不总是希望将整数解析为以10为底的数字,因此提供基数可以指定其他数字系统。 基数是一位数字的值数。十六进制为16。八进制为8,二进制为2,依此类推… 在该函数中,您可以执行一些操作来提示基数而不提供基数。如果用户输入的字符串与其中一个规则匹配,但没有明确规定,则这些方法也可能对您不利。例如: