【问题标题】:Java Jackson deserializing with inheritance with builder patternJava Jackson 使用构建器模式进行继承反序列化
【发布时间】:2019-01-31 08:50:39
【问题描述】:

我有一个基类 (Foo) 和 2 个孩子(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)

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

【问题讨论】:

  • 可以给抽象的Foo类添加空构造函数吗?
  • 另外你把B类粘贴错了,构造函数名应该是B,而不是A。
  • 我在本地测试过,没有出现异常,能分享一下你的控制器实现吗?您尝试发送什么数据?

标签: java json spring-mvc serialization jackson


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2020-09-13
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多