2

I am trying to use Jackson's XML annotations to serialize a Map to XML. I am converting the Map to a List in order to use the map keys as the element names and the values as the element values, and I am so close to getting the desired XML.

My class looks like:

@JacksonXmlRootElement(localName = "request")
public class TrackingEvent {
    private List<JAXBElement<String>> data = new ArrayList<JAXBElement<String>>();

    public TrackingEvent() {}

    public TrackingEvent addData(String key, String value) {
        data.add(new JAXBElement<String>(new QName(key), String.class, value));
        return this;
    }

    public Map<String, String> getData() {
        Map<String, String> dataAsMap = new HashMap<String, String>(data.size());
        for (JAXBElement<String> elem : data) {
            dataAsMap.put(elem.getName().getLocalPart(), elem.getValue());
        }
        return Collections.unmodifiableMap(dataAsMap);
    }
}

My test code (quick-n-dirty, not an actual test):

@RunWith(JUnit4.class)
public class TrackingEventMapperTest {

    @Test
    public void eventToXml() throws Exception {
        TrackingEvent e = new TrackingEvent().addData("eVar17", "woohoo");

        XmlMapper mapper = new XmlMapper();
        mapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
        mapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
        System.out.println("\n" + 
            mapper.writerWithDefaultPrettyPrinter().writeValueAsString(e));        
    }
}

And here is the XML it generates:

<?xml version='1.0' encoding='UTF-8'?>
<request>
  <data>
    <eVar17>woohoo</eVar17>
  </data>
</request>

But what I am looking for is:

<?xml version='1.0' encoding='UTF-8'?>
<request>
  <eVar17>woohoo</eVar17>
</request>

I have tried adding a @JacksonXmlElementWrapper(useWrapping = false) annotation to both the data declaration and its getter, but that appears to do nothing. I can change the name of the element adding a @JacksonXmlProperty(localName = "moop") to the declaration/getter, but cannot figure out how to leave it out entirely.

I am pretty sure I can use JAXB annotations as well from reading Jackson's docs, but haven't found anything via Google there either.

As you can probably guess, I am trying to create an XML document representing Omniture data, and trying to send all the eVar and prop variables in a way where I don't have to explicitly include them in my POJO.

My Solution

I decided to abandon any use of Jackson as the XML I need is not that complex, but forcing Jackson to do what I wanted to was getting increasingly complex. I decided to use STAX2 to write the XML directly using the same implementation that Jackson uses under the covers. This allows me to customize the XML however I want.

Blaise's answer sure seemed like it would have done exactly what I wanted though.

Todd Hansberger
  • 487
  • 4
  • 10
  • 1
    FYI - Here is how it can be done using EclipseLink JAXB (MOXy): http://stackoverflow.com/questions/13163430/jaxb-marshal-an-arraylist-created-by-xmladapter/13163680#13163680 – bdoughan Jan 21 '13 at 21:08
  • Hmmmm, I looked into using MOXy to do this, and it looks like it would do exactly what I want. However, we use Nexus to assist with our Maven repos, and there are apparently workarounds in getting Nexus to get the JARs, and I am not a Nexus admin and don't feel comfortable proposing all the changes just for this one JAR. Basically, there is a lot of extra work in getting MOXy JARs into your project which makes this solution a no-go. Oh well. – Todd Hansberger Jan 22 '13 at 14:25
  • It looks like Jackson's XML data binding in version 2.1.x should allow for this. – Todd Hansberger Feb 20 '13 at 14:26

0 Answers0