Search code examples
javaxmljaxbjax-rsmoxy

How to tell JAXB which fields to serialize at run time?


I want to selectively serialize fields based on the request and the user.

For example, an admin user would be served an XML with some additional fields. Whereas a normal user would get an XML without those fields.

Secondly, at present I use @XmlIDREF to prevent unnecessary expansion of referenced objects or collections.

But sometimes the user might want those details. Making a second request for the referenced object is not be desirable. I want to let the user tell the server that XYZ attribute should be expanded (i.e. include the complete object and not just its reference)

Given a user and a request, based on business logic I can tell which fields should be serialized. Now how do I communicate this information to JAXB?

As far as possible, I do not want to create an XSD. Note that request parameters are dynamic. Which fields to serialize is decided at run-time. So I cannot use something that has to be hard coded - like @Transient or @XmlIDREF annotations.


Solution

  • Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

    In EclipseLink 2.5 (get it here: http://www.eclipse.org/eclipselink/downloads/milestones.php) we added a new feature to MOXy JAXB called Object Graphs. Object Graphs allow to programatically or through metadata select a subset of properties that you want to marshal/unmarshal. Below is an example of creating an object graph to get a subset of data from a Customer, Address, and PhoneNumber model.

        // Create the Object Graph
        ObjectGraph contactInfo = JAXBHelper.getJAXBContext(jc).createObjectGraph(Customer.class);
        contactInfo.addAttributeNodes("name");
        Subgraph location = contactInfo.addSubgraph("billingAddress");
        location.addAttributeNodes("city", "province");
        Subgraph simple = contactInfo.addSubgraph("phoneNumbers");
        simple.addAttributeNodes("value");
    
        // Output XML - Based on Object Graph
        marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, contactInfo);
        marshaller.marshal(customer, System.out);
    

    For More Information