2

I have a requirement to marshal both json and xml outputs. But, how to generate JSON output using MOXy JAXB in Spring? I can generate the xml file as shown in the example at: http://wiki.eclipse.org/EclipseLink/Examples/MOXy/Spring/JAXBDynamicOXM

The documentation does not have any examples for outputting json. I know that I can use JAXB Marshaller to generate the json output by setting the jaxb properties. How to do the same using MOXy/Spring/JAXB?

Appreciate your help!

Ngun
  • 75
  • 1
  • 3
  • 5

1 Answers1

2

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

The following answer is based on the example from the MOXy wiki:

eclipselink-oxm.xml

Normally JAXB/MOXy is used with a static domain model. In the example you lined to there there isn't a real model, all the metadata is supplied via MOXy's metadata file.

<?xml version="1.0" encoding="US-ASCII"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="example.gettingstarted">
    <java-types>
        <java-type name="Customer">
            <xml-root-element/>
            <java-attributes>
                <xml-element java-attribute="name" type="java.lang.String" xml-path="personal-info/name/text()" />
                <xml-element java-attribute="address" type="example.gettingstarted.Address" xml-path="contact-info/address" />
                <xml-element java-attribute="phoneNumbers" type="example.gettingstarted.PhoneNumber" container-type="java.util.ArrayList" xml-path="contact-info/phone-number" />
            </java-attributes>
        </java-type>
        <java-type name="PhoneNumber">
            <java-attributes>
                <xml-attribute java-attribute="type" type="java.lang.String"/>
                <xml-value java-attribute="value" type="java.lang.String"/>
            </java-attributes>
        </java-type>
        <java-type name="Address">
            <xml-root-element/>
            <java-attributes>
                <xml-element java-attribute="street" type="java.lang.String" xml-path="street/text()" />
                <xml-element java-attribute="city" type="java.lang.String" xml-path="city/text()" />
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

jaxb.properties

To use MOXy with dynamic models you need to specify a different jaxb.properties file than normal:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory

Demo

In the example below we will convert an XML document into a dynamic model, and then marshal it to JSON. Note the context path ("forum12162216" in this example) must correspond to the package name that contains the jaxb.properties file. JSON binding is enabled by setting the "eclipselink.media-type" property on the Marshaller.

package forum12162216;

import java.io.File;
import java.util.*;

import javax.xml.bind.*;

import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.MarshallerProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum12162216/eclipselink-oxm.xml");
        JAXBContext jc = JAXBContext.newInstance("forum12162216", Demo.class.getClassLoader(), properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum12162216/customer.xml");
        DynamicEntity customer = (DynamicEntity) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
        marshaller.marshal(customer, System.out);
    }

}

customer.xml

<?xml version="1.0" encoding="UTF-8"?>
<customer>
    <personal-info><name>Jane Doe</name></personal-info>
    <contact-info>
        <address>
          <city>My Town</city>
          <street>123 Any Street</street>
        </address>
        <phone-number type="work">613-555-1111</phone-number>
        <phone-number type="cell">613-555-2222</phone-number>
    </contact-info>
</customer>

Output

{
   "customer" : {
      "personal-info" : {
         "name" : "Jane Doe"
      },
      "contact-info" : {
         "address" : {
            "street" : "123 Any Street",
            "city" : "My Town"
         },
         "phone-number" : [ {
            "type" : "work",
            "value" : "613-555-1111"
         }, {
            "type" : "cell",
            "value" : "613-555-2222"
         } ]
      }
   }
}

For More Information

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Thanks Blaise. I'm using Jaxb2Marshaller as noted in the spring/Moxy example, and the Jaxb2Marshaller doesn't seem to have the setProperty method. How can you print to Sysout or to browser using that jaxb2marshaller? also, I'm using Maven, where should the binding oxm.xml file be placed?, I have jaxb.properties in the same package as the model classes. – Ngun Aug 28 '12 at 17:54
  • @Ngun - There is an initJaxbMarshaller(Marshaller) method that looks promising but you would need to implement a subclass of `Jaxb2Marshaller` to leverage it: http://static.springsource.org/spring-ws/sites/1.5/apidocs/org/springframework/oxm/jaxb/Jaxb2Marshaller.html. Here is a link to an example that will help with the Maven aspect: https://github.com/bdoughan/blog20120418 – bdoughan Aug 28 '12 at 18:09
  • @Ngun - In the properties map where the OXM metadata file is specified, you could also set the `"eclipselink.media-type"` property to `"application/json"`. – bdoughan Aug 28 '12 at 18:25