我有一个名为Instance
的抽象类,然后有两个实现,UserInstance
和HardwareInstance
。我遇到的问题是,当我将@POST
的其余端点调用到数据库中时,我理想地希望它像.../rest/soexample/instance/create
那样将实例传递给REST端点。如果Instance
不具有多个实现的抽象,那就没关系,但是因为我有2个,所以我收到Jackson.databind
错误。
“问题:抽象类型需要映射到具体类型,具有自定义反序列化器,或者使用其他类型信息进行实例化”
在查找解决方案之后,我找到了一个SO答案,说我可以使用类似的东西:
@JsonDeserialize(as=UserInstance.class)
但是,如果有一个抽象类的实现,它似乎非常有用。假设我不能两次调用它,因为它无法确定它将是哪种类型的实例。
所以我想知道处理这种情况的最佳方法是什么?我应该创建不同的端点吗?像:
.../rest/soexample/userinstance/create
& .../rest/soexample/hardwareinstance/create
我不太确定,因为我是一个noobie @ REST相关的东西,虽然积极尝试学习。谢谢!
答案 0 :(得分:22)
以下是我在同一案件中所做的事情:
@JsonDeserialize(using = InstanceDeserializer.class)
public abstract class Instance {
//.. methods
}
@JsonDeserialize(as = UserInstance.class)
public class UserInstance extends Instance {
//.. methods
}
@JsonDeserialize(as = HardwareInstance.class)
public class HardwareInstance extends Instance {
//.. methods
}
public class InstanceDeserializer extends JsonDeserializer<Instance> {
@Override
public Instance deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
Class<? extends Instance> instanceClass = null;
if(checkConditionsForUserInstance()) {
instanceClass = UserInstance.class;
} else {
instanceClass = HardwareInstance.class;
}
if (instanceClass == null){
return null;
}
return mapper.readValue(root, instanceClass );
}
}
使用Instance
注释@JsonDeserialize(using = InstanceDeserializer.class)
以指示用于反序列化抽象类的类。然后,您需要指示每个子类将自行反序列化as
,否则它们将使用父类反序列化器,您将获得StackOverflowError
。
最后,在InstanceDeserializer
内部,您将逻辑反序列化为一个或另一个子类(例如checkConditionsForUserInstance()
)。