【问题标题】:Jackson MixIn to replace the generic class JAXBElement<T> with its T behind getValue()Jackson MixIn 将通用类 JAXBElement<T> 替换为 getValue() 后面的 T
【发布时间】:2015-02-17 00:47:55
【问题描述】:

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

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

我必须使用 JAXB 注释并且不能更改它们。我的问题是一些 XML 直接转换为通用类 JAXBElement&lt;T&gt; 而不是类 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&lt;T&gt; 不是根元素时我不能这样做,因为杰克逊是 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&lt;T&gt;)来获得正确的类型Capabilities作为对象名称(还有其他类而不是Capabilities,也可以放置为T)?

任何其他想法如何跳过对象树中任何JAXBElement&lt;T&gt; 的序列化并继续其getValue() 方法后面的对象的序列化?

【问题讨论】:

  • 当您使用 WPS 时,您可能会对 ogc-schemas 项目感兴趣。
  • 您能找到解决方案吗?

标签: java xml json jaxb jackson


【解决方案1】:

这不是您问题的直接答案,而是可能实现您的目标的秘诀。

如果你只是想摆脱最顶层的JAXBElement,为什么不直接自定义XJC 为你的Capabilities 元素生成一个额外的类?

类似:

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

这应该生成一个带有“@XmlRootElement”注释的类Capabilities。这样你就可以摆脱JAXBElement

【讨论】:

    【解决方案2】:

    Jackson 不支持 JAXBElement,因为它非常特定于 XML,并且很难与其他格式一起使用:Jackson JAXB 支持专注于使用来自注释的信息来使事情正常工作,但目标不是完整的 JAXB 实现。

    因此,最好的办法是按照@lexicore 的建议去做,并尽量避免使用JAXBElement

    【讨论】:

      猜你喜欢
      • 2018-10-27
      • 2012-07-18
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多