- @XmlElement
- @XmlElementWrapper
- @XmlList
- @XmlList and @XmlAttribute
- @XmlList and @XmlValue
Java Model
For this example we will use the following model. We will apply different JAXB annotations to observe the effect it has on the XML representation.
import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { private List<String> emailAddresses; public Customer() { emailAddresses = new ArrayList<String>(); } public List<String> getEmailAddresses() { return emailAddresses; } public void setEmailAddresses(List<String> emailAddresses) { this.emailAddresses = emailAddresses; } }
Demo Code
The following code will be used to convert the Customer object to XML. We will examine the impact of changing the metadata on the XML representation.
import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Customer.class); Customer customer = new Customer(); customer.getEmailAddresses().add("janed@example.com"); customer.getEmailAddresses().add("jdoe@example.org"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } }
Default
By default each item in the collection will be marshalled to an XML element.
<customer> <emailAddresses>janed@example.com</emailAddresses> <emailAddresses>jdoe@example.org</emailAddresses> </customer>
@XmlElement
We can control the name of the XML element a collection item is marshalled to by using the @XmlElement annotation.
import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlElement(name="email-address") private List<String> emailAddresses; }
The following is the corresponding XML output:
<customer> <email-address>janed@example.com</email-address> <email-address>jdoe@example.org</email-address> </customer>
@XmlElementWrapper
Sometimes we want to add a grouping element to organize our collection data. This is done using the @XmlElementWrapper annotation.
import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlElementWrapper(name="email-addresses") @XmlElement(name="email-address") private List<String> emailAddresses; }
The following is the corresponding XML output:
<customer> <email-addresses> <email-address>janed@example.com</email-address> <email-address>jdoe@example.org</email-address> </email-addresses> </customer>
@XmlList
We can also represent our collection data as space seperated text. This is done using the @XmlList annotation.
import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlList private List<String> emailAddresses; }
The following is the corresponding XML output:
<customer> <emailAddresses>janed@example.com jdoe@example.org</emailAddresses> </customer>
@XmlList and @XmlAttribute
Since @XmlList allows us to represent a collection in a single piece of text it is also compatible with an XML attribute.
import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlList @XmlAttribute private List<String> emailAddresses; }
The following is the corresponding XML output:
<customer emailAddresses="janed@example.com jdoe@example.org"/>
@XmlList and @XmlValue
Since @XmlList allows us to represent a collection in a single piece of text it is also compatible with a single text node.
import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlList @XmlValue private List<String> emailAddresses; }
The following is the corresponding XML output:
<customer>janed@example.com jdoe@example.org</customer>
Thanks for posting. In a Spring application that I wrote using JAXB for marshalling, I chose to live with the ugly XML and have a nice Java API for the JAXB objects. Now I now that I can indeed have my cake and eat it to by using this metadata capability.
ReplyDeleteThanks Sudhakar. The MOXy JAXB implementation has even more mapping options. Check out XPath Based Mapping - Geocode Example
ReplyDeletePerfect - Just what I was looking for :)
ReplyDeleteThanks for posting.
ReplyDeleteSuppose we have List, Can we define Type of element present in List with annotation?
If you are using an untyped list, then you can specify the type using @XmlElement(type=Foo.class).
ReplyDelete-Blaise
You're a legend - I was looking for a summary just like this. Coming from an XStream background the marshalling done by JAXB seemed counter-intuitive at first...
ReplyDeleteHi Blaise,
ReplyDeleteCan we convert a JAXB object into DOCUMENT object or INPUTSTREAM object??If yes how??
Which annotation can I use for java's Map ?
ReplyDeleteJAXB has a default representation for java.util.Map. If you want more control of the XML format you can use an XmlAdapter:
ReplyDelete- XmlAdapter - JAXB's Secret Weapon
I've also been considering the following extension to cover maps:
- https://bugs.eclipse.org/322423
-Blaise
You can create an org.w3c.dom.Document and use JAXB to marshal an object into it. You can also marshal object to something like a ByteArrayOutputStream and then create a ByteArrayInputStream from that. You may also be able to leverage javax.xml.bind.util.JAXBSource.
ReplyDelete-Blaise
Blaise, when unmarshalling is there a way of automatically applying @XmlElementWrapper to collections using Java 6 and JAXB 2.1?
ReplyDeleteI had a look at Bjarne Hansen's plugin but this isn't compatible with JAXB 2.1
JAXB does not currently provide a standard way to generate an @XmlElementWrapper annotation when generating Java classes from an XML schema (although I think it should).
ReplyDeleteI was not aware of Bjarne Hansen's plugin, I will take a look at it and post back. You may want to contact him about its use in JAXB 2.1.
-Blaise
Hello Blaise (sorry for cross-postings),
DeleteAre there any developments on this front? I couldn't get this plugin to work with a recent xjc (2.2.4), and I would really like to tell xjc to skip certain levels and generate an @XmlElementWrapper instead.
Thanks again for your tireless work in providing great and clear jaxb/xsd/xjc examples.
~Pierre
Hi Pierre,
DeleteI'm happy to hear you are finding the blog useful. I haven't had a chance to investigate this plug-in yet. Have you tried contacting the author (Bjarne Hansen) of the plug-in?
-Blaise
Thx for helpful examples. I was little bit nervous but now it works perfect. :)
ReplyDeleteI had been searching for a long time, and now found the solution in this post. Thank u very much!
ReplyDeleteAnd even years later your post helped me a lot :)
ReplyDeleteThanks for posting.
Likewise. Very useful post.
ReplyDelete