如何在Jackson中对具有抽象类型的引用进行反序列化JSON

Koppor

我对抽象类的对象引用以及JSON序列化和反序列化有问题。抽象的问题看起来像这样:

我有一个由节点和边组成的图。每个边缘连接两个节点。节点可以是红色和绿色。因此,存在一个抽象类Node和两个派生类RedNodeGreenNodeANode取一个id@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")):

@JsonSubTypes({
    @JsonSubTypes.Type(value = GreenNode.class, name = "GreenNode"),
    @JsonSubTypes.Type(value = RedNode.class, name = "RedNode")
})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public abstract class Node {
    public String id;
}

public class RedNode extends Node {
    // ...
}

public class GreenNode extends Node {
    // ...
}

Edge来源和目标类型为Node,被序列化为引用(@JsonIdentityReference(alwaysAsId = true)):

public class Edge {
    @JsonIdentityReference(alwaysAsId = true)
    public Node source;
    @JsonIdentityReference(alwaysAsId = true)
    public Node target;
}

该图定义如下:

public class Graph {
    public List<GreenNode> greenNodes = new ArrayList();
    public List<RedNode> redNodes = new ArrayList();
    public List<Edge> edges = new ArrayList();
}

JSON示例如下所示:

{
  "greenNodes" : [ {
    "id" : "g",
    "content" : "green g",
    "greenProperty" : "green"
  } ],
  "redNodes" : [ {
    "id" : "r",
    "content" : "red r",
    "redProperty" : "red"    
  } ],
  "edges" : [ {
    "source" : "g",
    "target" : "r"
  } ]
}

使用ObjectMapper无法读取以下内容:

无法构造com.github.koppor.jsonidentityissue.model.Node的实例:抽象类型要么需要映射到具体类型,要么具有自定义反序列化器,或者包含其他类型信息

错误位置为“第13行,第16列”。因此,它被击中边缘的id。节点本身已正确序列化。

一种解决方法是在json中添加类型信息:

@JsonTypeInfo(
      use = JsonTypeInfo.Id.NAME,
      include = JsonTypeInfo.As.PROPERTY,
      property = "type")
public abstract class Node {

然后,一切正常:

{
  "greenNodes" : [ {
    "id" : "g",
    "type" : "GreenNode",
    "content" : "green g",
    "greenProperty" : "green"
  } ],
  "redNodes" : [ {
    "id" : "r",
    "type" : "RedNode",
    "content" : "red r",
    "redProperty" : "red"    
  } ],
  "edges" : [ {
    "source" : "g",
    "target" : "r"
  } ]
}

然后,一切正常。

真的有必要在引用的对象中包含类型信息以使引用起作用吗?如果没有类型信息,则可以加载具有红色和绿色节点(无边)的图形。进入边缘后,就不能。但是,边缘的JSON仅包含一个ID。引用的对象已被解析。

我真的很想摆脱@JsonTypeInfo注释。有没有一种方法可以得到一个干净的JSON?

完整示例可在https://github.com/koppor/jackson-jsonidentityreference-issue/tree/issue中获得

Koppor

当前的解决方案是包括伪造的类型信息。完整代码位于https://github.com/koppor/jackson-jsonidentityreference-issue

Node得到现有的属性type,这是不写的:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.EXISTING_PROPERTY,
    property = "type")
public abstract class Node {
    @JsonIgnore
    public abstract String getType();
}

每个子类将自己指定为,defaultImpl并提供的实现getType

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.EXISTING_PROPERTY,
    property = "type",
    defaultImpl=GreenNode.class)
public class GreenNode extends Node {
    @Override
    public String getType() {
        return "GreeNode";
    }
}

这样,JSON保持干净,但是Jackson可以解析id引用而没有任何问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Jackson JSON(反序列化)中自定义序列化或转换具有自定义键类型的Map属性?

Dart中抽象类型的反序列化

反序列化具有抽象类型属性的对象

如何在杰克逊中反序列化抽象类

如何使用 Jackson 反序列化匿名抽象类?

C#JSON反序列化:类型是接口或抽象类,无法实例化

如何在父类中指定类型时使Jackson类中没有类型属性的子类反序列化

具有不同类型的字段的 JSON 反序列化(使用 Jackson 和 Scala)

如何在angular2 +中序列化/反序列化.NET类型的JSON

Jackson从JSON中的变量类型反序列化

Delphi使用抽象类反序列化JSON

在Jackson中反序列化具有相同名称但不同类型的属性?

具有嵌入类型的反序列化JSON

通过JSON.NET对具有类型的锯齿状数组进行反序列化

无法反序列化扩展使用Java中的杰克逊抽象类JSON

如何在Flutter中使用json_serializable对具有其ID的ID的Firestore文档进行反序列化?

如何反序列化对某些容器类型具有只读反向引用的类型的实例,并且这些实例也会反序列化?

如何在具有相同类型子节点的 c# 中反序列化 XML

如何在Rust中反序列化引用树?

具有包含混合子类对象类型的列表的抽象类的序列化

如何基于公共字段用Jackson抽象地反序列化不同的枚举类型?

如何在 JSON.NET 中反序列化具有嵌套对象列表的对象列表?

Java Jackson反序列化实现接口的抽象类子级

通用抽象类的自定义Jackson反序列化

Jackson抽象类基于参数值反序列化

对具有两种类型的字段的Json进行反序列化,而一种类型是递归的

如何在 C# 中反序列化具有属性的 XML

如何在Rails中反序列化json

如何在MVC中反序列化JSON数据