Java 使用JaxB编组实现公共接口的对象列表

Java 使用JaxB编组实现公共接口的对象列表,java,xml,jaxb,Java,Xml,Jaxb,我试图整理一个实现公共接口的对象列表。 涉及3个类和1个接口: 社区类(有一个方法:列出getPeople();) Person接口(有一个方法:字符串getName();) 女孩班级(个人) 男孩班级(个人) 请参阅下面的代码 我想要一个如下所示的XML: <community> <people> <girl> <name>Jane</name> </girl> <boy>

我试图整理一个实现公共接口的对象列表。 涉及3个类和1个接口:

社区类(有一个方法:列出getPeople();

Person接口(有一个方法:字符串getName();

女孩班级(个人)

男孩班级(个人)

请参阅下面的代码

我想要一个如下所示的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;
   }

}
@XmlRootElement(name=“community”)
公共阶层社区{
私人名单;
@XmlElementWrapper
@xmlement(name=“person”)
公共列表getPeople(){
还人,;
}
公共社区(){
people=newarraylist();
添加(新女孩());
添加(新男孩());
添加(新女孩());
添加(新男孩());
}
}
@XmlRootElement(name=“girl”)
公务班女生{
@XmlElement
公共字符串getName(){
返回“Jane”;
}
}
@XmlRootElement(name=“boy”)
公共班级的男孩是一个人{
@XmlElement
公共字符串getName(){
返回“约翰”;
}
}
@XmlJavaTypeAdapter(AnyTypeAdapter.class)
公共接口人员{
公共字符串getName();
}
公共类AnyTypeAdapter扩展了XmlAdapter{
@凌驾
公共对象封送处理(对象v)引发异常{
返回v;
}
@凌驾
公共对象解组(对象v)引发异常{
返回v;
}
}

好的,如果您准备将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();
}
公共类主{
公共静态void main(字符串[]args)引发异常{
社区=新社区();
JAXBContext context=JAXBContext.newInstance(Community.class);
Marshaller=context.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
马歇尔(社区,系统,输出);
}
}
@XmlRootElement(name=“community”)
@XMLSEEALLO({Person.class})
公共阶层社区{
私人名单;
@xmlementwrapper(name=“people”)
@xmlementref()
公共列表getPeople(){
还人,;
}
公共社区(){
people=newarraylist();
添加(新女孩());
添加(新男孩());
添加(新女孩());
添加(新男孩());
}
}
@XmlRootElement(name=“boy”)
公务舱男学生{
公共字符串getName(){
返回“约翰”;
}
}
@XmlRootElement(name=“girl”)
公务舱女生{
公共字符串getName(){
返回“Jane”;
}
}
@XmlRootElement(name=“person”)
@XMLSEEALSE({Girl.class,Boy.class})
公共抽象类人物{
@xmlement(name=“name”)
公共抽象字符串getName();
}
主要的技巧是在社区列表中使用。这通过@XmlRootElement标识类的类型。您可能还对有助于组织上下文声明的应用程序感兴趣

输出是

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

简
约翰
简
约翰

对于这个场景,我建议使用@XmlElements@XmlElements用于表示选择的XML模式概念:

下面是您的示例的外观:

@XmlElements({ 
    @XmlElement(name="girl", type=Girl.class),
    @XmlElement(name="boy", type=Boy.class)
})
@XmlElementWrapper
public List<Person> getPeople() {
    return people;
}
@XmlElements({
@XmlElement(name=“girl”,type=girl.class),
@XmlElement(name=“boy”,type=boy.class)
})
@XmlElementWrapper
公共列表getPeople(){
还人,;
}
@XmlElementRef对应于XML模式中的替换组概念。这就是为什么前面的答案要求将Person从接口更改为类的原因