2009-05-05 66 views
10

我试图使用JAXB的内省来编组并且取消对一些现有的使用JAXB标注标记的域对象的解析。大多数事情都按预期工作,但是我得到一个相当简单的类来序列化时遇到了一些麻烦。该类被用作对一些豆类的@XmlElement看起来类似:JAXB编组和泛型

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是还在生的界面相媲美。

public class DoubleRange extends Range<Double> {} 

同时使用范围和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 

我意识到,在大多数情况下列表<牛逼>和地图< T,U >只工作因为JAXB规范在遇到bean时对这些类型有特殊规定,但是有什么方法可以将我想要的内容传达给JAXB自省引擎,而无需使用非泛型字段来实现范围的重新实现?

回答

5

你可以写一个自定义适配器(不使用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你要被编组类

注意

  • 当然这将而不是工作复杂(嵌套)的数据结构。
  • 你必须思考如何解开这个回来,可能会更棘手。如果 它太狡猾,等待比我更好的建议;)
+0

我想了解为什么JAXB很难受,并避免大量的自定义编组代码(因为我相信我会击中这在将来的某个时刻再次发生,可能在更复杂的对象上)。但从技术上讲,这是一个答案,如果没有其他人有更好的答案,我会在几天内将其标记为这样。谢谢=) – 2009-05-06 14:28:53

0

尝试类似Simple XML Serialization它支持XML元素中的泛型类型,并带有许多注释(如@Element和@ElementList)。编程模型非常相似,但比JAXB更简单。

-1

所以看起来问题是startendE的删除是Comparable。如果它不能处理接口,你可以尝试Object,但我希望它也抱怨(现在或以后)。可能你可以制作Range摘要并专门针对每个特定的E。我应该更多地了解JAXB。

+0

我在假设DoubleRange类能解决擦除问题时不正确吗?我尝试重新定义getter为public Double getEnd()和public Double getStart(),但我得到了同样的错误。它看起来好像对于类型来说太深了。 – 2009-05-05 22:57:32

+0

IIRC,JAXB可以查看获取者和设置者或者(更好)字段。如果是后者,那么你需要将字段移动到专门的类,并使g​​etStart/getEnd抽象。可能抽象类不应该注释为JAXB可编码的。我不是这方面的专家,因为你可能会知道...... – 2009-05-05 23:29:51

0

其实,为什么这是行不通的这是不太清楚,我。看起来JAXB应该能够正确解析特定的子类型:if(且仅当!)这种类型不是根类型(它不是根据您的描述)。我的意思是,它只是一个豆;所以如果用T替换直接类型的bean,那么应该使用子类来绑定类型(如在示例中所做的那样)。

所以也许它可能是一个实施中的错误?