Jackson XmlMapper Single vs Multi Element Arrays

Jackson’s XmlMapper handles arrays and collections by mapping repeated XML tags to list elements, but dealing with single-element arrays often presents challenges due to XML’s lack of native array notation. This article explains how XmlMapper distinguishes between single and multi-element arrays during serialization and deserialization, the common pitfalls encountered when parsing single tags into collections, and the configurations and annotations used to ensure consistent data structures.

The Core Challenge with XML and Arrays

Unlike JSON, which explicitly defines arrays using square brackets [], standard XML has no native data type for arrays. Instead, collections in XML are represented either by repeated sibling tags or by wrapping child tags inside a parent container.

Because of this ambiguity, a parser must infer whether a single XML element is meant to be a standalone property, an object, or the only item inside an array.

Deserializing Multi-Element vs. Single-Element XML

Multi-Element Behavior

When Jackson encounters multiple sibling elements with the same tag name, it naturally groups them into a collection or array if the target POJO defines the field as a List, Set, or array.

<library>
    <book>Book A</book>
    <book>Book B</book>
</library>

In this case, Jackson maps both <book> entries into a List<String> books without any special configuration.

Single-Element Behavior

When only a single tag is present in the XML payload, XmlMapper faces an ambiguity:

<library>
    <book>Book A</book>
</library>

By default, standard Jackson data binding may fail with a MismatchedInputException if it expects an array structure but encounters a single element, or it may interpret the tag as a single scalar value rather than a collection.

Enabling Single-Value Array Support

To ensure that a single XML element is properly deserialized into a collection or array, configure the DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY setting on the XmlMapper instance:

XmlMapper xmlMapper = new XmlMapper();
xmlMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);

When this feature is enabled, Jackson automatically wraps a lone <book>Book A</book> tag into a List<String> containing one element, eliminating the mismatch between single-element and multi-element payloads.

Handling Wrapped vs. Unwrapped Collections

Jackson provides specific annotations to control how arrays and collections are parsed and generated.

1. Wrapped Collections (Default)

By default, Jackson expects a wrapping parent tag around collection items:

<library>
    <books>
        <book>Book A</book>
        <book>Book B</book>
    </books>
</library>

In a Java class, this corresponds to:

public class Library {
    @JacksonXmlElementWrapper(localName = "books")
    @JacksonXmlProperty(localName = "book")
    private List<String> books;
}

If the collection is empty, the wrapper tag may remain empty (<books/>), making the array intent explicit even when zero or one element exists.

2. Unwrapped Collections

When XML structures omit the container tag and place items directly under the root, you must disable wrapping using @JacksonXmlElementWrapper(useWrapping = false):

public class Library {
    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty(localName = "book")
    private List<String> books;
}

This annotation explicitly informs XmlMapper that repeated <book> tags directly belong to the books list. When combined with ACCEPT_SINGLE_VALUE_AS_ARRAY, Jackson consistently parses zero, one, or multiple <book> tags into the target collection.