我有一个Animal类和一个名为AnimalExtension的Animal扩展。
public class Animal
public class AnimalExtension extends Animal
这两个类之间的唯一区别是AnimalExtension还有另一个实例变量叫做animalId。Animal没有此实例变量。
我也有自己的数据类型,想要对XML进行封送处理。此数据类型称为AnimalList。在AnimalList内,有一个Animals列表作为实例变量。
@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'
要映射此用例,可以利用以下XmlAdapters:
动物适配器
由于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);
}
}
模型类的注释如下:
动物名单
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;
}
}
动物延伸
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>
相关信息
您可能会发现以下信息有用:
问题内容: 我在这里已经读到,在Java中,具有相同名称但不同类型的两个变量可以在同一范围内共存。我的意思是这个 但是所有的Java IDE都不允许这样的代码。我想知道这样的代码在语法上是否正确,或者只是IDE不允许这样的代码防止歧义。 无论如何,这是网站的摘录 “如果幸运的话,您也许能够重新编译Jad的输出。 但是,Java VM对于变量命名的规则比Java语言本身更为宽松。例如,一个有效的类文
但所有java IDE都不允许这样的代码。我想知道这样的代码在语法上是否真的正确,或者只是IDE不允许这样的代码来防止歧义。 总之,这里是从网站上摘录的 “如果你幸运的话,你也许可以重新编译JAD的输出。然而,Java VM对变量命名的规则比Java语言本身更宽松。例如,一个有效的类文件可以有几个名为'a'的变量,只要它们有不同的类型。如果你反编译这样的类,你得到的源代码将是无效的。 JAD通常会
问题内容: 以下代码可以正常工作。在两个不同的结构上操作并打印该结构的字段的两种方法: 在控制台中显示所需的输出: 现在 ,如果我以以下方式更改方法签名,则会出现编译错误。我只是将方法的接收者移动到方法的参数: 我什至无法编译程序: 问 :为什么 当 方法具有相同的名称和Arity 时 ,我可以在接收器中互换结构类型,而不能在参数中互换结构类型? 问题答案: 因为Go不支持在其参数类型上重载用户定
我可以看到它不工作,因为我尝试了它。我只是无法解释为什么一定要这样。 第二个方法来自一个类,该类是实现第一个getValue()方法的类的子类。 为什么同名不足以覆盖该方法?我想到的唯一论点是,它将反对“是一个”关系,因为用A扩展的第二个方法的类必须具有与A相同的能力,如果你重写返回类型,你就打破了那个法律,对吧?
问题内容: 我今天在另一个问题中提出了这个问题,但是 由于措辞的方式,恐怕无法解决任何问题。 我有一个json输入,其中包含以下数据: 杰森 如您所见,option_value项是一个对象中的Array和 另一个对象中的简单字符串。 我怎样才能让Gson正确处理呢?我的类将此描述为 List对象,因此它适用于option_value是 数组的前几个项目,但是当它成为字符串时,应用程序崩溃,并且我收
我在一次面试中被问到以下问题: 问题:名称和签名相同但返回类型不同的方法。他问我,可能吗?这种类型叫什么。 有人能告诉我以下情况吗: > 上面的事情在任何情况下都是可能的(至少像一个在基类中,一个在派生类中?)如果是,是什么类型?比如编译或运行时多态? 在编译时多态性中,如果方法的返回类型与签名也不同,该怎么办?但只有函数的名称是相同的。还是编译时多态性吗? 在重写中,如果我有不同的返回类型,但方