java JAXB @XmlElements,不同类型但同名?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5007516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JAXB @XmlElements, different types but same name?
提问by denniss
I have an Animal class and an extension of Animal called AnimalExtension.
我有一个 Animal 类和一个名为 AnimalExtension 的 Animal 扩展。
public class Animal
public class AnimalExtension extends Animal
The only difference between the two classes is that AnimalExtension has another instance variable called animalId. Animal does not have this instance variable.
这两个类之间的唯一区别是 AnimalExtension 有另一个名为 AnimalId 的实例变量。Animal 没有这个实例变量。
I also have my own data type that I want to marshal and unamarshal to XML. This data type is called AnimalList. inside AnimalList, there is a list of Animals as an instance variable.
我也有自己的数据类型,我想将其编组和解组为 XML。这种数据类型称为 AnimalList。在 AnimalList 中,有一个 Animals 列表作为实例变量。
@XmlType(name = "AnimalList")
public class AnimalList{
private List<Animal> animalList;
....
animalList can contain both Animal and AnimalExtension. However, on the XML I dont want the element to be named as AnimalExtension; I want them all to have element name of Animal. I only want the extra attribute to show up when JAXB knows that the Animal is actually an instance of AnimalExtension. So if I have a list of that looks like
动物列表可以包含动物和动物扩展。但是,在 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);
I want the XML to look like
我希望 XML 看起来像
<AnimalList>
<Animal name="Don" id="1" />
<Animal name="Mike" />
</AnimalList>
This is what I have tried to do
这就是我试图做的
@XmlElements(
{
@XmlElement(name = "Animal", type = Animal.class),
@XmlElement(name = "Animal", type = AnimalExtension.class)
}
)
public List<Animal> getEntries() {
return animalList;
}
The code compiles but when I try running my server. It gives me this weird error that is so unrelated to what is going on (BeanCreationException). I tried making the name of the XmlElement to be different for each type and that works, but the challenge here is to make the name the same.
代码编译但当我尝试运行我的服务器时。它给了我这个与正在发生的事情无关的奇怪错误(BeanCreationException)。我尝试使 XmlElement 的名称对于每种类型都不同并且有效,但这里的挑战是使名称相同。
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'encryptionPayloadContentProvider'
采纳答案by bdoughan
To map this use case you could leverage the following XmlAdapters:
要映射此用例,您可以利用以下 XmlAdapter:
AnimalAdapter
动物适配器
Since AnimalExtension is a super set of Animal we will use it to produce/consume XML. Then we will leverage the value of the animalId property to determine if an instance of Animal or AnimalExtension will be returned to AnimalList.
由于 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
身份适配器
We will need a second XmlAdapter to suppress animalId if its value is 0:
如果其值为 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);
}
}
Your model classes will be annotated as follows:
您的模型类将被注释如下:
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;
}
}
Animal
动物
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;
}
}
Demo Code
演示代码
The following demo code can be used to demonstrate this solution:
以下演示代码可用于演示此解决方案:
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);
}
}
The following output will be produced:
将产生以下输出:
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>
Related Information
相关信息
You may find the following information useful:
您可能会发现以下信息很有用: