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

发布于 2024-10-09 22:40:27 字数 921 浏览 6 评论 0原文

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() 本身,所以我看不到有地方可以控制创建什么类的对象。

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;
}

When attempting to deserialize this with Jackson, the JsonTypeInfo hints fail when ExampleNode data is created because the "kind" property is associated with its parent and not visible. I have tried various variations of factory methods, and Jackson annotations, but because Jackson creates the ExampleNode object and passes it to setData() itself, I see no place to control what class of object is created.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

抚笙 2024-10-16 22:40:27

从谷歌到这里,找到了解决方案。实际上,现在由于 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();
    }

}

有趣的文章:

杰克逊朋友的多态性

相关堆栈溢出问题

Got to here from google , and found the solution. actually these days its possible due to the include=JsonTypeInfo.As.EXTERNAL_PROPERTY , example:

 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();
    }

}

Interesting articles:

Polymorphism with jackson friend

Related stack overflow question

相思碎 2024-10-16 22:40:27

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

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

Correct -- use of "external type identifiers" (ones that are not contained within Object to deserialize, but as siblings) is not yet supported.

This could be implemented (as in, there is nothing fundamental preventing support from being added) -- beyond Jira issue mentioned that could help, a new feature request could be filed for directly requesting ability to use such type identifiers. This has actually been mentioned by multiple users; possibly since there are data formats (geoJSON?) that use such typing structure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文