多态性的杰克逊反序列化嵌套为多态性又称多个解串器

时间:2018-07-12 15:22:37

标签: jackson polymorphism deserialization abstract

几个星期以来,我一直在努力为系统的反序列化配置,该系统的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相同):

  1. ServiceDTO包含域对象{...}中的属性
  2. ServiceDTOObject,以防Service返回包装 对象{service: {...}}
  3. ServiceDTOList如上,但>1 {service: [{...},{...},...]}
  4. ServiceDTOString,以防=0 {services: ""}
  5. ServiceDTOWrappedObject,以防Service被包装到对象中 然后再次包装到另一个对象{services: {service: {...}}}
  6. ServiceDTOWrappedList>1 {services: {service: [{...},{...},...]}}
  7. 差不多

这有效,但是当我开始考虑嵌套多态类型时,它会失败。.我希望如果为Port配置相同的反序列化策略,它将由jackson处理。.并非如此。.在{ {1}}不管是nullPointerException还是PortPort的数组,还是完全缺失。

因此,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的反序列化器。在这里,我想确认如何做-在这种情况下配置反序列化器链例..

非常感谢,米哈尔

0 个答案:

没有答案