我有一个表示各种有限域值的类(类似于枚举):
public abstract class AbstractEnum {
private String id;
// ...
}
和扩展EnumA, EnumB
的具体课程AbstractEnum
。
业务对象可能看起来像
public class Obj {
private EnumA a;
private EnumB b;
// ...
}
EnumA, EnumB
的实例由工厂管理。反序列化Obj
时,我想调用工厂而不是构造函数。无法从枚举值的JSON表示推断具体类型(EnumA
或EnumB
),因为它们仅包含其ID,但是从Obj
中的相应属性类型推断出来。 / p>
我尝试在@JsonCreator
上使用@JsonDeserialize
或AbstractEnum
(带转换器),但属性类型似乎不可用于创建者/转换器。似乎我必须使用@JsonTypeInfo
来序列化额外的类型信息(这似乎是多余的),或者为每个具体的AbstractEnum
子类定义一个创建者/转换器,其中不仅仅有两个。
还有另一种方式吗?
修改:EnumA
的实例可以与EnumB
的实例具有相同的ID,因此ID不能用于推断类型。
答案 0 :(得分:0)
可能是您可以使用字段名来区分类型,而不必依赖工厂或其他任何东西。我在这里假设名为EnumA
的字段将始终引用类型public class SpikeJson {
public static abstract class AbstractEnum {
private final String id;
protected AbstractEnum(String id) {
this.id = id;
}
@Override
public String toString() {
return "AbstractEnum{" + "id=" + id + '}';
}
}
public static class EnumA extends AbstractEnum {
public EnumA() {
super("enuma");
}
}
public static class EnumB extends AbstractEnum {
public EnumB() {
super("enumb");
}
}
public static class EnumC extends AbstractEnum {
public EnumC() {
super("enumc");
}
}
public static class Obj {
@JsonProperty
private EnumA a;
@JsonProperty
private EnumB b;
@JsonProperty
private EnumC c;
@Override
public String toString() {
return "Obj{" + "a=" + a + ", b=" + b + ", c=" + c + '}';
}
}
public static void main(String[] args) throws IOException {
//{
// "a": {},
// "b": null
//}
String json = "{\n"
+ " \"a\": {},\n"
+ " \"b\": null\n"
+ "}";
ObjectMapper om = new ObjectMapper();
Obj obj = om.readValue(json, Obj.class);
System.out.println("obj = " + obj);
}
}
,依此类推。下面是一些测试代码,它使用您的代码并尝试单独显示字段名称可能会起作用。
{{1}}
此代码的输出是
obj = Obj {a = AbstractEnum {id = enuma},b = null,c = null}
表明JSON已正确反序列化。
答案 1 :(得分:0)
我按照建议here使用ContextualDeserializer
解决了问题:在createContextual()
中我抓住了具体的类,在deserialize()
中我调用我的工厂来获取基于{的实例{1}}和ID。