オブジェクトを XML として返す RESTful Jersey Web サービスがあります。返されたオブジェクトのメンバーの 1 つは、実行時までわからないいくつかの可能な型 (すべて共通の基本クラスから派生したもの) の 1 つです。以下に示すように、このメンバーを出力 XML に表示することはできません。
問題をいくつかのサンプルクラスに減らしました:
@XmlRootElement
public abstract class Animal {
public String type;
public Animal() {
type = "?";
}
public Animal(String type) {
this.type = type;
}
}
@XmlRootElement
public class Mammal extends Animal {
public String name;
public Mammal() {
name = "?";
}
public Mammal(String type, String name) {
super(type);
this.name = name;
}
}
@XmlRootElement
public class Zoo {
private Animal creature;
@XmlElementRef
public Animal getCreature() {
return creature;
}
public void setCreature(Animal creature) {
this.creature = creature;
}
public Zoo() {
creature = new Mammal("Mouse", "Mickey");
}
}
@Path("/test")
public class TestResource {
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Zoo get() {
Zoo z = new Zoo();
return z;
}
}
サービスを呼び出すと、次の応答が返されます。
<zoo/>
予想されるクリーチャーは含まれません。
メンバ 'creature' の型を Animal (抽象基本クラス) から Mammal (派生クラス) に変更すると、期待どおりの出力が得られますが、それは適切な解決策ではありません。
そこで、次のコードを get() メソッドに追加しました。
// DIAGNOSTIC CODE: Convert object to XML and send to System.out
try {
JAXBContext context = JAXBContext.newInstance(Zoo.class, Mammal.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(z, System.out);
} catch (JAXBException ex) {
ex.printStackTrace();
}
そして今、サービスからのXMLが間違っていますが(空のタグだけです)、コンソールに正しい出力が表示されます:
<?xml version="1.0" encoding="UTF-8"?>
<zoo>
<mammal>
<type>Mouse</type>
<name>Mickey</name>
</mammal>
</zoo>
さて、その出力を得るために、私は Mammal.class が JAXBContext.newInstance() に渡されたことを確認しなければなりませんでした。 Web サービスによって行われることは、派生した Mammal クラスを認識しないため、オブジェクトを正しくシリアル化できません。それは正しい診断ですか?どうすれば修正できますか?