-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for JAXB's XmlElementWrapper to improve JAXB-specification-compliance #194
Comments
Hi @cowtowncoder, Would you be interested in an integration? Cheers. |
@raphw I am always interested in improvements. My only concern is wrt scope of changes needed -- so while I wish I could promise to integrate it all I can say is that I will definitely consider it. And if nothing else it may well be possible to create a module that would implement this. This could mean adding some extensibility into ps. And no problem at all about "bothering" me :) |
I would certainly keep things backwards compatible but allow for configuration via the module. I will prepare a pull request based on my suggestions, that makes it easier to discuss the code. We can see about scope and details from there. |
I have an immediate struggle already: How would I handle that I need a dependency on the XML serializer module to support XML serialization. Would introducing such an (optional) dependency be an issue? |
@raphw Right, ideally databind deals with all serialization/deserialization aspects, possibly by checking some capabilities of the backend (there are some introspection methods in So... ideally as few overrides of shared functionality as possible (and jackson-databind specifically has no format-specific checks, cannot depend on XML module). But sometimes sub-classing may be needed. Not sure if above helps, but for what it is worth XML module is by far the most customized backend for Jackson. With a few gnarly hacks. One more won't make a humongous difference if necessary. |
The problem I am facing is that I can only communicate an additional property by registering an How would I be able to add an additional property to a serializer other then by adjusting the |
Hmmh. Yeah, complexity on that class is already bit scary. I don't really have a good answer. But looking at the original problem statement, I wonder if part of the problem is one key difference between Jackson XML module's defaults and JAXB: Jackson defaults to using "wrapper" element for |
If you have an example on how to switch it, any pointer is appreciated! I only found this thread stating that it's not currently possible: FasterXML/jackson-databind#512 |
@raphw Sorry, different feature: XML List wrapping is not related to more general functionality (... which does not exist). Disabling wrapping on individual List properties is done with annotation
but default can be changed with: protected XmlMapper _xmlMapper = mapperBuilder()
.propertyNamingStrategy(new PropertyNamingStrategies.UpperCamelCaseStrategy())
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.defaultUseWrapper(false)
// Or in 2.x directly
xmlMapper.setDefaultUseWrapper(false); with this setting, no wrapping is added, same as default JAXB. Default differs for historical reasons. |
This is different to the JAXB case, though. The problem is that the class is represented on the server side as: class Root {
@XmlElement(name = "elements")
Elements elements;
}
class Elements {
@XmlElement(name = "element")
List<Element> elements;
} and on the client side as: class Root {
@XmlElement(name = "element")
@XmlElementWrapper(name = "elements")
List<Element> elements;
} I would need to be able to represent both the same way. My idea was that I would expand the latter example. I would not know how to do this still given your example. Are you addressing another problem? |
I only mentioned this since it is directly related to additional/missing wrapping. Not that I thought it would be the same thing necessarily. But looking at examples I do think it is relevant: with JAXB implementation, |
Indeed, but the issue is that the two representations in the ticket's description would be both representing the same, valid JAXB structure. I do not think it is currently possible to marshal them to the same XML/JSON representation. Or do I miss something? |
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:JAXB allows a definition as:
This definition is equivalent to having
elements
defined as a separate object: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:
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. TheXmlElementWrapper
wraps exactly one element that is always a list. It's implementation is therefore much simpler that I would consider support for aJsonWrapped
annotation.The text was updated successfully, but these errors were encountered: