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.