Jackson多态性:如何将多个亚型映射到同一类



我使用的是Jackson 1.9.x。坚持动物的例子,以下是我想做的:

假设我有一个动物类:

public class Animal {
    private String type;
    // accessors
}
public class Mammal extends Animal {
    private String diet;
    // accessors
}
public class Bird extends Animal {
    private boolean tropical;
    // accessors
}

我希望能够做这样的事情(我将几个子类型映射到一个类,并将更多的子类型映射成不同的类):

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = Mammal.class, name = "Dog"),
                @JsonSubTypes.Type(value = Mammal.class, name = "Cat"),
                @JsonSubTypes.Type(value = Bird.class, name = "Dodo"},
                @JsonSubTypes.Type(value = Bird.class, name = "Cockatoo"})
public class Animal {
}

我现在看到的是,杰克逊只会认出狗对哺乳动物和渡渡鸟对鸟的映射。这是因为StdSubtypeResolver_collectAndResolve()只允许同一个类注册一次(由于NamedType.equals()的实现)。

我看到的问题有解决办法吗?

我也遇到了同样的问题,发现子类型映射需要唯一的类。

我所做的是创建两个扩展同一基类的类。扩展类是空的,因为它们与基类具有相同的属性。然后将它们添加到"子类型"映射中。例如,在您的情况下,它将是-

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = Mammal.class, name = "Dog"),
            @JsonSubTypes.Type(value = Mammal.class, name = "Cat"),
            @JsonSubTypes.Type(value = BirdDodo.class, name = "Dodo"},
            @JsonSubTypes.Type(value = BirdCockatoo.class, name = "Cockatoo"})
public class Animal {
}
public class BirdCockatoo extends Cockatoo{}
public class BirdDodo extends Dodo{}

我知道这不是最好的方法,但在问题没有解决之前,这可能是解决这个问题的最佳方法。我现在采用了这种方法。

希望它能帮助你!

该错误已在2.6.0版本中得到解决,因此您只需将Jackson更新到22.6.0

也许不是通过使用注释。问题来自这样一个事实,即这种映射不适用于序列化,并且现有的映射确实期望一对一(双射)关系。但您可能想要在jackson数据绑定问题跟踪器中提交RFE;增加支撑是可能的。

您可以引入一个中级抽象类。

您也可以避免列出整个子类型列表,而使用@JsonTypeName
这个解决方案是IMHO更ellegant,因为

  • 定义紧挨着实际的子类型
  • 子类型的长列表使代码的可维护性降低
  • 你可以";插件";在其他地方上课

Howto

默认情况下,Jackson不会遍历类型树来查找嵌套的子类型。它将失败:

无法将类型id"Dodo"解析为
的子类型ch.zizka.test.Animal:已知类型ids=〔com.zizka.test.Bird,…Mammal〕
在[Source:(byte[])"处;{

您需要将@JsonSubTypes添加到中级类(BirdMammal)中。

结果

  • Animal@JsonTypeInfo(use=NAME)
    • Mammal@JsonSubTypes(@Type(Dog.class, Cat.class))
      • Dog@JsonTypeName("Dog")
      • Cat@JsonTypeName("Cat")
    • Bird@JsonSubTypes(@Type(Dodo.class, Cockatoo.class))
      • Dodo@JsonTypeName("Dodo")
      • Cockatoo@JsonTypeName("Cockatoo")

刚刚测试-#WORKSFORME。(Jackson 2.10.5)

从Jackson 2.12开始,@JsonSubTypes.Type注释中有一个单独的字段。

/**
 * (optional) Logical type names used as the type identifier for the class: used if
 * more than one type name should be associated with the same type.
 *
 * @since 2.12
 */
public String[] names() default {};

检查下面的示例代码。

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = Mammal.class, names = {"Dog", "Cat"}),
                @JsonSubTypes.Type(value = Bird.class, names = {"Dodo", "Cockatoo"}},
                
public class Animal {
}

最新更新