java - 使用 JAXB 和 Any 序列化

标签 java xsd jaxb axis2

我有一个定义以下类型的架构:

<xsd:complexType name="Payload">
   <xsd:sequence>
      <xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
   </xsd:sequence>
</xsd:complexType>

这样就创建了一个对象:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Payload", propOrder = {
    "any"
})
public class Payload {

    @XmlAnyElement(lax = true)
    protected List<Object> any;
}

现在我尝试将另一个生成的 JAXB 对象添加到该有效负载中,执行如下操作:

Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );

但我遇到了一个可怕的异常,看起来它永远不会工作,所以我决定先将有效负载对象序列化为 XML,然后将其作为字符串添加到有效负载中。

StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance( sdoRequest.getClass() );
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(new JAXBElement(new QName("uri", sdoRequest.getClass().getSimpleName()), sdoRequest.getClass(), sdoRequest), writer);
payload.getAny().add( writer.toString() );

这会引发异常,提示“java.lang.String”不包含@XmlRootElement。

那么 xs:any 的使用将如何与 JAXB 一起工作?似乎什么都不想工作,因为 JAXB 将有效负载转换为对象,并且它不会序列化对象中的任何内容。这也都在 Axis2 中,因此要达到这一点非常具有挑战性。

最佳答案

下面我来演示JAXB (JSR-222)any 示例:

负载

any 属性使用 @XmlAnyElement(lax=true) 注释。这意味着对于该属性,如果元素通过 @XmlRootElement@XmlElementDecl 与类关联,则相应对象的实例将用于填充属性,否则该元素将被设置为 org.w3c.dom.Element 的实例。

package forum13941747;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Payload", propOrder = {
    "any"
})
public class Payload {

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

}

下面是一个用 @XmlRootElement 注释的类的例子。

package forum13941747;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

}

下面是一个没有 @XmlRootElement 注释的类的示例。在此用例中,我们将在使用 @XmlRegistry 注释的工厂类(通常称为 ObjectFactory)上利用 @XmlElementDecl 注释。

package forum13941747;

public class Bar {

}

对象工厂

下面是为 Bar 类指定 @XmlElementDecl 注释的示例。

package forum13941747;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="bar")
    public JAXBElement<Bar> createBar(Bar bar) {
        return new JAXBElement<Bar>(new QName("bar"), Bar.class, bar);
    }

}

输入.xml

下面是我们将用于此示例的输入文档。有 3 个元素对应于 any 属性。第一个对应于 Foo 类上的 @XmlRootElement 注释。第二个对应于 Bar 类的 @XmlElementDecl 注释,第三个不对应于任何域类。

<?xml version="1.0" encoding="UTF-8"?>
<payload>
    <foo/>
    <bar/>
    <other/>
</payload>

演示

在下面的演示代码中,我们将解码输入文档,然后在生成的 any 属性中输出对象的类,然后将 payload 对象编码回 XML .

package forum13941747;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Payload.class, Foo.class, ObjectFactory.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum13941747/input.xml");
        Payload payload = (Payload) unmarshaller.unmarshal(xml);

        for(Object o : payload.any) {
            System.out.println(o.getClass());
        }

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(payload, System.out);
    }

}

输出

下面是运行演示代码的输出。请注意与 any 属性中的对象对应的类。 foo 元素成为 Foo 类的一个实例。 bar 元素成为 JAXBElement 的一个实例,它包含一个 Bar 的实例。 other 元素成为 org.w3c.dom.Element 的实例。

class forum13941747.Foo
class javax.xml.bind.JAXBElement
class com.sun.org.apache.xerces.internal.dom.ElementNSImpl
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<payload>
    <foo/>
    <bar/>
    <other/>
</payload>

关于java - 使用 JAXB 和 Any 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13941747/

相关文章:

java - 如果我必须对大量数据进行二分查找,我应该使用哪种数据类型?

c# - 解析 XML 响应并返回对象集合

Java 通过导入针对 xsd 验证 xml

java - JAXB创建的Java类是否应该有逻辑代码

java - Spring MVC 中的@RequestParam 处理可选参数

java - 实例化 servlet 类登录时出错

java - 通过 gradle 编写 xlsx

java - 如果在 java 类中找不到字段,则 jaxb 捕获异常

java - 使用 jaxb 更改 xml 结构

java - 如何实例化 JAXBElement<String> 对象?