共通インターフェースを実装するオブジェクトのリストをマーシャリングしようとしています。 3つのクラスと1つのインターフェイスが関係しています。
コミュニティクラス(1つのメソッドがあります:List <Person> getPeople();)
Person interface(1つのメソッドがあります:String getName();)
Girl class(実装Person)
Boy class(実装Person)
以下のコードを参照してください。
次のような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>
要素を別の要素に変更できることに気付きましたが、要素名はGirlクラスまたはBoyクラスで指定した名前にしたいです。
これはできますか?ありがとう。
@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;
}
}
このシナリオでは、@ XmlElementsの使用をお勧めします。 @XmlElementsは、選択のXMLスキーマの概念を表すために使用されます。
以下に例を示します。
@XmlElements({
@XmlElement(name="girl", type=Girl.class),
@XmlElement(name="boy", type=Boy.class)
})
@XmlElementWrapper
public List<Person> getPeople() {
return people;
}
@XmlElementRefは、XMLスキーマの置換グループの概念に対応しています。これが、前の回答で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を通じてクラスのタイプを識別します。また、コンテキスト宣言を整理するのに役立つ @ 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>