XStream JavaBeanConverter 不序列化属性

发布于 2024-08-25 12:54:43 字数 2176 浏览 7 评论 0原文

尝试使用 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 设置期间没有正确配置某些内容。

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

谢谢!


Edit 1

另外,如果有帮助的话,我正在为此使用以下 Maven 依赖...

<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>


Edit 2

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

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

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

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

希望这能解释得更好一点。

谢谢。

Attempting to use XStream's JavaBeanConverter and running into an issue. Most likely I'm missng something simple, or not understanding XStream's converter handling well enough.

@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>         
    */
}

I tried adding a trace on the TestObject.getFoo() method and it appears it is being called by XStream, but the data isn't being written to the output stream.

After looking at the source for JavaBeanConverter, it looks like my implementation should work, which leads me to believe I haven't configured something correctly during the XStream setup.

Am I just missing something simple?

Thanks!


Edit 1

Also, if it helps, I'm using the following Maven deps for this...

<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>


Edit 2

I altered the TestObject.getFoo() method to better explain my objective.

I'm trying to use the getters/setters to do "sanitation" of the internal object's data.
Specifically, I'm trying to clean up incoming deserialized data, while trying to avoid having to implement Serializable's readResolve() method.

If I implemented readResolve's method I would have to do the cleanup in both the setter method (for any non-deserialized incoming data set elsewhere) and also in the readResolve (for XML data I deserialized).

That's the reason why I'm using JavaBeanConverter instead of XStream's normal field based practices... to force data through the getters/setters.

Hopefully this explains a little better.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情话难免假 2024-09-01 12:54:43

单步浏览 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 值。

Stepping through XStream's source you can find this in 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);
}

You will notice for the String it returns JavaBeanConverter and the reason it does that is that JavaBeanConverter will be used for any object with a default public constructor (which String has).

One way to fix the problem is to give the JavaBeanConverter a lower priority.

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

Then JavaBeanConverter is used for your Bean and SingleValueConverterWrapper is used for the String value.

卸妝后依然美 2024-09-01 12:54:43

如果您注释掉该行,

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

它就可以正常工作:)我认为您正在同时进行注释处理和注册转换器,而其中一个就足够了

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

If you comment out the line

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

it works fine :) I think you are doing both annotation processing and registering converters when just one of them would be enough

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文