在XStream中为不在XML中的字段设置默认值

有没有办法创建转换器或在每次转换后执行的某些操作? 对于上下文,我试图填充不在我的XML中的字段的默认值,以便在我的数据模型更改时保持向后兼容性。 例如,如果我有这个对象:

class A { private String b; private String c; private String d; } 

我的XML是这样的:

  b d  

我希望我导入XML以便知道字段c的默认值为"c"并将其设置为A 这应该是一个通用操作,我可以将默认值添加到非常复杂的图形的任何字段。 如果在每次转换后都有某种方法触发函数,它可以根据我想设置默认值的对象图检查当前对象。

还要注意,使用readResolve / readObject似乎不是一个选项,因为1. readObject()似乎根本不适合我.2。readResolve将使用默认值覆盖该字段,即使它实际包含在XML中。 如果我的假设在这里是错误的,请告诉我。

编辑::我在用户邮件列表中找到了这个相关的主题: http : //article.gmane.org/gmane.comp.java.xstream.user/4619/match=default+value

似乎唯一建议的解决方案是使用readResolve() ,我已经说过它不是一个有效的解决方案。

使用PureJavaReflectionProvider

 XStream xstream = new XStream(new PureJavaReflectionProvider()); 

并像往常一样使用默认值初始化您的对象。 通过字段初始化或构造函数代码。

背景

如果您未指定ReflectionProvider xstream尝试查找最佳reflection提供程序。 但xstream的最佳ReflectionProvider可能不是最适合您的,因为它通常会选择Sun14ReflectionProvider

Sun14ReflectionProvider使用与java序列化机制相同的实例化策略,这意味着它跳过构造函数代码或更详细 – 对象初始化程序代码。

因此实例字段初始化如

 class A { private String b = "DEFAULT"; } 

将不会应用,也不会应用构造函数代码,例如

 class A { private String b; public A(){ b = "DEFAULT"; } } 

PureJavaReflectionProvider使用(顾名思义)javareflectionAPI来实例化对象,例如Class.newInstance() ,因此执行对象初始化代码。

你需要一个转换器。

以下是您的案例的代码示例:

 public class AConverter implements Converter { @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { A a = new A(); String bValue = "b"; String cValue = "c"; String dValue = "d"; while (reader.hasMoreChildren()) { reader.moveDown(); if ("b".equals(reader.getNodeName())) { bValue = reader.getValue(); } else if ("c".equals(reader.getNodeName())) { cValue = reader.getValue(); } else if ("d".equals(reader.getNodeName())) { dValue = reader.getValue(); } reader.moveUp(); } a.setB(bValue); a.setC(cValue); a.setD(dValue); return a; } @Override public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) { A a = (A) object; writer.startNode("b"); writer.setValue(a.getB()); writer.endNode(); writer.startNode("c"); writer.setValue(a.getC()); writer.endNode(); writer.startNode("d"); writer.setValue(a.getD()); writer.endNode(); } @Override public boolean canConvert(Class clazz) { return clazz == A.class; } 

}

不要忘记注册转换器:

 XStream xs = new XStream(); xs.registerConverter(new AConverter()); 

编辑:修复了转换器代码。

当XML没有为c设置任何值时, c将被设置为null 。 然后,您可以在getter中检查null并返回相应的默认值。