10

我正在尝试使用 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 是一个接口,JAXB 不能处理接口。
    此问题与以下位置有关:
        在 java.lang.Comparable
        在受保护的 java.lang.Comparable com.controlpath.util.Range.start
        在 example.util.Range
        在 example.util.DoubleRange
        在公共 example.util.DoubleRange example.domain.SomeBean.getRange()
        在 example.domain.SomeBean

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

4

6 回答 6

5

您可以通过执行以下操作来编写自定义适配器(不使用 JAXB 的 XmlAdapter):

1)声明一个接受各种元素并具有JAXB注释并根据需要处理它们的类(在我的示例中,我将所有内容都转换为字符串)

@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

笔记

  • 当然,这不适用于复杂(嵌套)数据结构。
  • 您必须考虑如何再次将其解组,这可能会更加棘手。如果太棘手,请等待比我更好的建议;)
于 2009-05-06T00:41:49.067 回答
1

怎么样

public class Range<**E extends Number**> implements Serializable { ...
  • 数字是一个

  • 我打赌 JAXB 知道Number 的默认编组/解组规则

要解组到特定类型,您需要 XmlAdapter,正如我在此处描述的那样:JAXB 继承,解组到编组类的子类

于 2009-05-06T00:45:38.167 回答
0

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

于 2009-05-05T20:21:30.970 回答
0

实际上,我不太清楚为什么这不起作用。似乎 JAXB 应该能够正确解析特定的子类型:如果(且仅当!)此类型不是根类型(它不是根据您的描述)。我的意思是,它只是一个 Bean;因此,如果将 T 替换为直接类型的 bean 有效,那么泛型版本应该使用子类化来绑定类型(如示例中所做的那样)。

所以也许这可能是实现中的一个错误?

于 2010-01-30T05:38:58.170 回答
0

我所做的是以下内容:

  1. 创建一个空类并将其标记为 JAXB
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class Marshallable {}
  1. 使每个将在泛型类中结束的类作为类型扩展这个 Marshallable 类型
(...)
public class A extends Marshallable {
(...)
  1. 将您的泛型类限制为仅允许 Marshallable 的子类作为泛型类型
public class GenericType<T extends Marshallable> {
  1. 使用你原本打算的课程
A a = new A();

jaxbMarshaller.marshal(new GenericType(a), outputStream);

现在 Jaxb 将适用于扩展 Marshallable 的所有类型,甚至作为泛型类型的一部分。

于 2021-12-20T21:49:13.487 回答
-1

所以看起来问题是Eonstartendis的擦除Comparable。如果它不能处理你可以尝试的接口Object,但我希望它也会抱怨(现在或以后)。可能您可以将Range其抽象化并针对每个特定的E. 我应该更多地了解 JAXB。

于 2009-05-05T21:43:44.983 回答