代码之家  ›  专栏  ›  技术社区  ›  Richard

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

  •  0
  • Richard  · 技术社区  · 6 年前

    我有一个基础班( Foo )有两个孩子( A B ).它们看起来像这样:

    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反序列化到适当的子类中?我做错了什么?

    1 回复  |  直到 6 年前
        1
  •  -1
  •   Vaibhav Gupta    6 年前

    基类不会得到子类的构造函数,相反,您不能在基类中设置子类特定的属性,而是需要使用特定的子类进行调用或使用 基类的自定义反序列化程序 正确使用 intanceOf

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