Java Jackson用生成器模式进行继承反序列化

时间:2018-08-24 21:14:22

标签: java json spring-mvc serialization jackson

我有一个基类(Foo),有两个孩子(AB)。他们看起来像这样:

public abstract class Foo {
  private String fooString;
  public Foo(String fooString) {
    this.fooString = fooString;
  }
  //getter
}

@JsonDeserialize(builder = A.ABuilder.class)
public class A extends Foo {
  private int amount;
  public A(String fooString, int amount) {
    super(fooString);
    this.amount = amount;
  }
  //getter

  @JsonPOJOBuilder
  public static class ABuilder {
    private String fooString;
    private int amount;

    public ABuilder withFooString(final String fooString) {
        this.fooString = fooString;
        return this;
    }

    public ABuilder withAmount(final int amount) {
        this.amount = amount;
        return this;
    }

    public A build() {
      return new A(fooString, amount);
    }
  }
}

@JsonDeserialize(builder = B.BBuilder.class)
public class B extends Foo {
  private String type;
  public B(String fooString, String type) {
    super(fooString);
    this.type = type;
  }
  //getter

  @JsonPOJOBuilder
  public static class BBuilder {
    private String fooString;
    private String type;

    public BBuilder withFooString(final String fooString) {
        this.fooString = fooString;
        return this;
    }

    public BBuilder withType(final String type) {
        this.type = type;
        return this;
    }

    public B build() {
      return new B(fooString, type);
    }
  }
}

在我的控制器中,我有以下端点:

@PutMapping
private ResponseEntity<Foo> doSomething(@RequestBody Foo dto) {
    //stuff
}

但是每当我尝试发送json有效负载时

{
   "fooString":"test",
   "amount":1
}

我得到了错误:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.test.Foo` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (String)"{"fooString":"test","amount":1}; line: 1, column: 1]
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
    at AbstractJackson.main(AbstractJackson.java:11)

我如何让杰克逊将json反序列化为正确的子类?我在做什么错了?

1 个答案:

答案 0 :(得分:0)

基类不会获得子类的构造函数,相反,它是相反的,您不能在基类中设置子类的特定属性,而是需要使用特定的子类进行调用或使用自定义反序列化器基本类并正确使用intanceOf 要使其正常工作,最简单的方法是更改​​控制器方法。

@PutMapping
private ResponseEntity<Foo> doSomething(@RequestBody A dto) {
    //stuff
}