我有一个Animal类和Animal的扩展名为AnimalExtension。
public class Animal
public class AnimalExtension extends Animal
这两个类之间的唯一区别是AnimalExtension有另一个名为animalId的实例变量。 Animal没有此实例变量。
我也有自己的数据类型,我想编组和解组XML。此数据类型称为AnimalList。在AnimalList中,有一个动物列表作为实例变量。
@XmlType(name = "AnimalList")
public class AnimalList{
private List<Animal> animalList;
....
animalList可以包含Animal和AnimalExtension。但是,在XML上我不希望该元素被命名为AnimalExtension;我希望他们都拥有Animal的元素名称。当JAXB知道Animal实际上是AnimalExtension的一个实例时,我只希望显示额外的属性。所以,如果我有一个类似于
的列表List<Animal> animalList = new LinkedList<Animal>();
AnimalExtension animalExtension = new AnimalExtension();
animalExtension.setAnimalId(1);
amimalExtension.setName("Don");
Animal animal = new Animal();
animal.setName("Mike");
animalList.add(animalExtension);
animalList.add(animal);
我希望XML看起来像
<AnimalList>
<Animal name="Don" id="1" />
<Animal name="Mike" />
</AnimalList>
这是我试图做的事情
@XmlElements(
{
@XmlElement(name = "Animal", type = Animal.class),
@XmlElement(name = "Animal", type = AnimalExtension.class)
}
)
public List<Animal> getEntries() {
return animalList;
}
代码编译但是当我尝试运行我的服务器时。它给了我这个与正在发生的事情无关的奇怪错误(BeanCreationException)。我试着让XmlElement的名称对于每种类型都不同并且有效,但这里的挑战是使名称相同。
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'encryptionPayloadContentProvider'
答案 0 :(得分:10)
要映射此用例,您可以利用以下XmlAdapter:
<强> AnimalAdapter 强>
由于AnimalExtension是Animal的超级集合,我们将使用它来生成/使用XML。然后我们将利用animalId属性的值来确定是否将Animal或AnimalExtension的实例返回给AnimalList。
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class AnimalAdapter extends XmlAdapter<AnimalExtension, Animal> {
@Override
public Animal unmarshal(AnimalExtension animalExtension) throws Exception {
if(0 != animalExtension.getAnimalId()) {
return animalExtension;
}
Animal animal = new Animal();
animal.setName(animalExtension.getName());
return animal;
}
@Override
public AnimalExtension marshal(Animal animal) throws Exception {
if(animal.getClass() == AnimalExtension.class) {
return (AnimalExtension) animal;
}
AnimalExtension animalExtension = new AnimalExtension();
animalExtension.setName(animal.getName());
return animalExtension;
}
}
<强> IdAdapter 强>
如果其值为0,我们将需要第二个XmlAdapter来抑制animalId:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class IdAdapter extends XmlAdapter<String, Integer> {
@Override
public Integer unmarshal(String string) throws Exception {
return Integer.valueOf(string);
}
@Override
public String marshal(Integer integer) throws Exception {
if(integer == 0) {
return null;
}
return String.valueOf(integer);
}
}
您的模型类将注释如下:
<强> AnimalList 强>
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name="AnimalList")
public class AnimalList {
private List<Animal> animalList = new ArrayList<Animal>();
@XmlElement(name="Animal")
@XmlJavaTypeAdapter(AnimalAdapter.class)
public List<Animal> getEntries() {
return animalList;
}
}
<强>动物强>
import javax.xml.bind.annotation.XmlAttribute;
public class Animal {
private String name;
@XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<强> AnimalExtension 强>
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
public class AnimalExtension extends Animal {
private int animalId;
@XmlAttribute(name="id")
@XmlJavaTypeAdapter(IdAdapter.class)
public int getAnimalId() {
return animalId;
}
public void setAnimalId(int animalId) {
this.animalId = animalId;
}
}
演示代码
以下演示代码可用于演示此解决方案:
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(AnimalList.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("input.xml");
AnimalList animalList = (AnimalList) unmarshaller.unmarshal(xml);
for(Animal animal : animalList.getEntries()) {
System.out.println(animal.getClass());
}
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(animalList, System.out);
}
}
将生成以下输出:
class AnimalExtension
class Animal
<?xml version="1.0" encoding="UTF-8"?>
<AnimalList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Animal name="Don" id="1"/>
<Animal name="Mike"/>
</AnimalList>
相关信息
您可能会发现以下信息非常有用: