我有这些课程:
@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
都已填充。在带有DogConfig
实例的第一个XML和带有CatConfig
实例的第二个XML中。
这可以通过添加一些注释来实现吗?
答案 0 :(得分:3)
似乎XStream不允许您轻松完成。
您的问题类似于this one,要求使用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
更适合这个目的。代码已相应更新。
答案 1 :(得分: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并降低性能。
答案 2 :(得分: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 {}
答案 3 :(得分: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>"));