Serializing collections as XML and JSON

742 views
Skip to first unread message

Pål Skjager Løberg

unread,
Sep 23, 2014, 3:58:19 AM9/23/14
to jackso...@googlegroups.com

I believe I must be missing something here, but after fighting Jackson for a long time I feel it's time to ask :-)

I have a POJO like:


@XmlRootElement(name = "device")
public class Foo {

    @XmlAttribute(name = "id")
    private String id;

    @XmlElement(name = "name")
    private String name;
...
}

When I create a collection of these, like an ArrayList, and serialize them to JSON using the ObjectMapper I get what I want:

[
 
{"id" : "1", "name" : "Foo One"},
 
{"id" : "2", "name" : "Foo Two"}
]


However, if I serialize to XML using XmlMapper I get:

<ArrayList>
 
<item id="1">
   
<name>Foo One</name>
 
</item>
 
<item id="2">
   
<name>Foo Two</name>
 
</item>
</ArrayList>


For XML I would like to change the outer element from "ArrayList" to "foos" and then "item" should be "foo". If I wrap it in my own class I'm able to do so, but that changes the JSON structure...

I'm doing this from inside Jersey, setting it up using in my ResourceConfig:

   XmlMapper om = new XmlMapper();
   om
.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION);
   om
.registerModule(new JodaModule());
   om
.registerModule(new JaxbAnnotationModule());
   om
.registerModule(new JacksonXmlModule());
   
register(new JacksonJaxbXMLProvider(om, JacksonJaxbXMLProvider.DEFAULT_ANNOTATIONS));

Any suggestions on how to get the collections correctly serialized?
  

Thanks,

 -- Paul

Tatu Saloranta

unread,
Sep 23, 2014, 11:52:06 AM9/23/14
to jackso...@googlegroups.com
My first suggestion is to never serialize root-level Collections, Lists or Maps.
Even on  a good day, Type Erasure is likely to cause issues; and instead to use a POJO. Collections/Map work just fine on any other level.
Also some of annotations that are available for properties can not be used for types, or are cumbersome to use.

So in this case, the usual way of changing root element name (@XmlRootElement or equivalent) is not available, unless you sub-class ArrayList. While this is doable (i.e. you can create subtype, add annotation), a better alternative may be to define root name override via writer:

 String xml = xmlMapper
                .writer()
                .withRootName("foos")
                .writeValueAsString(list);

The other problem, however, is something I don't know answer to.
If this was a property, it would be done using @XmlElementWrapper.
Choice of "item", for root-level Collections, is essentially hard-coded; comment in XmlSerializerProvider saying:

   // Could repeat root name, but what's the point? How to customize?

so that the thought of allowing it to be changed has crossed my mind at some point. I am open to suggestions for configuring this. An easy thing would be to add a setter for XML module / mapper to change String.
Finding root name for value is trickier, since type information may or may not be available; peeking at first value might work.

Hope this helps,

-+ Tatu +-


--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages