Skip to content

Add support for JAXB's XmlElementWrapper to improve JAXB-specification-compliance #194

@raphw

Description

@raphw

I am creating a new ticket after a comment in a previous thread on this current limitation. I summarize the problem here to avoid the need for constant backtracking.

Problem description

Jackson's XML annotation handler does not currently process the XmlElementWrapper of the JAXB specification. The annotation is originally meant to be used with XML, where the annotations avoids the need for explicitly creating a wrapper element. To create XML like the following:

<root>
  <elements>
    <element/>
    <element/>
  </elements>
</root>

JAXB allows a definition as:

class Root {
  @XmlElement(name = "element")
  @XmlElementWrapper(name = "elements")
  List<Element> elements;
}

This definition is equivalent to having elements defined as a separate object:

class Root {
  @XmlElement(name = "elements")
  Elements elements;
}
class Elements {
  @XmlElement(name = "element")
  List<Element> elements;
}

According to the JAXB-specification, both objects represent the same XML structure and will marshal/unmarshal to/from the above XML structure.

This is not the case for Jackson where the first representation will marshal to the following JSON, even if the JAXB annotation introspector is used:

{"element": [{}, {}]}

whereas the latter representation creates the following JSON:

{"elements":{"element": [{}, {}]}}

Of course, the wrapper element is redundant in JSON, but it has the unfortunate bi-effect that the very same JAXB object representation cannot be marshalled/unmarshalled into one another. If an API contract is using XSD but represents the data as JSON, it is not possible to communicate if not both client and server choose the same XSD-object representation.

Practically, this can affect handrolled JAXB object representations, but it also can cause problems if either client or server use the XEW plugin for XJC whereas the other does not. While APIs still work when using a JAXB-compliant marshaller, using Jackson will violate the contract. In theory, XJC could also add native support for XmlElementWrapper in the future what would likely increase this problem.

Suggested solution

The Jackson unmarshaller should tolerate both representations (wrapped and unwrapped) to increase compatibility, if an XmlElementWrapper tag is discovered. The marshaller should allow for configuration on whether the wrapper tag is needed.

I tried an implementation to showcase that Jackson could introduce such handling. At the same time, I am not an expert on Jackson to understand if this implementation is effective or efficient. Feedback would be appreciated! I am also happy to invest time for helping to integrate this into Jackson's JAXB support.

I also wanted to point out that this is not a similar problem to a possible @JsonWrapped annotation as it was suggested. The XmlElementWrapper wraps exactly one element that is always a list. It's implementation is therefore much simpler that I would consider support for a JsonWrapped annotation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions