在javax.xml.bind中使集合成为泛型集合
在我编写的REST服务器中,我有几个集合类,它们包装要从我的服务返回的单个项:在javax.xml.bind中使集合成为泛型集合,java,jaxb,jax-rs,resteasy,Java,Jaxb,Jax Rs,Resteasy,在我编写的REST服务器中,我有几个集合类,它们包装要从我的服务返回的单个项: @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement(name = "person_collection") public final class PersonCollection { @XmlElement(name = "person") protected final List<Person> collection = new Ar
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "person_collection")
public final class PersonCollection {
@XmlElement(name = "person")
protected final List<Person> collection = new ArrayList<Person>();
public List<Person> getCollection() {
return collection;
}
}
以下是输出:
java.lang.String
我认为由于类型擦除,您所要求的是不可能的。任何通用解决方案都会丢失解组所需的容器的“类型” 反思问题
下面是需要进行的反射测试。我认为类型擦除是防止这种情况发生的原因:
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class TestReflection extends AbstractCollection<String> {
private List<Integer> childCollection = new ArrayList<Integer>();
public List<Integer> getChildCollection() {
return childCollection;
}
public static void main(final String[] args) throws Exception {
final TestReflection testReflection = new TestReflection();
final Class<?> cls = testReflection.getClass();
Method method1 = cls.getMethod("getChildCollection", new Class[] {});
System.out.println(method1.getGenericReturnType());
Method method2 = cls.getMethod("getCollection", new Class[] {});
System.out.println(method2.getGenericReturnType());
}
}
然后是以下演示代码:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(PersonCollection.class, Person.class);
PersonCollection pc = new PersonCollection();
pc.getCollection().add(new Person());
pc.getCollection().add(new Person());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(pc, System.out);
}
}
将产生:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person_collection>
<person/>
<person/>
</person_collection>
有关更多信息,请参阅:
java.lang.reflect.Field.getGenericType()
返回一个Type
对象(可能是TypeVariable
的实例),该对象可用于检索集合的实际类型。在最坏的情况下,我可以让每个子类构造函数将其“child”类型的单个Class
参数传递给AbstractCollection
;老实说,我已经记不起反射和泛型的注意事项了,只是有些存在。你不必在@xmlement
上指定@xmlement
属性,所以你只需将@xmlement
添加到AbstractCollection.collection
,让JAXB推断出元素名。@skaffman:它不起作用。我得到了一个javax.xml.bind.JAXBException:class com.example.Person,它的任何超类都不为这个上下文所知。把这个加在你的问题上,我会发布一个答案。@skaffman:补充。请参见上文:-)。+1个很好的问题-目前正在使用EclipseLink JAXB(MOXy)调试此问题。但是,在这种情况下,我们不能从子类(
)中读取泛型类型吗?我找不到一个不涉及XML模式的关于JAXB的好教程。我手工编写了我的类,需要对它们进行注释,以便它们能够正确地封送/解封。如果我不重构成一个抽象的超类,我会让它工作得很好,但我不喜欢生成大量的样板代码。@Ralph-诀窍是知道从子类可以应用到列表(我希望有一种方法)。我在我的回答中添加了一种可能对您有用的替代方法。我的博客是从类开始使用JAXB的一个很好的例子:您的编辑看起来很正确。我得玩它。我来看看你的博客。@Ralph-你可能会发现以下文章很有用:
java.util.List<java.lang.Integer>
java.util.List<T>
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAnyElement;
public abstract class AbstractCollection<T> {
protected List<T> collection = new ArrayList<T>();
@XmlAnyElement(lax=true)
public List<T> getCollection() {
return collection;
}
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Person {
}
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(PersonCollection.class, Person.class);
PersonCollection pc = new PersonCollection();
pc.getCollection().add(new Person());
pc.getCollection().add(new Person());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(pc, System.out);
}
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person_collection>
<person/>
<person/>
</person_collection>