json Jackson多态性:如何将多个子类型Map到同一个类

6yoyoihd  于 2023-03-24  发布在  其他
关注(0)|答案(5)|浏览(112)

我使用的是Jackson1.9.x。坚持使用Animals示例,下面是我想做的:
假设我有一个Animal类:

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
}

我希望能够做这样的事情(我将几个子类型Map到一个类,再将几个子类型Map到另一个类):

@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 {

}

我现在看到的是Jackson只会识别Dog-to-Mammal和Dodo-to-BirdMap。这是因为StdSubtypeResolver._collectAndResolve()只允许同一个类注册一次(由于NamedType.equals()的实现)。
对于我看到的问题,是否有解决方法?

2nbm6dog

2nbm6dog1#

我也遇到了同样的问题,发现子类型Map需要唯一的类。
我所做的是创建两个类,它们扩展了同一个基类。扩展类是空的,因为它们与基类具有相同的属性。然后将它们添加到SubtypeMap中。例如,在您的情况下,它将是-

@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{}

我知道这不是最好的方法,但在问题没有解决之前,这可能是解决这个问题的最好方法。
希望对你有帮助!

c86crjj0

c86crjj02#

该错误已在 2.6.0 版本中解决,因此您只需将Jackson更新到 2.6.0 或更高版本。附加信息为herehere

cbjzeqam

cbjzeqam3#

也许不是通过使用注解。问题来自这样一个事实,即这种Map不适用于序列化,现有的Map确实期望一对一(双射)关系。可以添加支撑。

zynd9foi

zynd9foi4#

你可以引入一个中间层的抽象类。
您也可以避免列出整个子类型列表,而使用@JsonTypeName
这个解决方案是IMHO更ellegant,因为

  • 这些定义紧挨着实际的子类型,
  • 子类型的长列表使代码不易维护,
  • 你可以在其他地方“插入”类。

操作指南

默认情况下,Jackson不会遍历类型树来查找嵌套的子类型。它将失败,并显示:
无法将类型ID“Dodo”解析为
ch.zizka.test.Animal:已知类型ids = [com.zizka.test.Bird,... Mammal]...
at [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.(Jackson2.10.5)

v9tzhpje

v9tzhpje5#

从Jackson2.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 {

}

相关问题