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实例的第二个 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 反射 API 和性能下降。

于 2012-07-17T14:11:18.883 回答
1

这很容易。你只需要做对,而不是像我以前的演讲者那样。当您处理注释时,XStream 可以分配这些类。

@XStreamAlias("person")
public class PersonConfig {

    private AnimalConfig animalConfig;

    public String toXml() {
        XStream xstream = new XStream();
        xstream.processAnnotations(DogConfig.class);
        xstream.processAnnotations(CatConfig.class);
        return xstream.toXML(this);
    }
}

public interface AnimalConfig {}

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

@XStreamAlias("cat");
public class CatConfig implements AnimalConfig {}
于 2013-10-09T06:50:59.427 回答
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 回答