1

JAXB.marshal が呼び出されたときに、クラス AdapterDataObj を使用してクラス DataObj を AdaptedDataObj に変換しています。


package test;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(AdapterDataObj.class)
public class DataObj { 
    public String bla = "I'm DataObj";
    public String name; 
    public DataObj(String name) { 
        this.name = name;
    }

    } 
    

package test; 
public class AdaptedDataObj {
        public String bla="I'm AdaptedDataObj";
        public  String name;

        public AdaptedDataObj(String name) {
            this.name = name;
        }
}

package test; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 
public class AdapterDataObj extends XmlAdapter { 
    @Override
    public DataObj unmarshal(AdaptedDataObj v) throws Exception {
        return null; // not needed in this case
    }

    @Override
    public AdaptedDataObj marshal(DataObj v) throws Exception {
        System.out.println("Marschal for " + v.name + " called!");
        return new AdaptedDataObj(v.name);
    } 
}

ここで、DataObj を新しいクラスに入れ、このクラスに対して JAXB.marshal を呼び出します。出力は問題ないようです。AdaptedDataObj が呼び出されたというメッセージも表示されます。


package test; 
import javax.xml.bind.JAXB; 
public class Testobj { 
    public DataObj x; 
    public Testobj() {
        x = new DataObj("Hallo World");
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Testobj");
        System.out.println("=================================");
        Testobj to = new Testobj();
        JAXB.marshal(to, System.out);
    } 
}

ここで、" public DataObj x;" を " "に変更しますpublic Object x;。これは、そのクラスに DataObj だけでなく格納したいからです。

ただし、この場合、AdapterDataObj は呼び出されなくなります。AdapterDataObj ではなく DataObj が xml としてエクスポートされます。

どこに問題があるのか​​ わかりますか?

また、@XmlJavaTypeAdapter を package-info.java に追加することに成功しませんでした。AdapterDataObj はまだ呼び出されていません。Java 1.7.0_45 および 1.8.0-ea でテストしました。


package test; 
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlSeeAlso; 
@XmlSeeAlso({DataObj.class})
public class Testobj3 { 
        public Object x; 
    public Testobj3() {
        x = new DataObj("Hallo World");
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Testobj3");
        System.out.println("=================================");
        Testobj3 to3 = new Testobj3();
        JAXB.marshal(to3, System.out);
    } 
}
4

1 に答える 1

2

JAXB 2.2仕様によると:

XmlAdapter を拡張し、クラス、インターフェース、または Enum 型 (つまり、メタ アノテーション @Target={type} に一致するプログラム要素) で指定される @XmlJavaTypeAdapter は、次のように参照ポイントで boundType を適応させる必要があります。

  1. 参照型が boundType であるプロパティ/フィールド
  2. boundType がパラメトリック型として使用されるプロパティ/フィールド

そのため、JAXB が Adapter を使用する必要があることを認識するためには、フィールド/プロパティが特定のタイプである必要があります。

同じ理由で、ルート要素でアダプターを使用することはできません。説明は、終了した JAXB の問題JAXB-117 にあります。

アダプターは、インスタンスではなく、型に対して定義されます。特に、アダプターは、インスタンスからだけで正しいアダプターを常に推測できるとは限らないように設計されています。

編集 JAXB クラスでオブジェクトを使用することはあまり一般的ではありません。おそらく、保存したいオブジェクトには共通点があるため、注釈を付けることができるインターフェイス/基本クラスを抽出できます@XmlJavaTypeAdapter。共通点がない場合は、別々のプロパティとして保存する方がよいでしょう。

于 2013-10-24T08:59:56.873 に答える