[英]JAXB Marshalling and Generics
我正在嘗試使用 JAXB 的自省來編組和解組一些用 JAXB 注釋標記的現有域對象。 大多數事情都按預期工作,但我在序列化一個相當簡單的類時遇到了很多麻煩。 這個類在許多 bean 上用作 @XmlElement,看起來像:
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;
}
}
我嘗試了以下操作,沒有成功,JAXB 仍然對接口 Comparable 生氣。
public class DoubleRange extends Range<Double> {}
使用 Range 和 DoubleRange 作為 bean getter 的返回類型會產生如下異常:
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
我意識到在大多數情況下 List<T> 和 Map<T, U> 僅起作用,因為 JAXB 規范對在 bean 上遇到這些類型時有特殊規定,但是有什么方法可以將我想要的內容傳達給 JAXB 自省引擎而不必重新實現具有非通用字段的范圍?
您可以通過執行以下操作編寫自定義適配器(不使用JAXB的XmlAdapter):
1)聲明一個接受所有類型元素並具有JAXB注釋並根據需要處理它們的類(在我的示例中,我將所有內容轉換為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)在你的待編組課程中使用這個課程而不是E課程
筆記
怎么樣
public class Range<**E extends Number**> implements Serializable { ...
數字是一個類
我敢打賭JAXB知道Number的默認編組/解組規則
對於特定類型的解組,你需要我在這里描述的XmlAdapter: JAXB繼承,unmarshal到封送類的子類
實際上,我不清楚為什么這不起作用。 似乎JAXB應該能夠正確地解析特定的子類型:if(並且僅當!)此類型不是根類型(它不是根據您的描述)。 我的意思是,它只是一個豆; 因此,如果將T替換為直接類型的bean工作,那么通用版本iff應使用子類來綁定類型(如示例中所示)。
那么也許它可能是實施中的一個錯誤?
我所做的是以下內容:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class Marshallable {}
(...)
public class A extends Marshallable {
(...)
public class GenericType<T extends Marshallable> {
A a = new A();
jaxbMarshaller.marshal(new GenericType(a), outputStream);
現在 Jaxb 將適用於所有擴展 Marshallable 的類型,甚至作為泛型類型的一部分。
嘗試像Simple XML Serialization這樣的東西,它支持XML元素中的泛型類型,帶有許多注釋,如@Element和@ElementList。 編程模型非常相似,但比JAXB更簡單。
所以看起來問題是E
在start
和end
的擦除是Comparable
。 如果它無法處理接口你可以嘗試Object
,但我希望它也會抱怨(現在或以后)。 可能你可以使Range
抽象並為每個特定的E
專門化它。 我應該更多地了解JAXB。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.