用JaxB编组实现通用接口的对象列表

我试图编组实现通用接口的对象列表。 有3个类和1个接口涉及:

社区类(有一个方法: List <Person> getPeople();

Person接口(有一个方法: String getName();

女生课(实施人)

男孩class(实施人)

看下面的代码。

我想要一个如下所示的XML:

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

或者可能:

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

到目前为止,我得到的是这样的:

 <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> 

我意识到我可以将元素改为别的东西,但是我希望元素名称是女孩或男孩类中的名字。

可以这样做吗? 谢谢。

 @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; } } 

对于这种情况,我会build议使用@XmlElements。 @XmlElements用于表示XML模式select的概念:

这是如何看你的例子:

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

@XmlElementRef对应于XML模式中的replace组的概念。 这就是为什么以前的答案要求将Person从接口更改为类。

好的,如果你准备把Person从一个接口变成一个抽象的基类,那么你就是金。 代码如下:

 public class Main { public static void main(String[] args) throws Exception { Community community = new Community(); JAXBContext context = JAXBContext.newInstance(Community.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(community, System.out); } } @XmlRootElement(name = "community") @XmlSeeAlso({Person.class}) public class Community { private List<Person> people; @XmlElementWrapper(name="people") @XmlElementRef() 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="boy") public class Boy extends Person { public String getName() { return "John"; } } @XmlRootElement(name="girl") public class Girl extends Person { public String getName() { return "Jane"; } } @XmlRootElement(name = "person") @XmlSeeAlso({Girl.class,Boy.class}) public abstract class Person { @XmlElement(name="name") public abstract String getName(); } 

主要的技巧是在社区列表中使用@XmlElementRef 。 这通过它的@XmlRootElement来标识类的types。 您可能也有兴趣@XmlSeeAlso这有助于组织上下文的声明。

而输出是

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <community> <people> <girl> <name>Jane</name> </girl> <boy> <name>John</name> </boy> <girl> <name>Jane</name> </girl> <boy> <name>John</name> </boy> </people> </community>