Search code examples
javaxmljacksonfasterxml

How to serialize a list of POJO using FasterXML library


I'm using FasterXML to serialize POJO. I want to serialize a list of my POJO. When serialize a signle POJO I get the expected xml (there's one problem --> question 2) Here's my code:

List<Movie> movies = new ArrayList<>();
// add movies
JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);
xmlMapper = new XmlMapper(module);
xmlMapper.disable(MapperFeature.AUTO_DETECT_CREATORS,
            MapperFeature.AUTO_DETECT_FIELDS,
            MapperFeature.AUTO_DETECT_GETTERS,
            MapperFeature.AUTO_DETECT_IS_GETTERS,
            MapperFeature.AUTO_DETECT_SETTERS,
            MapperFeature.USE_GETTERS_AS_SETTERS);
String xml = xmlMapper.writeValueAsString(movies);

I get this:

<ArrayList>
    <item imdbID="tt0077687" title="The Hobbit" year="1977"/>
</ArrayList>

Here's what I want:

<movies>
    <movie imdbID="tt0077687" title="The Hobbit" year="1977"/>
    <movie imdbID="tt0077687" title="title2" year="1977"/>
</movies>

or

<movie imdbID="tt0077687" title="The Hobbit" year="1977"/>
<movie imdbID="tt0077687" title="title2" year="1977"/>
  1. When I serialize a movie I get this:

Is it possible to get this:

<movie imdbID="tt0077687" title="The Hobbit" year="1977"><movie>

Solution

  • As a general rule, do not try serializing List, Maps or arrays directly as the root-level value: always use a Bean (POJO). Properties may be of any types, recursively.

    The problem is that Java type erasure make things problematic for collection and Map types in general (even with JSON); but there are additional problems for XML.

    So while it may seem unnecessary, I have found it safest to have a simple Object as the root value, even if it's only something like:

    public class Response {
       public List<Movie> movies;
    }
    

    Having said that, to change the name of root element can be done multiple ways. One possibility is to use Jackson annotation @JsonRootName (despite "Json" in there, it applies to all formats).

    Or, you can use ObjectWriter, override root name with:

    String xml mapper.writer().withRootName("movies").writeValueAsString(movies);