The goal is to produce the following XML with JAXB
<foo>
<bar>string data</bar>
<bar>binary data</bar>
</foo>
Is there a workaround to allow generic @XmlValue
fields (I need to store byte[]
and String
data)? Below is what I desire:
@XmlRootElement
public class Foo {
private @XmlElement List<Bar> bars;
}
@XmlRootElement
public class Bar<T> {
private @XmlValue T value; // (*)
}
But I get this exception
(*) IllegalAnnotationException:
@XmlAttribute/@XmlValue need to reference a Java type that maps to text in XML.
The trick I'm usually using is to create schema with types you want and then use xjc to generate Java classes and see how annotations are used. :) I believe in XML schema proper type mapping for byte[] is 'base64Binary', so creating schema like this:
and running xjc we would get following code generated:
I couldn't get
@XmlValue
working as I always gotNullPointerException
along the way—not sure why. I came up with something like the following instead.Drop your
Bar
class entirely, because, as you want it to be able to contain anything you can simply represent it withObject
.Without telling JAXB which namespaces your types are using every
bar
element inside afoo
would contain separate namespace declarations and stuff—thepackage-info.java
and all the namespace stuff serves only fancification purposes only.Running this simple test would spout-out something similar to your XML snippet.
Output:
You could leverage an
XmlAdapter
for this use case instead of@XmlValue
:BarAdapter
Foo
The
XmlAdapter
is associated with thebars
property using the@XmlJavaTypeAdapter
annotation:Bar
Demo
You can test this example using the following demo code:
Output
Note how the output includes the
xsi:type
attributes to preserve the type of the value. You can eliminate the thexsi:type
attribute by having yourXmlAdapter
returnString
instead ofObject
, if you do this you will need handle the conversion fromString
to the appropriate type yourself for the unmarshal operation:https://stackoverflow.com/a/3074027/1851289 could be a duplicate, however the answer has other 2 options.
Is there a reason you don't simply construct a String with your byte[]? Do you truly need a generic?