在反序列化时使用父对象的属性来确定子类?

时间:2011-01-01 17:37:49

标签: java json polymorphism jackson

children: [
      {
          o kind: "t3"
            data: {                 // ExampleNodeT3 class should be used for kind == t3
                + t3var1: "val1"
                + t3var2: true
            }
      }
      {
          o kind: "t4"                
            data: {                 // ExampleNodeT4 class should be used for kind == t4
                + t4var1: false
                + t4var2: 2346
            }
      }
] ... etc.


@JsonTypeInfo(use=Id.NAME, property="kind")
@JsonSubTypes({
@Type(value=ExampleNodeT3.class, name="t3"),
@Type(value=ExampleNodeT4.class, name="t4")})
public abstract class ExampleNode {
...
public void setData(ExampleNode data) {
    this.data = data;
}

当尝试使用Jackson反序列化时,JsonTypeInfo提示在创建ExampleNode数据时失败,因为“kind”属性与其父级关联且不可见。我尝试了各种工厂方法和Jackson注释,但由于Jackson创建了ExampleNode对象并将其传递给setData()本身,我看不到控制创建对象类的地方。

3 个答案:

答案 0 :(得分:3)

从谷歌到这里,找到了解决方案。实际上这些天可能由于include = JsonTypeInfo.As.EXTERNAL_PROPERTY,例如:

 public class Parent {

    @JsonProperty("type")
    public String type;

    @JsonProperty("data")
    @JsonInclude(Include.NON_NULL)
    public ChildBase ChildBase;

    public Parent() {
        medias = new HashMap<>();
    }

    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="type")
    @JsonTypeIdResolver(ChildBaseByParentTypeResolver.class)
    public void setChildBase(ChildBase ChildBase){
        this.ChildBase = ChildBase;
    }
}


@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ChildBase {
      public String someStr;

}


@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class AggressiveChild extends ChildBase{
     public String someStr1;

}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ChilledChild extends ChildBase{
     public String someStr1;

}


public class ChildBaseByParentTypeResolver extends TypeIdResolverBase {

    private JavaType superType;

    @Override
    public void init(JavaType baseType) {
        superType = baseType;
    }   

    @Override
    public Id getMechanism() {
        return Id.NAME;
    }

    @Override
    public JavaType typeFromId(DatabindContext context, String id) {
        Class<?> subType = ChildBase.class;     
        switch (id) {
        case "agressiveParent":        
            subType = AggressiveChild.class;
            break;
        case "chilledParent":        
            subType = ChilledChild.class;
            break;        
        }
        return context.constructSpecializedType(superType, subType);        
    }

    @Override
    public JavaType typeFromId(String directiveType) {
         throw new NotImplementedException();
    }

}

有趣的文章:

Polymorphism with jackson friend

Related stack overflow question

答案 1 :(得分:1)

答案 2 :(得分:1)

正确 - 使用&#34;外部类型标识符&#34; (尚未包含在反序列化的Object中,但作为兄弟姐妹的那些)尚不支持。

这可以实现(因为没有任何基本的防止支持被添加) - 除了提到的Jira问题可能有帮助之外,可以提交新的功能请求以直接请求使用这种类型标识符的能力。这实际上已被多个用户提及;可能因为有数据格式(geoJSON?)使用这种打字结构。