几个星期以来,我一直在努力为系统的反序列化配置,该系统的API根据其计数返回不同类型的对象。
我们的系统充当代理-到目前为止,我们将整个响应转发到UI-危险,我们希望在中间有一个对象映射,并使我们的API标准化。因此,该计划是将远程系统模式建模到我们的系统中,并配置Jackson来完成工作。.虽然这是一个不错的计划,但是我正在与之通信的系统具有我曾经使用过的非标准API。.因此,如果您遇到过Tufin -永远不会。
所以让我们举个例子。例如,名为Service
的对象将按照以下方式包装:
0
服务:{services: ""}
或嵌套在其他对象中时完全消失1
服务:{services: {service: {...}}}
或{service: {...}}
>1
服务:{services: {service: [{...},{...},...]}}
或{service: [{...},{...},...]}
当Service
中嵌套了不同的资源时,将应用此逻辑。示例Service
定义了Port
。
1)
{
services: {
service: {
name: "FTP",
ports: {
port: [
{number: 21, protocol: "TCP", desc: "FTP data"},
{number: 20, protocol: "TCP", desc: "FTP control"}
]
}
}
}
}
2)
{
services: {
service: {
name: "WEB",
ports: {
port: {number: 80, protocol: "TCP", desc: "WWW data"}
}
}
}
}
3)
{
services: {
service: {
name: "TEST",
ports: ""
}
}
}
这些都是系统可以返回给我的“有效”响应,我需要配置杰克逊以对其进行反序列化。
我首先解决了问题的第一层-仅根对象。在我们的情况下,Service
。因此,我编写了一个自定义解串器,并基于node
类型设置了variantClass
。
因此,我首先使用多态性为Service
建模(与Port
相同):
ServiceDTO
包含域对象{...}
中的属性ServiceDTOObject
,以防Service
返回包装
对象{service: {...}}
ServiceDTOList
如上,但>1
{service: [{...},{...},...]}
ServiceDTOString
,以防=0
{services: ""}
ServiceDTOWrappedObject
,以防Service
被包装到对象中
然后再次包装到另一个对象{services: {service: {...}}}
ServiceDTOWrappedList
与>1
{services: {service: [{...},{...},...]}}
这有效,但是当我开始考虑嵌套多态类型时,它会失败。.我希望如果为Port
配置相同的反序列化策略,它将由jackson处理。.并非如此。.在{ {1}}不管是nullPointerException
还是Port
或Port
的数组,还是完全缺失。
因此,null
的结尾看起来像这样(与ServiceDTO
相同):
Port
还有反序列化器(与class ServiceDTO {
String name;
PortDTOAbstract port;
//getters+setters//
}
class abstract ServiceDTOAbstract {
} // to represent polymorphism
class ServiceDTOObject extends ServiceDTOAbstract {
@JsonProperty("service")
ServiceDTO service;
//getters+setters//
}
class ServiceDTOList extends ServiceDTOAbstract {
@JsonProperty("service")
List<ServiceDTO> service;
//getters+setters//
}
class ServiceDTOString extends ServiceDTOAbstract {
@JsonProperty("services")
String service;
//getters+setters//
}
class ServiceDTOWrappedObject extends ServiceDTOAbstract {
@JsonProperty("services")
ServiceDTOObject services;
//getters+setters//
}
class ServiceDTOWrappedList extends ServiceDTOAbstract {
@JsonProperty("services")
ServiceDTOList services;
//getters+setters//
}
相同):
Port
与public class ServiceDeserializer extends StdDeserializer<ServiceDTOAbstract> {
public ServiceDeserializer() {
super(ServiceDTOAbstract.class);
}
@Override
public ServiceDTOAbstract deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Class<? extends ServiceDTOAbstract> variantClass = null;
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = mapper.readTree(jp);
JsonNode node;
node = root.get("service");
if (node != null) {
switch (node.getNodeType()) {
case STRING:
variantClass = ServiceDTOString.class;
break;
case OBJECT:
variantClass = ServiceDTOObject.class;
break;
case ARRAY:
variantClass = ServiceDTOList.class;
break;
}
}
node = root.get("services");
if (node != null) {
switch (node.getNodeType()) {
case STRING:
variantClass = ServiceDTOString.class;
break;
case OBJECT:
node = node.get("service");
if (node != null) {
switch (node.getNodeType()) {
case OBJECT:
variantClass = ServiceDTOWrappedObject.class;
break;
case ARRAY:
variantClass = ServiceDTOWrappedList.class;
break;
}
} else {
variantClass = ServiceDTOWrappedObject.class;
}
}
}
if (variantClass == null) {
return null;
}
return mapper.readValue(root.traverse(), variantClass);
}
}
相同的反序列化器,但仅在直接请求Port
时有效。.当Port
嵌套在Port
中时,杰克逊在nullPointerException上失败。看到Service
的节点已填充,但是嵌套的多态性失败,并且根本没有考虑Port
的反序列化器。在这里,我想确认如何做-在这种情况下配置反序列化器链例..
非常感谢,米哈尔