Open-source project
FasterXML/jackson-dataformat-xml avatar
FasterXML/jackson-dataformat-xml

jackson-dataformat-xml: XML through the Jackson data-binding model

Extension for Jackson JSON processor that adds support for serializing POJOs as XML (and deserializing from XML) as an alternative to JSON

635 stars251 forksJavaApache-2.0

At a glance

What is it?
jackson-dataformat-xml is the Jackson extension that reads and writes XML with the same ObjectMapper API you already use for JSON, aiming to emulate JAXB code-first binding without claiming to be a JAXB clone or a general XML toolkit. It fits Java teams that want Jackson annotations to drive XML, and it deliberately trades schema-first support and some XML constructs for that.
Who is it for?
jackson-dataformat-xml fits a Jackson codebase that needs to read or write XML without introducing a second binding model, particularly where annotations and polymorphism already carry the mapping. It is the wrong choice for a schema-first project, for a payload using XML constructs the module does not support, and for a team that needs a general purpose XML toolkit.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Code-first binding, and the explicit refusal to be a JAXB clone

The overview is short and unusually clear about what this module is and is not. It contains a Jackson extension component for reading and writing XML encoded data, and the goal is to emulate how JAXB data-binding works with a code-first approach. There is no support added for the schema-first approach. Support for JAXB annotations is provided by a separate JAXB annotation module, and this module supplies low-level abstractions such as XmlParser, ToXmlGenerator and XmlFactory, plus a small number of higher level overrides needed to make data-binding work.

The next paragraph is the one that saves adopters time, because it states the boundary in the project's own words. The goal is not to be a full JAXB clone, and not to be a general purpose XML toolkit. What follows is a four-point clarification.

XML serialization should ideally be similar to JAXB output, but deviations are not automatically considered flaws, and the README gives a reason for some differences. What is guaranteed is that any XML written using the module must be readable using the module as well, described as read what I wrote, which is a full round-trip support aim. Some XML constructs will not be handled, including cases that JAXB and other Java XML libraries support. And the module does support constructs and use cases JAXB does not handle, specifically the rich type and object id support of Jackson.

That last point is the one to hold on to. This is a Jackson module that happens to speak XML, not a JAXB replacement. If you arrive with a schema and expect generated classes, or arrive with JAXB annotations and expect them to work here, you are reading the wrong project.

Two artifact lines, because Jackson 2 and Jackson 3 do not share coordinates

The dependency section in the README exists to make one point that catches people out: the groupId and version to use depend on which Jackson major version you are on.

For the Jackson 3.x line the coordinates are:

xml
<dependency>
  <groupId>tools.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>3.1.1</version>
</dependency>

and the Gradle equivalent is:

groovy
dependencies {
    implementation 'tools.jackson.dataformat:jackson-dataformat-xml:3.1.1'
}

For the Jackson 2.x line the groupId is com.fasterxml.jackson.dataformat and the version shown is 2.21.2, again with a matching Gradle form. The README adds that you should use whatever version is most up-to-date at the moment, which is sensible advice for a module that ships on the same cadence as the core.

The two-coordinate split is not an accident of publishing. The groupId rename from com.fasterxml to tools.jackson marks the Jackson 3 package and artifact restructure, and the module follows it. So the first question when adding this dependency is not which version of the extension but which major version of the core you are on, because picking the wrong one is a resolution failure at best and a subtle runtime mismatch at worst.

The repository reflects the same split in its branches. The 3.x branch is for developing the next major Jackson version, 3.2, and there are active maintenance branches for LTS releases at 3.1, 2.21 and 2.18. Older branches are usually not changed but are available for historic reasons, and all released versions have matching git tags such as jackson-dataformat-xml-2.17.1.

Woodstox is a near-requirement, not an optimisation

The README goes further than a recommendation on the XML library. You usually also want to make sure the XML library in use is Woodstox, since it is not only faster than the Stax implementation the JDK provides, but also works better and avoids some known issues like adding unnecessary namespace prefixes.

The dependency it wants alongside the module is:

xml
<dependency>
  <groupId>com.fasterxml.woodstox</groupId>
  <artifactId>woodstox-core</artifactId>
  <version>6.5.0</version>
</dependency>

