在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
并返回相应的默认值。