9

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

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

我的 XML 类似于:

<a>
 <b>b</b>
 <d>d</d>
</a>

我希望我的 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()我已经说过的不是有效的解决方案。

4

3 回答 3

12

使用PureJavaReflectionProvider

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

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

背景

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

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

因此实例字段初始化像

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

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

class A {
    private String b;

    public A(){
        b = "DEFAULT";
    }
}

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

于 2015-04-20T12:19:54.720 回答
1

你需要一个转换器。

这是您的案例的代码示例:

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());

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

于 2013-04-18T14:11:17.810 回答
1

cnull当 XML 没有为 . 设置任何值时,将设置为c. 然后,您可以检查null您的 getter 并返回适当的默认值。

于 2014-06-18T14:33:27.210 回答