with the Gradle form given as well. The namespace-prefix point is the one that matters in practice, because a Jackson module that reads and writes XML will happily produce documents with namespace declarations you did not ask for, and a consumer that compares documents byte for byte or matches on qualified names will object.

Note the groupId here is com.fasterxml.woodstox even for the Jackson 3 section of the README, because Woodstox is a separate project and not part of the Jackson rename.

Underneath, the low-level XML processing is delegated to a Stax implementation, and the README names the three candidates: Woodstox, Aalto, and the JDK-default Oracle implementation. Which one is in play changes what you can configure, which is the subject of the next section.

Building the mapper: default, builder, or a hand-configured factory

The usage section makes an important point about where usage usually happens. Although the module implements the low-level JsonFactory, JsonParser and JsonGenerator abstractions, most usage is through the data-binding level, because a small number of work-arounds have been added at data-binding level to work around XML peculiarities, meaning the stream of JsonTokens that the parser produces has idiosyncrasies that need special handling.

That sentence explains a design decision you would otherwise find puzzling. If the low-level API were the primary interface, the token stream would be the contract. It is not, because the data-binding layer patches around the places where the token stream misbehaves.

The simplest construction is one line:

java
XmlMapper mapper = new XmlMapper();

When you need configuration, the README points to the Builder style construction added in Jackson 2.10:

java
XmlMapper mapper = XmlMapper.builder()
   .defaultUseWrapper(false)
   // enable/disable Features, change AnnotationIntrospector
   .build();

The defaultUseWrapper call is the setting most users meet first. XML has a natural notion of a repeated element, and a wrapper element is how Jackson models a list or a repeated field, so the setting controls whether that wrapper appears in the output.

When you need to control the underlying Stax layer itself, you build the factories by hand and pass them into an XmlFactory:

java
XMLInputFactory ifactory = new WstxInputFactory(); // Woodstox XMLInputFactory impl
ifactory.setProperty(WstxInputProperties.P_MAX_ATTRIBUTE_SIZE, 32000);
// configure
XMLOutputFactory ofactory = new WstxOutputFactory(); // Woodstox XMLOutputfactory impl
ofactory.setProperty(WstxOutputProperties.P_OUTPUT_CDATA_AS_TEXT, true);
XmlFactory xf = XmlFactory.builder()
    .xmlInputFactory(ifactory) // note: in 2.12 and before "inputFactory()"
    .xmlOutputFactory(ofactory) // note: in 2.12 and before "outputFactory()"
    .builder();
XmlMapper mapper = new XmlMapper(xf); // there are other overloads too

The comments flag a compatibility trap: the builder method names changed in 2.12, so code written for an older Jackson will not compile against a newer one on that line alone.

The round-trip guarantee is the real contract, and it is narrower than JAXB

The most important sentence in the whole README is the guarantee about round trips: any XML written using this module must be readable using the module as well, described as read what I wrote. The module aims for full round-trip support.

That is a meaningful guarantee, and it is a different guarantee from JAXB's. What it says is that the module is self-consistent. What it does not say is that the module handles everything, and the README is explicit that some XML constructs will not be handled, including cases that JAXB and other Java XML libraries support.

So the adoption question is a document question rather than an API question. The API is small, and the mapper construction above is the whole of it. The real work is finding out whether your documents are inside the supported subset, and the only way to know is to write them and read them back.

There is a second asymmetry worth keeping in view. The module supports constructs and use cases JAXB does not handle, specifically the rich type and object id support of Jackson. If your data model relies on Jackson's polymorphic type handling and object identifiers, those work here in a way they would not under JAXB. That is the case where this module is genuinely better than a JAXB clone, and it is also the case where the XML you get out is not the XML a JAXB-based system would produce, so any consumer expecting JAXB output needs adjusting.

The status table in the README lists the CI build badge, the Maven Central artifact, the Tidelift sponsorship, the javadoc badge, code coverage for the 3.x branch, an OpenSSF Scorecard badge and a fuzzing status badge. The fuzzing entry is the one that tells you most about the maturity of a parser that reads untrusted input.

Where jackson-dataformat-xml is the wrong tool

The first wrong-tool case is a schema-first project. The README says no support is added for the schema-first approach, so if your binding is driven by an XSD, or by a WSDL contract, this module does not help you. JAXB code-first, in the sense of annotating classes, is what it targets.

