【问题标题】:Deserializing abstract property from JSON request body, based on another property from that body基于来自 JSON 请求主体的另一个属性,反序列化来自 JSON 请求主体的抽象属性
【发布时间】:2019-11-07 15:20:20
【问题描述】:

当一个对象具有一个抽象属性时,如何从 JSON 中正确反序列化(使用 Jackson)?

这可能最好用一个例子来描述。

我的 REST 端点的请求正文包含一个属性,该属性是具有多个具体实现的抽象类型,应基于 discriminator 属性进行反序列化:

@Getter
@Builder
@AllArgsConstructor
public class SomeRequestBody {

    @NotNull
    @NotBlank
    @NumberFormat
    private final String discriminator;

    @NotNull
    private final SomeAbstractClass someAbstractClass;

}

有问题的抽象类

@Getter
@AllArgsConstructor
public abstract class SomeAbstractClass{

    @NotNull
    @NotBlank
    protected final String commonProperty;

}

抽象类的示例实现

@Getter
public class ConcreteImplementationA extends SomeAbstractClass {

    @Builder
    @JsonCreator
    public ConcreteImplementationA(
        @NotNull @NotBlank @JsonProperty("commonProperty") String commonProperty,
        @NotNull @NotBlank @JsonProperty("specificProperty") Date specificProperty) {
            super(commonProperty);
            this.specificProperty = specificProperty;
    }

    @NotNull
    @NotBlank
    private final String specificProperty;

}

我尝试了什么...

@Getter
@Builder
@AllArgsConstructor
public class SomeRequestBody {

    @NotNull
    @NotBlank
    @NumberFormat
    private final String discriminator;

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "discriminator")
    @JsonSubTypes({
        @JsonSubTypes.Type(value = ConcreteImplementationA.class, name = "1"),
        Other implementations...)
    })
    @NotNull
    private final SomeAbstractClass someAbstractClass;

}

但是,我遇到了以下异常:

"Type definition error: [simple type, class abc.SomeRequestBody]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `abc.SomeRequestBody`, problem: Internal error: no creator index for property 'someAbstractClass' (of type com.fasterxml.jackson.databind.deser.impl.FieldProperty)\n at [Source: (PushbackInputStream); line: 8, column: 1]"

实现我需要的正确方法是什么?

【问题讨论】:

    标签: java rest spring-boot jackson json-deserialization


    【解决方案1】:

    事实证明,该抽象属性的反序列化不是问题,但不可变属性和 Lombok 的 @AllArgsConstructor 与 Jackson 不兼容。我创建了一个 @JsonCreator 带注释的构造函数,而不是使用注释,现在它可以正常工作了。

    【讨论】:

    • 不是构建自己的构造函数,添加它也应该有效@AllArgsConstructor(onConstructor = @__({@JsonCreator})),至少对我来说它有效。
    • 如果您的大多数对象都是这样不可变的,并且您不想为每个类添加配置详细信息...您可以创建一个 lombik.config 属性为 lombok.anyConstructor.addConstructorProperties=true 的文件它。这将导致 lombok 将 Java 注释添加到构造函数参数,并命名它们,Jackson 可以使用。
    猜你喜欢
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    相关资源
    最近更新 更多