Сериализация с помощью 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.класс})