Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshalling a List of objects implementing a common interface, with JaxB

Tags:

java

xml

jaxb

I am trying to marshall a list of objects implementing a common interface. There are 3 classes and 1 interface involved:

Community class (has one method: List<Person> getPeople();)

Person interface (has one method: String getName();)

Girl class (implements Person)

Boy class (implements Person)

See code below.

I want an XML that looks something like this:

<community>   <people>     <girl>       <name>Jane</name>     </girl>     <boy>       <name>John</name>     </boy>     <girl>       <name>Jane</name>     </girl>     <boy>       <name>John</name>     </boy>   </people> </community> 

or possibly:

<community>   <people>    <person>       <girl>         <name>Jane</name>       </girl>     </person>     <person>       <boy>         <name>John</name>       </boy>     </person>   </people> </community> 

So far what I get is this:

<community>     <people>         <person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="girl">             <name>Jane</name>         </person>         <person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="boy">             <name>John</name>         </person>         <person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="girl">             <name>Jane</name>         </person>         <person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="boy">             <name>John</name>         </person>     </people> </community> 

I realize I can change the element to something else, but I want the element name to be the name spesified in the Girl or Boy class.

Can this be done? Thanks.

@XmlRootElement(name = "community") public class Community {   private List<Person> people;   @XmlElementWrapper  @XmlElement(name="person")  public List<Person> getPeople() {   return people;  }   public Community() {   people = new ArrayList<Person>();   people.add(new Girl());   people.add(new Boy());   people.add(new Girl());   people.add(new Boy());  } }        @XmlRootElement(name = "girl") public class Girl implements Person {   @XmlElement  public String getName() {   return "Jane";  } }   @XmlRootElement(name = "boy") public class Boy implements Person {   @XmlElement  public String getName() {   return "John";  } }    @XmlJavaTypeAdapter(AnyTypeAdapter.class) public interface Person {  public String getName(); }    public class AnyTypeAdapter extends XmlAdapter<Object, Object> {   @Override    public Object marshal(Object v) throws Exception {     return v;    }   @Override    public Object unmarshal(Object v) throws Exception {     return v;    }  } 
like image 884
Beni Avatar asked Nov 10 '10 12:11

Beni


People also ask

How does JAXB marshalling work?

In JAXB, marshalling involves parsing an XML content object tree and writing out an XML document that is an accurate representation of the original XML document, and is valid with respect the source schema. JAXB can marshal XML data to XML documents, SAX content handlers, and DOM nodes.

How do you Unmarshal a list of objects?

public List<T> Unmarshal(List<Entry> entries, Class clazz) { List<T> out = new ArrayList<T>(); T instance; for (Entry e : entries) { try { JAXBContext context = JAXBContext. newInstance(clazz); Unmarshaller unmarsh = context.

What is marshalling in Java?

In the Java-related RFC 2713, marshalling is used when serialising objects for remote invocation. An object that is marshalled records the state of the original object and it contains the codebase (codebase here refers to a list of URLs where the object code can be loaded from, and not source code).


1 Answers

For this scenario I would recommend the use of @XmlElements. @XmlElements is used to represent the XML schema concept of choice:

  • http://bdoughan.blogspot.com/2010/10/jaxb-and-xsd-choice-xmlelements.html

Here is how it would look for your example:

@XmlElements({      @XmlElement(name="girl", type=Girl.class),     @XmlElement(name="boy", type=Boy.class) }) @XmlElementWrapper public List<Person> getPeople() {     return people; } 

@XmlElementRef corresponds to the concept of substitution groups in XML schema. This is why the previous answer requires Person to be changed from an interface to a class.

  • http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-using-substitution.html
like image 146
bdoughan Avatar answered Oct 09 '22 17:10

bdoughan