6

次の例を検討してください。

ClassAとそれを拡張したClassBがあります。私の問題は、xml ファイルからClassBをアンマーシャリングする必要があることです。ClassAは私の管理下にないため、変更できないことに注意してください。

この例では、いくつかの問題が指摘されています。

主な問題は、ClassAには、アダプターなしで JAXB に必要なデフォルトの引数なしコンストラクターがないことです。したがって、 ClassBをJAXB で問題なく処理できる単純なクラスValBにマップするMyAdapterを実装しました。

主な問題は、JAXB にこのアダプターを使用させる方法ですか? クラスレベルで@XmlJavaTypeAdapterを定義すること も、アダプターをアンマーシャラーに登録することもありません。

アンマーシャラーがClassAのインスタンスであるオブジェクトを返すように、JAXB にMyAdapterを使用させる方法を知っている人はいますか?

public class JaxbTest {

    public static abstract class ClassA {
        public ClassA(String id) {
        }
    }

    @XmlRootElement
    @XmlJavaTypeAdapter(MyAdapter.class) // does not have an effect
    public static class ClassB extends ClassA {

        public String text;

        public ClassB() {
            super("");
        }
    }

    public static class ValB {
        public String text;
    }

    public static class MyAdapter extends XmlAdapter<ValB, ClassB> {

        @Override
        public ClassB unmarshal(ValB v) throws Exception {
            ClassB b = new ClassB();
            b.text = v.text;
            return b;
        }

        @Override
        public ValB marshal(ClassB v) throws Exception {
            ValB b = new ValB();
            b.text = v.text;
            return b;
        }

    }

    public static void main(String[] args) {
        try {
            JAXBContext context = JAXBContext.newInstance(ClassB.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setAdapter(new MyAdapter()); // does not have an effect
            ClassA a = (ClassA) unmarshaller.unmarshal(new File("test.xml"));
            // do somthing with a
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ところで: コードをあまり深刻に考えないでください。これは、問題を示す単なる例です。ClassAClassBの定義があまり役に立たないことはわかっています。

4

1 に答える 1

2

アップデート

この問題は、今後のEclipseLink JAXB (MOXy) 2.2.0 リリースで対処されています (バグ #332742を参照)。このリリースでは、抽象クラスは引数なしのコンストラクターに対してチェックされません。

この修正を含むプレリリース バージョンは、12 月 18 日以降、次の場所から入手できます。

回避策

これが @XmlTransient アノテーションの目的です。可能であれば、次のことを行います。

@XmlTransient
public static abstract class ClassA {
    public ClassA(String id) {
    }
}

ClassA に直接アノテーションを付けることができない場合は、EclipseLink JAXB (MOXy)拡張機能を利用してこれを行うことができます。MOXy では、JAXB メタデータを XML ファイルとして指定できます。これは、モデル クラスを変更できない場合に便利です。

以下は、@XmlAdapter を説明するいくつかの記事です。

于 2010-12-16T10:35:37.683 に答える