XStream JavaBeanConverter不序列化属性

时间:2010-03-16 17:04:37

标签: java javabeans xstream

尝试使用XStream的JavaBeanConverter并遇到问题。很可能我会想到一些简单的东西,或者不太了解XStream的转换器处理能力。

@XStreamAlias("test")
public class TestObject
{
    private String foo;

    public String getFoo()
    {
        //return foo; -- Adjusted for EDIT#2
        return foo.toLowerCase();
    }

    public void setFoo(String foo)
    {
        this.foo = foo;
    }
}

public void test() throws Exception
{
    XStream x = new XStream(new XppDriver());
    x.autodetectAnnotations(true);
    x.processAnnotations(TestObject.class);

    x.registerConverter(new JavaBeanConverter(x.getMapper()));

    TestObject o = new TestObject();
    //o.setFoo("bar"); -- Adjusted for EDIT#2
    o.setFoo("BAR");

    String xml = x.toXML(o);

    System.out.println(xml);

    /*
      Expecting...
        <test>
          <foo>bar</foo>
        </test>

      But instead getting...
        <test>
          <foo/>
        </test>         
    */
}

我尝试在TestObject.getFoo()方法上添加一个跟踪,看起来它正被XStream调用,但数据没有被写入输出流。

在查看JavaBeanConverter的源代码之后,看起来我的实现应该可以工作,这让我相信我在XStream设置期间没有正确配置。

我只是错过了一些简单的事情吗?

谢谢!

<小时/> 修改1

此外,如果它有帮助,我正在使用以下Maven deps ...

<dependency>
    <groupId>org.apache.servicemix.bundles</groupId>
    <artifactId>org.apache.servicemix.bundles.xstream</artifactId>
    <version>1.3_3</version>
</dependency>
<dependency>
    <groupId>org.apache.servicemix.bundles</groupId>
    <artifactId>org.apache.servicemix.bundles.xpp3</artifactId>
    <version>1.1.4c_3</version>
</dependency>

<小时/> 修改2

我修改了TestObject.getFoo()方法以更好地解释我的目标。

我正在尝试使用getter / setter对内部对象的数据进行“卫生”。 具体来说,我正在尝试清理传入的反序列化数据,同时试图避免必须实现Serializable的readResolve()方法。

如果我实现了readResolve的方法,我将不得不在setter方法(对于其他地方的任何非反序列化的传入数据集)和readResolve(对于我反序列化的XML数据)中进行清理。

这就是为什么我使用JavaBeanConverter而不是XStream正常的基于字段的实践...来强制数据通过getter / setter。

希望这可以解释得更好。

感谢。

2 个答案:

答案 0 :(得分:4)

单步浏览XStream的源代码,您可以在com.thoughtworks.xstream.core.DefaultConverterLookup中找到它。

public Converter lookupConverterForType(Class type) {
    Converter cachedConverter = (Converter) typeToConverterMap.get(type);
    if (cachedConverter != null) return cachedConverter;
    Iterator iterator = converters.iterator();
    while (iterator.hasNext()) {
        Converter converter = (Converter) iterator.next();
        if (converter.canConvert(type)) {
            typeToConverterMap.put(type, converter);
            return converter;
        }
    }
    throw new ConversionException("No converter specified for " + type);
}

你会注意到String返回JavaBeanConverter,它的原因是JavaBeanConverter将被用于任何具有默认公共构造函数的对象(String具有)。

解决问题的一种方法是给JavaBeanConverter一个较低的优先级。

x.registerConverter(new JavaBeanConverter(x.getMapper()), -10);

然后JavaBeanConverter用于您的Bean,SingleValueConverterWrapper用于String值。

答案 1 :(得分:2)

如果您注释掉

x.registerConverter(new JavaBeanConverter(x.getMapper()));

它工作得很好:)我认为你正在进行注释处理和注册转换器,只需其中一个就够了

http://x-stream.github.io/annotations-tutorial.html