使用 JAXB 和 Any 进行序列化 [英] Serializing with JAXB and the Any

查看:48
本文介绍了使用 JAXB 和 Any 进行序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a schema that defines the following type:

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

这会创建一个像这样的对象:

And that creates an object like so:

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

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

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

Now I try adding another generated JAXB object to that Payload doing something like this:

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

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

But I get a terrible exception that looks like it'll never work so I decide to serialize the payload object to XML first then add that as a string in the payload.

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 的异常而爆炸.

And this blows up with an exception saying "java.lang.String" does not contain an @XmlRootElement.

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

So how will the use of xs:any ever work with JAXB? Nothing seems to want to work because JAXB turns the Payload into Object, and it won't serialize just anything in Object. This is all inside Axis2 as well so it's been very challenging to get to this point.

推荐答案

下面我将演示 JAXB (JSR-222)any 以一个例子:

Below I will demonstrate JAXB (JSR-222) and any with an example:

有效载荷

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

The any property is annotated with @XmlAnyElement(lax=true). This means that for that property if an element is associated with a class via @XmlRootElement or @XmlElementDecl then an instance of the corresponding object will be used to populate the property if not the element will be set as an instance of 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;

}

Foo

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

Below is an example of a class annotated with @XmlRootElement.

package forum13941747;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

}

条形

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

Below is an example of a class without the @XmlRootElement annotation. In this use case we will leverage the @XmlElementDecl annotation on a factory class (usually called ObjectFactory) annotated with @XmlRegistry.

package forum13941747;

public class Bar {

}

对象工厂

以下是为 Bar 类指定 @XmlElementDecl 注释的示例.

Below is an example of specifying an @XmlElementDecl annotation for the Bar class.

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);
    }

}

input.xml

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

Below is the input document we'll use for this example. There are 3 elements that correspond to the any property. The first corresponds to the @XmlRootElement annotation on the Foo class. The second corresponds to the @XmlElementDecl annotation for the Bar class and the third does not correspond to any of the domain classes.

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

演示

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

In the demo code below we will unmarshal the input document, then output the classes of the objects in the resulting any property and then marshal the payload object back to 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 的一个实例.

Below is the output from running the demo code. Note the classes corresponding to the objects in the any property. The foo element became an instance of the Foo class. The bar element became an instance of JAXBElement that holds an instance of Bar. The other element became an instance of 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>

这篇关于使用 JAXB 和 Any 进行序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