Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to ignore a wrapper class during JAXB marshalling

Tags:

java

xml

jaxb

I'm trying to get JAXB to ignore a wrapper class during the Mashalling process, it makes sense to have this wrapper class in code, as it keep all related information together, however I need to get rid of it during the marshaling process. The following is the relevant code.

@XmlType(name = "root")
@XmlRootElement(name = "root")
public class Root {

    @XmlElementRef
    private List<Resource> resources = new ArrayList<>();

    public void addResource(Resource resource) {
        resources.add(resource);
    }
}


@XmlRootElement(name = "", namespace = "")
@XmlAccessorType(XmlAccessType.NONE)
public class Resource {

    @XmlElementRef
    private Element element;
    @XmlElementRef
    private FieldType fieldType;
    @XmlElementRef
    private ListType listType;
}

Root is the main object, and Resource is the wrapper object that I'd like not have a node created for. I still want the Element, FieldType and ListType within the Resource to be rendered however.

This is what I currently have:

<root>
    <>
        <element name="resource1"/>
        <fieldType name="resource1--type">
        </fieldType>
        <listType name="resource--list">
        </listType>
    </>
    <>
        <element name="resource2"/>
        <fieldType name="resource2--type">
        </fieldType>
        <listType name="resource2--list">
        </listType>
    </>
</root>

What I'd like to achieve is the following:

<root>
    <element name="resource1"/>
    <fieldType name="resource1--type">
    </fieldType>
    <listType name="resource--list">
    </listType>
    <element name="resource2"/>
    <fieldType name="resource2--type">
    </fieldType>
    <listType name="resource2--list">
    </listType>
</root>

I don't know if it's possible, but any help would be appreciated.

Thanks.

like image 371
Ruaghain Avatar asked Jun 07 '12 10:06

Ruaghain


People also ask

What is marshalling in JAXB?

The JAXB Marshaller interface is responsible for governing the process of serializing Java content trees i.e. Java objects to XML data. This marshalling to XML can be done to variety of output targets.

What is JAXB marshalling and Unmarshalling?

JAXB definitionsMarshalling is the process of transforming Java objects into XML documents. Unmarshalling is the process of reading XML documents into Java objects. The JAXBContext class provides the client's entry point to the JAXB API. It provides API for marshalling, unmarshalling and validating.

What is @XmlRootElement?

Annotation Type XmlRootElementMaps a class or an enum type to an XML element. Usage. The @XmlRootElement annotation can be used with the following program elements: a top level class. an enum type.

What is JAXB_ fragment?

The -jaxb. fragment command determines whether the marshaller generates document-level events in the XML data. This command is optional. If you omit it, the default is false. Document-level events are not generated in the XML data.


2 Answers

You cannot achieve that in JAXB. Even if you would be able to serialize like this, using a XmlAdapter for example, it will be impossible to deserialize it.

Try this:

@XmlType(name = "root")
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.NONE)
public class Root {

    private ArrayList<Resource> resources = new ArrayList<Resource>();

    public void addResource(Resource resource) {
        resources.add(resource);
    }

    @XmlElementRefs(value = { @XmlElementRef(type = Element.class),
                              @XmlElementRef(type = ListType.class),
                              @XmlElementRef(type = FieldType.class) })
    public List<Object> getResourceFields() {
        List<Object> list = new ArrayList<Object>();
        for (Resource r : resources) {
            list.add(r.getElement());
            list.add(r.getFieldType());
            list.add(r.getListType());
        }
        return list;
    }
}

Basically getRerourceFields concatenates all the resources' fields in the same list. If you cannot change the Root class, this could be your RootAdapter and use it as @Biju suggested.

like image 73
tibtof Avatar answered Oct 14 '22 02:10

tibtof


You probably will have to create an XmlAdapter for your Root class, this adapter should basically map your root instances to a different type, where you can flatten your root structure before marshalling - along these lines:

public class CustomRootAdapter extends
                    XmlAdapter<CustomRoot,Root>> {
@Override
public Root unmarshal(CustomRoot v) throws Exception {
    return null;//if you are not keen on unmarshalling..
}
@Override
public CustomRoot marshal(Root v) throws Exception {
    return ...;
}    

}

You can register this Custom adapter using:

@XmlJavaTypeAdapter(CustomRootAdapter.class) with your Root class

like image 44
Biju Kunjummen Avatar answered Oct 14 '22 02:10

Biju Kunjummen