Jackson 使用 mixin 对 Lombok @Builder 类进行反序列化不起作用

Posted

技术标签:

【中文标题】Jackson 使用 mixin 对 Lombok @Builder 类进行反序列化不起作用【英文标题】:Jackson deserialization of a Lombok @Builder class using a mixin is not working 【发布时间】:2020-11-28 05:30:45 【问题描述】:

这是我的课:

@Builder
@Value
public class A 
    int id;
    String name;
    @NonNull String lastName;

Lombok @Builder 将添加 all args 构造函数。

我需要将一个字符串反序列化为一个 POJO 对象。

我创建了以下包含所有三个属性的 Jackson mixin:

public abstract class AMixin 
    public AMixin(@JsonProperty("name") String name,
                  @JsonProperty("id") int id,
                  @JsonProperty("lastName") String lastName) 
    

    @JsonProperty("name")
    abstract String getName();

    @JsonProperty("id")
    abstract int getId();

    @JsonProperty("lastName")
    abstract String getLastName();


我这样反序列化:

public static void main(String[] args) throws Exception 


        ObjectMapper mapper = new ObjectMapper();
        mapper.addMixIn(A.class, AMixin.class);

        String ss = "\"id\":1,\"name\":\"some name\",\"lastName\":\"some name\"\n";
        A c = mapper.readValue(ss, A.class);
    

但我收到此错误:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.bla.test.A` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)""id":1,"name":"some name","lastName":"some name"
"; line: 1, column: 2]

【问题讨论】:

您是否尝试添加 @NoArgsConstructor ?如果它不起作用,请检查这个***.com/questions/51464720/… @TraychoIvanov 我不想要没有参数的构造函数。我的类是最终的,它的所有字段都是最终的,必须在启动阶段(构造函数)声明 在这种情况下,您需要使用 @JsonDeserialize 的这种方法,这里有一个很好的例子 ***.com/a/48801237/9671280 @TraychoIvanov 混合的整个想法是避免在你的 POJO 中添加 Jackson 注释,所以我想知道为什么我的混合不起作用。 这能回答你的问题吗? Lombok 1.18.0 and Jackson 2.9.6 not working together 【参考方案1】:

我找到了答案。

添加带有内容的 lombok.config 文件:

lombok.anyConstructor.addConstructorProperties=true

【讨论】:

【参考方案2】:

这里的问题是,Jackson 需要一个无参数的构造函数或其他配置的创建对象的方式。

从 Lombok v1.18.14 开始,@Jacksonized 注释可以添加到带有 @Builder 注释的类中,以自动配置生成器以用于 Jackson 反序列化。

@Jacksonized
@Builder
@Value
public class A 
    int id;
    String name;
    @NonNull String lastName;

@Jacksonized 的 Lombok documentation 更详细地描述了这个注解:

@Jacksonized 注释是@Builder@SuperBuilder 的附加注释。它会自动配置生成的构建器类以供Jackson 的反序列化使用。它仅在存在@Builder@SuperBuilder 的上下文中才有效;否则会发出警告。

[...]

具体来说,注解做了以下事情:

将 Jackson 配置为使用构建器进行反序列化,在类上使用 @JsonDeserialize(builder=_Foobar_._Foobar_Builder[Impl].class))(其中 Foobar 是带注释的类的名称,Impl 是为 @SuperBuilder 添加的)。 (如果这样的注释已经存在,则会发出错误。) 将 Jackson 相关的配置注释(如@JsonIgnoreProperties)从类复制到构建器类。这是必要的,以便杰克逊在使用构建器时识别它们。 在生成的构建器类中插入@JsonPOJOBuilder(withPrefix="") 以覆盖Jackson 的默认前缀“with”。如果您在 lombok 中使用 setterPrefix 配置了不同的前缀,则使用此值。如果您使用 buildMethodName 更改了 build() 方法的名称,Jackson 也会知道这一点。 对于@SuperBuilder,将构建器实现类设为包私有。

注意:此问题与 mixin 的使用无关,可以通过将 Jackson 配置从 mixin 移动到类本身并观察问题仍然存在来验证。

【讨论】:

以上是关于Jackson 使用 mixin 对 Lombok @Builder 类进行反序列化不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Lombok、Spring mongodb 和 jackson 构造函数问题

带有 Jackson 的不可变 Lombok 注释类

Lombok v1.6.20 不适用于 Jackson

使用 lombok @Builder 时通过 Jackson 反序列化“2021-09-24 00:00:00”日期格式

IDE 不显示 Lombok 为 Jackson 注释类生成的 getter 和 setter

Lombok + Jackson 不可变