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> {}

Bean getterの戻りタイプとしてRangeとDoubleRangeの両方を使用すると、次のような例外が発生します。

java.lang.Comparableはインターフェースであり、JAXBはインターフェースを処理できません。
    この問題は、次の場所に関連しています。
        java.lang.Comparableで
        保護されたjava.lang.Comparablecom.controlpath.util.Range.startで
        example.util.Rangeで
        example.util.DoubleRangeで
        public 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のようなものを試してみてください。これには、@Elementや@ElementListなどの多数のアノテーションを持つXML要素のジェネリック型がサポートされています。プログラミングモデルは非常に似ていますが、JAXBよりも単純です。

于 2009-05-05T20:21:30.970 に答える
0

実際、なぜこれがうまくいかないのか、私にはよくわかりません。JAXB は特定のサブタイプを正しく解決できるように思われます: このタイプがルート タイプではない場合 (説明どおりではない場合のみ)。つまり、それは単なる Bean です。したがって、T が直接型に置き換えられた Bean が機能する場合は、サブクラス化を使用して型をバインドするジェネリック バージョンが動作するはずです (例で行われているように)。

おそらく、実装のバグである可能性がありますか?

于 2010-01-30T05:38:58.170 に答える
-1

Eしたがって、問題はonstartendisの消去にあるようですComparable。インターフェイスを処理できない場合は、試すことができますがObject、それについても文句を言うことを願っています(今または後で)。Rangeおそらく、抽象化して、特定の ごとに特化することができますE。JAXBについてもっと知っておくべきです。

于 2009-05-05T21:43:44.983 に答える