JAXB编组和泛型 [英] JAXB Marshalling and Generics
问题描述
我试图使用JAXB的自省对marshall进行反编译并取消对JAXB注释标记的某些现有域对象的解除。大多数事情都按预期工作,但是我得到一个相当简单的类来序列化时遇到了一些麻烦。这个类在许多bean上用作@XmlElement,看起来像这样:
public class Range< E extends Comparable< E - 代替;>实现Serializable {
protected boolean startInclusive,endInclusive;
保护E开始,结束;
public Range(){
startInclusive = endInclusive = true;
$ b $ public boolean contains(E value){...}
public E getEnd(){
return end;
}
public void setEnd(E end){
this.end = end;
}
public boolean isEndInclusive(){
return endInclusive;
}
public void setEndInclusive(boolean endInclusive){
this.endInclusive = endInclusive;
}
public E getStart(){
return start;
}
public void setStart(E start){
this.start = start;
}
public boolean isStartInclusive(){
return startInclusive;
}
public void setStartInclusive(boolean startInclusive){
this.startInclusive = startInclusive;
}
}
我试图做到以下几点,但没有成功,JAXB仍然对Comparable接口感到愤怒。
public class DoubleRange extends Range< Double> {}
使用Range和DoubleRange作为bean getter的返回类型会产生如下异常: p>
java.lang.Comparable是一个接口,JAXB无法处理接口。
此问题与以下位置有关:
在java.lang.Comparable $ b $ protected at protected java.lang.Comparable com.controlpath.util.Range.start
at example。 util.Range
at example.util.DoubleRange
at public example.util.DoubleRange example.domain.SomeBean.getRange()
at example.domain.SomeBean
我知道在大多数情况下,List< T>和Map< T,U>因为JAXB规范在遇到bean时对这些类型有特殊的规定,但是有什么方法可以传达我想要的JAXB自省引擎,而不必使用非泛型字段来实现范围?
通过执行以下操作, p> 1)声明一个接受各种元素并拥有JAXB注释
的类并按照你的意愿处理它们(在我的例子中,我将所有东西都转换为字符串)
@YourJAXBAnnotationsGoHere
public class MyAdapter {
@XmlElement //或@XmlAttribute如果您希望
私有字符串内容;
$ b $ public MyAdapter(Object input){
if(input instanceof String){
content =(String)input;
} else if(输入instanceof YourFavoriteClass){
content =((YourFavoriteClass)input).convertSomehowToString();
} else if(input instanceof .....){
content =((.....)input).convertSomehowToString();
//等等
} else {
content = input.toString();
}
}
}
//我建议使用Map< Class<>,IMyObjToStringConverter> ...
//避免讨厌的if-else-instanceof事物
<2>使用这个类而不是E在你要编组的类中
NOTES
- 当然,这对于复杂的(嵌套的)数据结构是 not 。
- 你必须考虑如何解组,可能会更棘手。如果
太棘手,请等待比我更好的提案;)
I am trying to use JAXB's introspection to marshall and unmashall some existing domain objects marked up with JAXB annotations. Most things work as expected, but I am having quite a bit of trouble getting a fairly simple class to serialize. This class is used as an @XmlElement on a number of beans and looks something like:
public class Range<E extends Comparable<E>> implements Serializable { protected boolean startInclusive, endInclusive; protected E start, end; public Range(){ startInclusive = endInclusive = true; } public boolean contains(E value){...} public E getEnd() { return end; } public void setEnd(E end) { this.end = end; } public boolean isEndInclusive() { return endInclusive; } public void setEndInclusive(boolean endInclusive) { this.endInclusive = endInclusive; } public E getStart() { return start; } public void setStart(E start) { this.start = start; } public boolean isStartInclusive() { return startInclusive; } public void setStartInclusive(boolean startInclusive) { this.startInclusive = startInclusive; } }
I have tried to do the following, with no success, JAXB is still angry with the interface Comparable.
public class DoubleRange extends Range<Double> {}
Using both Range and DoubleRange as return types for the bean getter's yields an exception like:
java.lang.Comparable is an interface, and JAXB can't handle interfaces. this problem is related to the following location: at java.lang.Comparable at protected java.lang.Comparable com.controlpath.util.Range.start at example.util.Range at example.util.DoubleRange at public example.util.DoubleRange example.domain.SomeBean.getRange() at example.domain.SomeBean
I realize that in most cases List<T> and Map<T, U> only work because the JAXB specification has special provisions for those types when they are encountered on beans, but is there any way to convey what I want to the JAXB introspection engine without having to reimplement range with non-generic fields?
解决方案You could write a custom adapter (not using JAXB's XmlAdapter) by doing the following:
1) declare a class which accepts all kinds of elements and has JAXB annotations and handles them as you wish (in my example I convert everything to String)
@YourJAXBAnnotationsGoHere public class MyAdapter{ @XmlElement // or @XmlAttribute if you wish private String content; public MyAdapter(Object input){ if(input instanceof String){ content = (String)input; }else if(input instanceof YourFavoriteClass){ content = ((YourFavoriteClass)input).convertSomehowToString(); }else if(input instanceof .....){ content = ((.....)input).convertSomehowToString(); // and so on }else{ content = input.toString(); } } } // I would suggest to use a Map<Class<?>,IMyObjToStringConverter> ... // to avoid nasty if-else-instanceof things
2) use this class instead of E in your to-be-marshalled class
NOTES
- Of course this would not work for complex (nested) data structures.
- You have to think how to unmarshall this back again, could be more tricky. If it's too tricky, wait for a better proposal than mine ;)
这篇关于JAXB编组和泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!