java 使用 JAXB 和 Any 进行序列化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13941747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Serializing with JAXB and the Any
提问by chubbsondubs
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;
}
Now I try adding another generated JAXB object to that Payload doing something like this:
现在我尝试将另一个生成的 JAXB 对象添加到该 Payload 中,执行如下操作:
Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );
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.
但是我得到了一个可怕的异常,看起来它永远不会工作,所以我决定首先将有效负载对象序列化为 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() );
And this blows up with an exception saying "java.lang.String" does not contain an @XmlRootElement.
这会因“java.lang.String”不包含@XmlRootElement 的异常而爆炸。
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.
那么 xs:any 的使用将如何与 JAXB 一起使用?似乎什么都不想工作,因为 JAXB 将 Payload 转换为 Object,并且它不会序列化 Object 中的任何内容。这一切都在 Axis2 中,因此达到这一点非常具有挑战性。
回答by bdoughan
Below I will demonstrate JAXB (JSR-222)and any
with an example:
下面我将演示JAXB(JSR-222)和any
用一个例子:
Payload
有效载荷
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
.
该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;
}
Foo
富
Below is an example of a class annotated with @XmlRootElement
.
下面是一个用@XmlRootElement
.
package forum13941747;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Foo {
}
Bar
酒吧
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
.
下面是一个没有@XmlRootElement
注释的类的例子。在这个用例中,我们将利用@XmlElementDecl
注释的工厂类(通常称为ObjectFactory
)上的注释@XmlRegistry
。
package forum13941747;
public class Bar {
}
ObjectFactory
对象工厂
Below is an example of specifying an @XmlElementDecl
annotation for the Bar
class.
下面是@XmlElementDecl
为Bar
类指定注释的示例。
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
输入文件
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.
下面是我们将用于此示例的输入文档。有 3 个元素对应于该any
属性。第一个对应于类@XmlRootElement
上的注释Foo
。第二个对应于类的@XmlElementDecl
注释,Bar
第三个不对应于任何域类。
<?xml version="1.0" encoding="UTF-8"?>
<payload>
<foo/>
<bar/>
<other/>
</payload>
Demo
演示
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.
在下面的演示代码中,我们将解组输入文档,然后在结果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);
}
}
Output
输出
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
.
下面是运行演示代码的输出。请注意与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>
回答by jcrshankar
Make use of Object Factory for mashelling the object like below you no need to have @XmlRootElement in DemoType.java .,
使用对象工厂来混搭如下所示的对象,您不需要在 DemoType.java 中使用 @XmlRootElement 。,
DemoType demoServiceRequest = new DemoType();
ObjectFactory obDemo = new ObjectFactory();
Request requestObject = new Request();
requestObject.setAny(obDemo.createDemo(demoServiceRequest));
And add DemoType class at Request.java like @XmlSeeAlso({DemoType.class})
并在 Request.java 中添加 DemoType 类,如 @XmlSeeAlso({DemoType.class})
回答by dbaltor
Should your payload be a XML string, I managed to solve the very same problem using the code below:
如果您的有效负载是 XML 字符串,我设法使用以下代码解决了同样的问题:
import javax.xml.parsers.DocumentBuilderFactory;
//...
String XMLPAYLOAD = "...";
Payload payload = new ObjectFactory().createPayload();
try {
payload.setAny(DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader(XMLPAYLOAD)))
.getDocumentElement());
} catch (Exception e) {
e.printStackTrace();
}
//...