我有一个表示有限域值的类(类似于枚举):
public abstract class AbstractEnum {
private String id;
// ...
}
和具体的类EnumA, EnumB
扩展AbstractEnum
. 业务对象可能如下所示
public class Obj {
private EnumA a;
private EnumB b;
// ...
}
EnumA, EnumB
的实例由工厂管理。当反序列化一个Obj
时,我想调用工厂而不是构造函数。具体类型(EnumA
或EnumB
)不能从枚举值的JSON表示中推断出来,因为它们只包含它们的ID,而是从Obj
中相应的属性类型推断出来的。
我尝试在AbstractEnum
上使用@JsonCreator
或@JsonDeserialize
(带转换器),但创建者/转换器似乎无法使用属性类型。似乎我必须使用@JsonTypeInfo
来序列化额外的类型信息(这似乎是多余的),或者为每个具体的AbstractEnum
子类定义一个创建者/转换器,其中不止两个。 还有别的办法吗?
编辑:EnumA
的实例可以与EnumB
的实例具有相同的ID,因此ID不能用于推断类型。
可能是您可以使用字段名称来区分类型,而不必依赖工厂或其他任何内容。 我在这里假设名为a
的字段将始终引用类型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": nulln"
+ "}";
ObjectMapper om = new ObjectMapper();
Obj obj = om.readValue(json, Obj.class);
System.out.println("obj = " + obj);
}
}
此代码的输出为
obj = Obj{a=AbstractEnum{id=enuma}, b=null, c=null}
这表明 JSON 已正确反序列化。
我按照此处的建议使用ContextualDeserializer
解决了它:createContextual()
中,我获取具体类,deserialize()
中,我调用我的工厂以获取基于targetClass
和ID的实例。