【问题标题】:Use property of parent object to determine subclass when deserializing?反序列化时使用父对象的属性来确定子类?
【发布时间】:2011-01-01 17:37:48
【问题描述】:
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 反序列化此内容时,创建 ExampleNode 数据时 JsonTypeInfo 提示失败,因为“kind”属性与其父级相关联且不可见。我已经尝试过各种工厂方法和 Jackson 注释,但由于 Jackson 创建了 ExampleNode 对象并将其传递给 setData() 本身,我看不到任何地方可以控制创建的对象类。

【问题讨论】:

标签: java json polymorphism jackson


【解决方案1】:

从 google 到这里,找到了解决方案。实际上这些天它可能由于 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

【讨论】:

  • 如果属性是列表怎么办?和public List&lt;ChildBase&gt; childBases;一样,在我的测试中,它不起作用。
  • 在我的情况下,当您找到答案时,我没有使用 List 但是,如果您可以在这里发表评论,那就太好了。
【解决方案2】:
【解决方案3】:

正确 - 尚不支持使用“外部类型标识符”(不包含在要反序列化的 Object 中,但作为同级的标识符)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多