如何从使用 JAXB 的服务返回的“anyType”创建 java 对象?

Posted

技术标签:

【中文标题】如何从使用 JAXB 的服务返回的“anyType”创建 java 对象?【英文标题】:How to create java object from 'anyType' returned from service using JAXB? 【发布时间】:2012-02-23 05:08:49 【问题描述】:

Web 服务正在返回由 WSDL 定义的对象:

<s:complexType mixed="true"><s:sequence><s:any/></s:sequence></s:complexType>

当我打印出这个对象的类信息时,它会出现:

class com.sun.org.apache.xerces.internal.dom.ElementNSImpl

但我需要将此对象解组为以下类的对象:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = 
        "info",
        "availability",
        "rateDetails",
        "reservation",
        "cancellation",
        "error" ) 
@XmlRootElement(name = "ArnResponse") 
public class ArnResponse  

我知道响应是正确的,因为我知道如何编组这个对象的 XML:

Marshaller m = jc.createMarshaller();
m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
m.marshal(rootResponse, System.out);

打印出来的:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:SubmitRequestDocResponse xmlns:ns2="http://tripauthority.com/hotel">
    <ns2:SubmitRequestDocResult>
        <!-- below is the object I'm trying to unmarshall -->
        <ArnResponse>
            <Info />
            <Availability>
                <!-- etc--> 
             </Availability>
        </ArnResponse>
    </ns2:SubmitRequestDocResult>
</ns2:SubmitRequestDocResponse>

如何将我看到的ElementNSImpl 对象转换为我知道它代表的ArnResponse 对象?

另外,我在 AppEngine 上运行,文件访问受到限制。

感谢您的帮助

更新

我添加了@XmlAnyElement(lax=true) 注释,如下所示:

  @XmlAccessorType(XmlAccessType.FIELD)
  @XmlType(name = "", propOrder = 
      "content"
  )
  @XmlSeeAlso(ArnResponse.class)
  public static class SubmitRequestDocResult 

    @XmlMixed
    @XmlAnyElement(lax = true)
    protected List<Object> content;

但这并没有什么不同。

这与内容是List这一事实有关吗?

这是我在从服务器取回内容后尝试访问内容的代码:

List list = rootResponse.getSubmitRequestDocResult().getContent();

for (Object o : list) 
  ArnResponse response = (ArnResponse) o;
  System.out.println(response);

哪个有输出:

2012 年 1 月 31 日上午 10:04:14 com.districthp.core.server.ws.alliance.AllianceApi getRates 严重: com.sun.org.apache.xerces.internal.dom.ElementNSImpl 不能强制转换为 com.districthp.core.server.ws.alliance.response.ArnResponse

答案:

axtavt 的回答成功了。这有效:

Object content = ((List)result.getContent()).get(0);
JAXBContext context = JAXBContext.newInstance(ArnResponse.class);
Unmarshaller um = context.createUnmarshaller();
ArnResponse response = (ArnResponse)um.unmarshal((Node)content);
System.out.println("response: " + response);

【问题讨论】:

我有响应对象和 WSDL 的所有模式的副本,如果知道有帮助的话。 注意这里使用的Nodeorg.w3c.dom.Node 【参考方案1】:

您可以将该对象传递给Unmarshaller.unmarshal(Node),它应该能够解组它。

【讨论】:

【参考方案2】:

您可以使用@XmlAnyElement(lax=true)。这会将具有已知根元素(@XmlRootElement@XmlElementDecl)的 XML 转换为域对象。示例见:

http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html

【讨论】:

我检查过,但注释已经存在。请看看我更新的问题。再次感谢您的帮助,我以前看过您的博客以及您在 SO 上的其他答案。你的工作对我帮助很大。【参考方案3】:

根据我使用 XML 的发现,anyType 可以表示任何对象,因此您可以将其映射回最接近的对象是 java.lang.Object。 (除此之外,anyType 在技术上可能是一个安全漏洞,允许某人将任何东西(包括恶意二进制文件)注入该位置,并且由于您的架构允许,因此没有什么可以阻止它。)

您最好更改架构以允许映射到您的自定义对象。从编程角度、消费角度和安全角度来看,这都更清晰。

如果您不能这样做,我建议您将类型存储为元素的属性。您可能需要编写自定义代码然后帮助您将anyType 转换回该对象,但至少您知道它的类型。

我的两分钱是根据我的经验(主要是在集成领域)。

【讨论】:

是的,如果可以的话,我不会使用anyType,但我们正在与其他人的架构集成,所以我们坚持使用它。

以上是关于如何从使用 JAXB 的服务返回的“anyType”创建 java 对象?的主要内容,如果未能解决你的问题,请参考以下文章

在Android中调用KSOAP2库访问webservice服务出现的服务端返回AnyType{}

我可以从类似于 jaxb 的 json 数据创建类吗

如何使用 JAXB 从 XML 模式生成 Java 枚举?

在 .NET 中处理 JAXB @XMLIDRef

如何使用 gradle 从 WSDL 和 XSD 生成类,相当于 maven-jaxb2-plugin

即使在JAXB中从XmlAdapter返回null之后,也不会从XML中删除Tag