3

私はこれらのクラスを持っています:

@XStreamAlias("person")
public class PersonConfig {

    private AnimalConfig animalConfig;

}

public interface AnimalConfig {}

@XStreamAlias("dog");
public class DogConfig extend AnimalConfig {}

@XStreamAlias("cat");
public class CatConfig extend AnimalConfig {}

そして、上記のクラスでこの xml を逆シリアル化できるようにしたいと思います。

<person>
    <dog/>
<person>

同じクラスを使用して、この xml も逆シリアル化します。

<person>
    <cat/>
<person>

そのため、どちらの場合も、PersonConfigのフィールドanimalConfigが埋められます。最初の XML にはDogConfigインスタンスがあり、2 番目の XML にはCatConfigインスタンスがあります。

これを機能させるために注釈を追加することでこれは可能ですか?

4

4 に答える 4

3

XStream では簡単に実行できないようです。

あなたの質問はこれに似ており、XStream で xsd:choice のようなものを管理することを求めています。

必ずしも XStream を使用する必要がない場合は、JAXB を使用すると簡単に実行できます。

@XmlRootElement(name="person")
public class PersonConfig {

    private AnimalConfig animalConfig;

    @XmlElementRefs({
        @XmlElementRef(name="cat", type=CatConfig.class),
        @XmlElementRef(name="dog", type=DogConfig.class)
    })
    public AnimalConfig getAnimalConfig() {
        return animalConfig;
    }

    public void setAnimalConfig(AnimalConfig animalConfig) {
        this.animalConfig = animalConfig;
    }
}

いくつかの調査の後、XmlAdapter. Blaise Doughan リンクの例では、インターフェイスではなく抽象クラスを使用しています。

編集 :

Blaise Doughan がコメントで述べたように、@XmlElementRefこの目的により適しています。それに応じてコードが更新されました。

于 2012-07-17T14:05:45.510 に答える
1

コンバーターを書くことができます。

public class CustomConverter implements Converter {

   public void marshal(Object source, HierarchicalStreamWriter writer,
        MarshallingContext context) {
     // TODO: Get annotation value from object 'source' with name of tag via Reflection.
     // Or add a method to the AnimalConfig interface giving you tag name to put to serialization output.
   }

   public Object unmarshal(HierarchicalStreamReader reader,
        UnmarshallingContext context) {
     // TODO: use reflection to create animal object based on what you xml tag you have at hahd.
     return context.convertAnother(context.currentObject(), SomeAnimalClazz.class);
   }

   public boolean canConvert(Class type) {
     return type.equals(AnimalConfig.class);
   }
 }

欠点があります。ポリモーフィズムでは、Java Reflection API を使用する必要があり、パフォーマンスが低下します。

于 2012-07-17T14:11:18.883 に答える
0

注釈なしで、そのまま使用できます...

private static interface Test {
    String getName();

    Params getParams();
}

private static interface Params {
}

private static class OneParams implements Params {
    private String oneValue;

    public String getOneValue() {
        return oneValue;
    }

    public void setOneValue(String oneValue) {
        this.oneValue = oneValue;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("OneParams [oneValue=");
        builder.append(oneValue);
        builder.append("]");
        return builder.toString();
    }

}

private static class TwoParams implements Params {
    private String twoValue;

    public String getTwoValue() {
        return twoValue;
    }

    public void setTwoValue(String twoValue) {
        this.twoValue = twoValue;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("TwoParams [twoValue=");
        builder.append(twoValue);
        builder.append("]");
        return builder.toString();
    }

}

private static class OneTest implements Test {
    private String name;

    private Params params;

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public Params getParams() {
        return params;
    }

    public void setParams(Params params) {
        this.params = params;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("OneTest [name=");
        builder.append(name);
        builder.append(", params=");
        builder.append(params);
        builder.append("]");
        return builder.toString();
    }

}

---- 今、このように逆シリアル化します...

    System.out
            .println(ser
                    .deserialize("<XStreamTest_-OneTest><name>OneTest</name><params class=\"XStreamTest$OneParams\"><oneValue>1</oneValue></params></XStreamTest_-OneTest>"));

    System.out
            .println(ser
                    .deserialize("<XStreamTest_-OneTest><name>TwoTest</name><params class=\"XStreamTest$TwoParams\"><twoValue>2</twoValue></params></XStreamTest_-OneTest>"));
于 2013-02-14T19:19:30.733 に答える