杰克逊反序列化多种类型
Jackson deserialization on multiple types
我有一个名为 Instance
的抽象 class,然后是它的两个实现,UserInstance
和 HardwareInstance
。我遇到的问题是,当我将 @POST
的其余端点调用到数据库中时,理想情况下我希望它像 .../rest/soexample/instance/create
那样将实例传递到 REST 端点。如果 Instance
不是具有多个实现的抽象,那会很好,但是因为我有 2 个,所以我得到一个 Jackson.databind
错误。
”问题:抽象类型要么需要映射到具体类型,要么需要自定义反序列化器,要么使用额外的类型信息进行实例化”
在查找解决方案后,我找到了一个 SO 答案,说我可以使用类似的东西:
@JsonDeserialize(as=UserInstance.class)
但似乎只有在抽象有一个实现时才有用 class。假设我不能调用它两次,因为它无法决定它是哪种类型的实例。
所以我想知道处理这种情况的最佳方法是什么?我应该创建不同的端点吗?喜欢:
.../rest/soexample/userinstance/create
& .../rest/soexample/hardwareinstance/create
我不太确定,因为我是一个菜鸟 @REST 相关的东西,虽然积极尝试学习。谢谢!
以下是我在相同情况下所做的:
@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 );
}
}
您使用 @JsonDeserialize(using = InstanceDeserializer.class)
注释 Instance
以指示 class 用于反序列化摘要 class。然后你需要指出每个子 class 将自己反序列化 as
,否则他们将使用父 class 反序列化器,你将得到一个 WhosebugError
.
最后,在 InstanceDeserializer
中将反序列化逻辑放入一个或另一个子 class(例如 checkConditionsForUserInstance()
)。
我有一个名为 Instance
的抽象 class,然后是它的两个实现,UserInstance
和 HardwareInstance
。我遇到的问题是,当我将 @POST
的其余端点调用到数据库中时,理想情况下我希望它像 .../rest/soexample/instance/create
那样将实例传递到 REST 端点。如果 Instance
不是具有多个实现的抽象,那会很好,但是因为我有 2 个,所以我得到一个 Jackson.databind
错误。
”问题:抽象类型要么需要映射到具体类型,要么需要自定义反序列化器,要么使用额外的类型信息进行实例化”
在查找解决方案后,我找到了一个 SO 答案,说我可以使用类似的东西:
@JsonDeserialize(as=UserInstance.class)
但似乎只有在抽象有一个实现时才有用 class。假设我不能调用它两次,因为它无法决定它是哪种类型的实例。
所以我想知道处理这种情况的最佳方法是什么?我应该创建不同的端点吗?喜欢:
.../rest/soexample/userinstance/create
& .../rest/soexample/hardwareinstance/create
我不太确定,因为我是一个菜鸟 @REST 相关的东西,虽然积极尝试学习。谢谢!
以下是我在相同情况下所做的:
@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 );
}
}
您使用 @JsonDeserialize(using = InstanceDeserializer.class)
注释 Instance
以指示 class 用于反序列化摘要 class。然后你需要指出每个子 class 将自己反序列化 as
,否则他们将使用父 class 反序列化器,你将得到一个 WhosebugError
.
最后,在 InstanceDeserializer
中将反序列化逻辑放入一个或另一个子 class(例如 checkConditionsForUserInstance()
)。