Сериализация с помощью JAXB и Any
у меня есть схема, которая определяет следующие типа:
<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.ленг.Строка " не содержит @XmlRootElement.
Итак, как будет использовать xs: any когда-либо работать с JAXB? Кажется, ничего не хочет работать, потому что JAXB превращает полезную нагрузку в объект, и он не будет сериализовать что-либо в объекте. Это все внутри Axis2, так что было очень сложно добраться до этой точки.
2 ответов
ниже я продемонстрирую 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
Примечание. В этом случае мы будем использовать @XmlElementDecl
аннотация в классе фабрики (обычно называется ObjectFactory
) аннотируется @XmlRegistry
.
package forum13941747;
public class Bar {
}
ObjectFactory
ниже пример указания @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);
}
}
вход.в XML
Ниже приведен входной документ, который мы будем использовать для этого примера. Есть 3 элемента, которые соответствуют any
собственность. Первый соответствует @XmlRootElement
аннотация Foo
класса. Второй соответствует @XmlElementDecl
Примечание Bar
класс, а третий не соответствует ни одному из доменов занятия.
<?xml version="1.0" encoding="UTF-8"?>
<payload>
<foo/>
<bar/>
<other/>
</payload>
демо
в демо-коде ниже мы будем unmarshal входной документ, а затем вывести классы объектов в результате 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
собственность. The foo
элемент стал пример Foo
класса. The bar
элемент стал экземпляр JAXBElement
, который содержит экземпляр Bar
. The 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>
используйте Object Factory для mashelling объекта, как показано ниже, вам не нужно иметь @XmlRootElement в Демотипе.Ява.,
DemoType demoServiceRequest = new DemoType();
ObjectFactory obDemo = new ObjectFactory();
Request requestObject = new Request();
requestObject.setAny(obDemo.createDemo(demoServiceRequest));
и добавьте класс DemoType по запросу.java, как @XmlSeeAlso ({DemoType.класс})