XStream序列化和反序列化中的多态性

我有这些课程:

@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:

    

除了反序列化这个xml,使用相同的类:

    

因此,在这两种情况下, PersonConfig的字段animalConfig填充。 在带有DogConfig实例的第一个XML和带有DogConfig实例的第二个XML中。

这是否可以通过添加一些注释来使其工作?

似乎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更适合这个目的。 代码已相应更新。

你可以写一个转换器。

 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和性能下降。

这很容易。 你必须做得对,而不是像以前的发言者那样。 处理注释时,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 {} 

它开箱即用,没有任何注释……

 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("OneTest1")); System.out .println(ser .deserialize("TwoTest2"));