JAXB @XmlElements, different types but same name?(JAXB @XmlElements,不同类型但名称相同?)
问题描述
我有一个 Animal 类和一个名为 AnimalExtension 的 Animal 扩展.
I have an Animal class and an extension of Animal called AnimalExtension.
public class Animal
public class AnimalExtension extends Animal
这两个类的唯一区别是AnimalExtension 有另一个实例变量,叫做animalId.Animal 没有这个实例变量.
The only difference between the two classes is that AnimalExtension has another instance variable called animalId. Animal does not have this instance variable.
我也有自己的数据类型,我想将其编组和解组为 XML.这种数据类型称为 AnimalList.在 AnimalList 中,有一个 Animals 列表作为实例变量.
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.
@XmlType(name = "AnimalList")
public class AnimalList{
private List<Animal> animalList;
....
animalList 可以同时包含 Animal 和 AnimalExtension.但是,在 XML 上,我不希望将元素命名为 AnimalExtension;我希望他们都有动物的元素名称.我只希望在 JAXB 知道 Animal 实际上是 AnimalExtension 的一个实例时显示额外的属性.所以如果我有一个看起来像的列表
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
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 看起来像
I want the XML to look like
<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 的名称都不同,这很有效,但这里的挑战是使名称相同.
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.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'encryptionPayloadContentProvider'
推荐答案
要映射此用例,您可以利用以下 XmlAdapters:
To map this use case you could leverage the following XmlAdapters:
AnimalAdapter
由于 AnimalExtension 是 Animal 的超集,我们将使用它来生成/使用 XML.然后我们将利用 animalId 属性的值来确定是否将 Animal 或 AnimalExtension 的实例返回给 AnimalList.
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.
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:
We will need a second XmlAdapter to suppress animalId if its value is 0:
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:
动物列表
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;
}
}
演示代码
以下演示代码可用于演示此解决方案:
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);
}
}
将产生以下输出:
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>
相关信息
您可能会发现以下信息很有用:
You may find the following information useful:
- http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
- http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
- http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-using-substitution.html
这篇关于JAXB @XmlElements,不同类型但名称相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:JAXB @XmlElements,不同类型但名称相同?
基础教程推荐
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 降序排序:Java Map 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01