Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为XStream中非XML格式的字段设置默认值_Java_Import_Xstream - Fatal编程技术网

Java 为XStream中非XML格式的字段设置默认值

Java 为XStream中非XML格式的字段设置默认值,java,import,xstream,Java,Import,Xstream,是否有方法创建转换器或在每次转换后执行的某些操作?对于上下文,我尝试填充不在XML中的字段的默认值,以便在数据模型更改时保持向后兼容性。例如,如果我有这个对象: class A { private String b; private String c; private String d; } 我的XML是这样的: <a> <b>b</b> <d>d</d> </a> 似乎唯一建议的解决方案是

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

class A {
    private String b;
    private String c;
    private String d;
}
我的XML是这样的:

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


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

您需要一个转换器

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

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

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

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

使用

然后像往常一样用默认值初始化对象。通过字段初始化或构造函数代码(初始值设定项)

背景

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

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

因此,实例字段初始化如下

class A {
    private String b = "DEFAULT";
}
不会应用,也不会应用构造函数代码,例如

class A {
    private String b;

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

相反,
PureJavaReflectionProvider
使用(顾名思义)java反射API来实例化对象,例如,因此执行对象初始化代码。

感谢pablosaraiva,但这只对某些类A显式有效。我需要它在完整对象图中的任何对象上通用。因此它必须适用于B/C/D对象,以及B/C/D可能具有的任何对象。此外,如果在这种情况下添加了其他字段,则需要维护此转换器。理想情况下,每当我需要添加一个新的默认值时,我可以说一些类似于newDefaultField(classWithNewDefault.class,newFieldName,newDefaultValue)的话。这只是玩具问题的玩具解决方案。您可能需要一个到每个具有默认值的类的转换器。您不需要在解组时手动构造对象,您可以有一个工厂来处理它。我希望有帮助,对。我想目标是避免任何可能很快变得复杂和失控的实际维护。不幸的是,我不认为XStream提供了一个更好的解决方案,除了每个转换器或每个地方都有一个readResolve()。这是一个合适的选项,可以为使用
fromXML(…)
时XML中缺少标记的成员设置默认值;特别是当默认行为只影响某个特定类的某些标记/成员时。这种方法不起作用。甚至PureJavaReflectionProvider也将默认值设置为Null这似乎不适用于具有默认值构造函数的类的Scala,即类a(字符串b=“”)您说过“readResolve将使用默认值覆盖字段,即使它实际上包含在XML中”。您可以编写
readResolve()
方法来处理这种情况
if(c==null){c=“c”}
我经常使用这样的代码,而且效果很好。
class A {
    private String b;

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