Jackson反序列化Lombok @Builder类时使用mixin不起作用。

huangapple go评论73阅读模式
英文:

Jackson deserialization of a Lombok @Builder class using a mixin is not working

问题

这是我的类:

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

Lombok的 @Builder 会添加所有参数的构造函数。

我需要将一个字符串反序列化为一个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]
英文:

This is my class:

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

The Lombok @Builder will add the all args constructor.

I need to deserialise a string into a POJO object.

I created the following Jackson mixin containing all three properties:

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();

}

I deserialise like this:

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

but I get this error:

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]

答案1

得分: 2

我找到了答案。

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

lombok.anyConstructor.addConstructorProperties=true
英文:

I found the answer.

Add lombok.config file with content:

lombok.anyConstructor.addConstructorProperties=true

答案2

得分: 2

问题在于Jackson期望一个无参数构造函数或其他已配置的方式来创建对象。然而,由于A上的@Builder注解,没有无参数构造函数,只有由Lombok生成的全参数构造函数A(int id, String name, String lastName)

从Lombok v1.18.14开始,可以在带有@Builder注解的类上添加@Jacksonized注解,这将自动配置用于Jackson反序列化的生成构建器。

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

Lombok的文档@Jacksonized注解进行了更详细的描述:

> @Jacksonized注解是@Builder@SuperBuilder的附加注解。它会自动配置生成的构建器类,以供Jackson的反序列化使用。只有在存在@Builder@SuperBuilder的上下文中才会产生影响;否则会发出警告。
>
> [...]
>
> 具体而言,该注解执行以下操作:
>
> * 使用@JsonDeserialize(builder=_Foobar_._Foobar_Builder[Impl].class))在类上配置Jackson以使用构建器进行反序列化(其中_Foobar_是带注解的类的名称,Impl是为了@SuperBuilder而添加的)。如果已存在这样的注解,将会发出错误。
> * 从类中复制Jackson相关的配置注解(如@JsonIgnoreProperties)到构建器类。这是必要的,以便Jackson在使用构建器时识别它们。
> * 在生成的构建器类上插入@JsonPOJOBuilder(withPrefix=""),以覆盖Jackson的默认前缀“with”。如果您在lombok中使用了setterPrefix配置了不同的前缀,则将使用该值。如果使用buildMethodName更改了build()方法的名称,Jackson也会知道。
> * 对于@SuperBuilder,使构建器实现类包私有。


注意:这个问题与使用mixin没有关系,可以通过将Jackson配置从mixin移到类本身并观察到问题仍然存在来进行验证。

英文:

The issue here is that Jackson expects a no-argument constructor or some other configured way of creating the object. However, because of the @Builder annotation on A, the no-argument constructor is not present, only the Lombok-generated all-argument constructor A(int id, String name, String lastName).

As of Lombok v1.18.14, the @Jacksonized annotation can be added to the class with the @Builder annotation, which automatically configures the builder to be used for Jackson deserialization.

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

The Lombok documentation for @Jacksonized describes this annotation in more detail:

> The @Jacksonized annotation is an add-on annotation for @Builder and @SuperBuilder. It automatically configures the generated builder class to be used by Jackson's deserialization. It only has an effect if present at a context where there is also a @Builder or a @SuperBuilder; a warning is emitted otherwise.
>
> [...]
>
> In particular, the annotation does the following:
>
> * Configure Jackson to use the builder for deserialization using @JsonDeserialize(builder=_Foobar_._Foobar_Builder[Impl].class)) on the class (where Foobar is the name of the annotated class, and Impl is added for @SuperBuilder). (An error is emitted if such an annotation already exists.)
> * Copy Jackson-related configuration annotations (like @JsonIgnoreProperties) from the class to the builder class. This is necessary so that Jackson recognizes them when using the builder.
> * Insert @JsonPOJOBuilder(withPrefix="") on the generated builder class to override Jackson's default prefix "with". If you configured a different prefix in lombok using setterPrefix, this value is used. If you changed the name of the build() method using using buildMethodName, this is also made known to Jackson.
> * For @SuperBuilder, make the builder implementation class package-private.


Note: This issue has nothing to do with the usage of a mixin, which can be verified by moving Jackson configuration from the mixin to the class itself and observing that the issue is still present.

huangapple
  • 本文由 发表于 2020年8月8日 05:14:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63309223.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定