Jackson MixIn用其后面的getValue()</t>替换泛型类JAXBElement <t>

时间:2014-12-18 09:22:20

标签: java xml json jaxb jackson

我尝试使用相同的JAXB注释绑定XML和JSON(使用JaxbAnnotationModule)。

XML <--> JAXB <--> Jackson <--> JSON

我必须使用JAXB注释,不能改变它们。我的问题是某些XML直接转换为泛型类JAXBElement<T>而不是类T。这导致了JSON输出:

{  
   "JAXBElement":{  
      "name":"{http://www.opengis.net/wps/1.0.0}Capabilities",
      "declaredType":"net.opengis.wps.v_1_0_0.WPSCapabilitiesType",
      "scope":"javax.xml.bind.JAXBElement$GlobalScope",
      "value":{  
         "ProcessOfferings":{  },
         "Languages":{  },
         "ServiceIdentification":{  },
         "ServiceProvider":{  },
         "OperationsMetadata":{  },
         "version":"1.0.0",
         "updateSequence":"1",
         "service":"WPS",
         "lang":"en-US"
      },
      "nil":false,
      "globalScope":true,
      "typeSubstituted":false
   }
}

虽然我想要:

{  
   "Capabilities":{  
     "ProcessOfferings":{  },
     "Languages":{  },
     "ServiceIdentification":{  },
     "ServiceProvider":{  },
     "OperationsMetadata":{  },
     "version":"1.0.0",
     "updateSequence":"1",
     "service":"WPS",
     "lang":"en-US"
   }
}

类型T的真实对象由JAXBElement包装。对于某些根元素可能会发生这种情况,并且嵌套在对象树中的任何位置。如果我打电话给getValue(),我就会得到真实的对象。但是当JAXBElement<T>不是根元素时,我无法做到这一点,因为Jackson是JAXB和JSON之间唯一的解释器,我既不能改变JAXB-Binding也不能改变创建的对象(其他的一些部分)代码也使用它们。)

所以我发现可以解决问题的是MixIns

// a mixin annotation that overrides the handling for the JAXBElement
public static interface JAXBElementMixin<T> {
    @JsonValue
    Object getValue();
}

ObjectMapper mapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
mapper.registerModule(module);
mapper.addMixInAnnotations(JAXBElement.class, JAXBElementMixin.class);

这解决了其他元素的问题,但导致对象的名称为JAXBElement而不是T(在我的情况下为Capabilities):

{  
  "JAXBElement":{  // <------ Should be 'Capabilities' because of type JAXBElement<Capabilities>
    "ProcessOfferings":{  },
    "Languages":{  },
    "ServiceIdentification":{  },
    "ServiceProvider":{  },
    "OperationsMetadata":{  },
    "version":"1.0.0",
    "updateSequence":"1",
    "service":"WPS",
    "lang":"en-US"
  }
}

问题:

任何想法我可以做什么(可能注释JAXBElementMixin<T>)以获得正确的类型Capabilities作为对象名称(还有其他类而不是Capabilities可以放置为{{ 1}},也是)?

还有其他想法如何跳过对象树中任何位置的任何T的序列化,并继续对其JAXBElement<T>方法后面的对象进行序列化?

2 个答案:

答案 0 :(得分:0)

这不是您问题的直接答案,但可能是实现目标的方法。

如果您只想摆脱最顶层的JAXBElement,为什么不定制XJC为Capabilities元素生成额外的课程?

类似的东西:

<jaxb:bindings node="xs:element[@name='Capabilities']">
   <jaxb:class name="Capabilities"/>
</jaxb:bindings>

这应该生成一个用&#39; @ XmlRootElement&#39;注释的类Capabilities。因此,您将摆脱JAXBElement

答案 1 :(得分:0)

杰克逊不支持JAXBElement,因为它非常特定于XML并且难以与其他格式一起使用:杰克逊JAXB支持专注于使用注释中的信息来使事情有效,但目标不是成为一个完整的JAXB实现。

因此,最好的办法是做@lexicore建议并尝试避免使用JAXBElement