The second is a document set that uses XML constructs outside the supported subset. Mixed content, complex namespace handling, or processing instructions with specific requirements may fall into the gap the README describes. If your payloads are documents that other people designed, rather than a schema you control, the risk of hitting an unsupported construct is much higher than if you are round-tripping your own objects.

The third is a need for a general purpose XML toolkit. The README says explicitly that this is not the goal. If you need XPath, XSLT, validation, DTD handling or namespace-aware querying over a document, you need a different library, and this module will not grow into one.

The fourth is a team whose existing investment is JAXB. If you already have JAXB annotations, a JAXB provider and a working code-first pipeline, this module is a migration rather than an addition, and the README's position is that it is not a full JAXB clone. The separate JAXB annotation module gives you the annotations, but the output shape and the round-trip behaviour are not identical to what JAXB produced, so you are changing the shape of your serialized contracts as well as the library.

The fifth is a very small or very simple mapping. Setting up a Woodstox dependency, choosing the right groupId for your Jackson major version and learning the wrapper and namespace behaviour is a lot of ceremony for reading a handful of elements. In that case the plain JDK XML APIs, or a dedicated small XML mapper, are less work.

One more practical limit: the API differences between Jackson 2 and Jackson 3 mean a codebase on the older line cannot simply upgrade this module. The README lists the builder method rename in 2.12 as a note, which is a small hint of how much churn a major version carries.

Maintenance signals, licensing and where the project sits in the Jackson family

The repository is not archived, and the last push was on 2026-10-22, with the default branch being 3.x. The repository has no GitHub releases, and the release-notes directory at the root is where the version history lives instead.

The branch layout is the most useful maintenance signal here, and the README explains it. The 3.x branch is for developing the next major Jackson version, 3.2, and alongside it sit active maintenance branches for LTS releases at 3.1, 2.21 and 2.18. Older branches are usually not changed but are available for historic reasons, and all released versions have matching git tags.

That is a well-organised maintenance policy for a library with users on several major versions, and it is a point in favour of adopting it, because the LTS branches are the ones a conservative team would pin to.

The licence is Apache License 2.0, stated in the README and with a LICENSE file at the repository root, plus a SECURITY.md for reporting vulnerabilities and a CLAUDE.md in the tree. For a data-binding library that most teams consume as a transitive dependency, the licence is rarely the deciding factor, and Apache-2.0 is among the more permissive choices with an explicit patent grant.

The dependency footprint is worth a sentence. The module brings in Woodstox as the practical default Stax implementation, and everything else is Jackson core. There is no additional runtime stack to reason about, which is one of the reasons the Jackson data formats family has been adopted so widely: the XML module slots into an ObjectMapper you already configured rather than asking for a separate binding universe.

Editorial conclusion

jackson-dataformat-xml fits a Jackson codebase that needs to read or write XML without introducing a second binding model, particularly where annotations and polymorphism already carry the mapping. It is the wrong choice for a schema-first project, for a payload using XML constructs the module does not support, and for a team that needs a general purpose XML toolkit. Before adopting it, read the round-trip requirement in the README and test your own documents through write and read, because the module's own guarantee is that what it writes it can read, and that guarantee is narrower than JAXB's.

Frequently asked questions

Is jackson-dataformat-xml a replacement for JAXB?

No, the README states the goal is not to be a full JAXB clone, and it does not support the schema-first approach, only code-first binding.

Which Maven dependency should I use for jackson-dataformat-xml?

For Jackson 3.x use groupId tools.jackson.dataformat with version 3.1.1, and for Jackson 2.x use groupId com.fasterxml.jackson.dataformat with version 2.21.2, as the README shows.

Do I need Woodstox to use jackson-dataformat-xml?

The README says you usually want to make sure Woodstox is the XML library in use, since it is faster than the JDK Stax implementation and avoids issues such as adding unnecessary namespace prefixes.

What does jackson-dataformat-xml guarantee about the XML it writes?

Any XML written using the module must be readable using the module as well, described as read what I wrote, and the module aims for full round-trip support.

Official sources

  1. FasterXML/jackson-dataformat-xml on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fasterxml-jackson-dataformat-xml.svg)](https://hysenlabs.com/projects/fasterxml-jackson-dataformat-xml)

Was this useful?