JAXB编组和泛型

Ste*_*rla 10 java generics jaxb

我正在尝试使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图做以下事情,但没有成功,JAXB仍然对Comparable接口感到愤怒.

public class DoubleRange extends Range<Double> {}
Run Code Online (Sandbox Code Playgroud)

使用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内省引擎无需重新实现非通用字段的范围?

iva*_*off 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
Run Code Online (Sandbox Code Playgroud)

2)在你的待编组课程中使用这个课程而不是E课程

笔记

  • 当然,这会不会对复杂的(嵌套)数据结构工作.
  • 你必须考虑如何再次解决这个问题,可能会更棘手.如果它太棘手了,等待比我更好的提议;)