当子类有成员且根类是包装类的成员时,JsonTypeInfo被破坏

当子类有成员且根类是包装类的成员时,JsonTypeInfo被破坏,json,inheritance,polymorphism,jackson,wrapper,Json,Inheritance,Polymorphism,Jackson,Wrapper,TL;DR-一个包装类的成员是用@JsonTypeInfo注释的抽象类的列表,该包装类被破坏 我有一个包装类和一个带有根抽象类、一个子抽象类和一个具体孙子的类层次结构 public static class RootClassWrapper { public static final String JSON_KEY_ROOT_CLASS_LIST = "root_class_list"; @JsonProperty(JSON_KEY_ROOT_CLASS_LI

TL;DR-一个包装类的成员是用
@JsonTypeInfo
注释的抽象类的列表,该包装类被破坏


我有一个包装类和一个带有根抽象类、一个子抽象类和一个具体孙子的类层次结构

public static class RootClassWrapper {
    public static final String JSON_KEY_ROOT_CLASS_LIST =
        "root_class_list";

    @JsonProperty(JSON_KEY_ROOT_CLASS_LIST)
    private final List<RootClass> rootClassList;

    @JsonCreator
    public RootClassWrapper(
        @JsonProperty(JSON_KEY_ROOT_CLASS_LIST)
            final List<RootClass> rootClassList) {

        this.rootClassList = rootClassList;
    }
}

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = RootClass.JSON_KEY_ROOT_CLASS_TYPE)
@JsonSubTypes({
    @JsonSubTypes.Type(
        value = GrandchildClass.class,
        name = GrandchildClass.CHILD_CLASS_TYPE) })
public static abstract class RootClass {
    public static final String JSON_KEY_ROOT_CLASS_TYPE = "root_class_type";
    public static final String JSON_KEY_ID = "id";

    @JsonProperty(JSON_KEY_ID)
    private final String id;

    @JsonCreator
    public RootClass(
        @JsonProperty(JSON_KEY_ID) final String id) {

        this.id = id;
    }
}

public static abstract class ChildClass extends RootClass {
    @JsonCreator
    public ChildClass(
        @JsonProperty(JSON_KEY_ID) final String id) {

        super(id);
    }
}

public static class GrandchildClass extends ChildClass {
    public static final String CHILD_CLASS_TYPE = "grandchild";

    @JsonCreator
    public GrandchildClass(
        @JsonProperty(JSON_KEY_ID) final String id) {

        super(id);
    }
}
但该输出的反序列化会导致以下错误:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Could not find creator property with name 'id' (in class test.Test$RootClass)
    at [Source: java.io.StringReader@13de68e2; line: 1, column: 1]
       at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
       at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:584)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:551)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:267)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:168)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:405)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:354)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:267)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
       at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
       at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:305)
       at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:151)
       at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:23)
       at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:309)
       at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.construct(PropertyBasedCreator.java:96)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:414)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:298)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
       at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
       at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:322)
       at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:2990)
       at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2884)
       at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
       at test.Test.main(Test.java:130)

仍然有一个bug,但这是可行的

RootClass
创建一个私有的默认构造函数,将其标记为
@JsonCreator
,并从现有构造函数中删除注释似乎是可行的。中间抽象类上的
@JsonCreator
注释是不相关的

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = RootClass.JSON_KEY_ROOT_CLASS_TYPE)
@JsonSubTypes({
    @JsonSubTypes.Type(
        value = GrandchildClass.class,
        name = GrandchildClass.CHILD_CLASS_TYPE) })
public static abstract class RootClass {
    public static final String JSON_KEY_ROOT_CLASS_TYPE = "root_class_type";
    public static final String JSON_KEY_ID = "id";

    @JsonProperty(JSON_KEY_ID)
    private final String id;

    @JsonCreator
    private RootClass() {
        id = null;
    }

    public RootClass(final String id) {
        this.id = id;
    }
}

public static abstract class ChildClass extends RootClass {

    /**
     * The annotations here don't matter.
     */
    @JsonCreator
    public ChildClass(@JsonProperty(JSON_KEY_ID) final String id) {
        super(id);
    }
}

public static class GrandchildClass extends ChildClass {
    public static final String CHILD_CLASS_TYPE = "grandchild";

    @JsonCreator
    public GrandchildClass(@JsonProperty(JSON_KEY_ID) final String id) {
        super(id);
    }
}

即使列表为空并且没有要反序列化的
RootClass
对象,这仍然会崩溃。
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Could not find creator property with name 'id' (in class test.Test$RootClass)
    at [Source: java.io.StringReader@13de68e2; line: 1, column: 1]
       at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
       at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:584)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:551)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:267)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:168)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:405)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:354)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:267)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
       at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
       at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:305)
       at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:151)
       at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:23)
       at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:309)
       at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.construct(PropertyBasedCreator.java:96)
       at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:414)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:298)
       at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
       at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
       at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:322)
       at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:2990)
       at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2884)
       at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
       at test.Test.main(Test.java:130)
@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = RootClass.JSON_KEY_ROOT_CLASS_TYPE)
@JsonSubTypes({
    @JsonSubTypes.Type(
        value = GrandchildClass.class,
        name = GrandchildClass.CHILD_CLASS_TYPE) })
public static abstract class RootClass {
    public static final String JSON_KEY_ROOT_CLASS_TYPE = "root_class_type";
    public static final String JSON_KEY_ID = "id";

    @JsonProperty(JSON_KEY_ID)
    private final String id;

    @JsonCreator
    private RootClass() {
        id = null;
    }

    public RootClass(final String id) {
        this.id = id;
    }
}

public static abstract class ChildClass extends RootClass {

    /**
     * The annotations here don't matter.
     */
    @JsonCreator
    public ChildClass(@JsonProperty(JSON_KEY_ID) final String id) {
        super(id);
    }
}

public static class GrandchildClass extends ChildClass {
    public static final String CHILD_CLASS_TYPE = "grandchild";

    @JsonCreator
    public GrandchildClass(@JsonProperty(JSON_KEY_ID) final String id) {
        super(id);
    }
}