2010-03-16 75 views
4

嘗試使用XStream的JavaBeanConverter並遇到問題。很可能我錯過了一些簡單的事情,或者不瞭解XStream的轉換器處理得不夠好。XStream JavaBeanConverter未序列化屬性

@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()方法以更好地解釋我的目標。

我想使用getters/setters來做內部對象數據的「衛生」。 特別是,我試圖清理傳入的反序列化數據,同時試圖避免必須實現Serializable的readResolve()方法。

如果我實現了readResolve的方法,我將不得不在setter方法(對於任何其他非反序列化的傳入數據集)以及readResolve(對於反序列化的XML數據)中執行清理。

這就是爲什麼我使用JavaBeanConverter而不是基於XStream的常規實踐的原因...通過getters/setters強制數據。

希望這解釋得更好一點。

謝謝。

+0

+1對於一個優秀的代碼示例(連同maven pom片段) – 2010-03-16 17:53:39

回答

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

你將要爲字符串注意到它返回JavaBeanConverter和原因,它即是JavaBeanConverter將用於一個默認的公共構造方法(字符串有)的任何對象。

解決此問題的一種方法是爲JavaBeanConverter提供較低的優先級。

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

然後JavaBeanConverter用於您的Bean和SingleValueConverterWrapper用於字符串值。

+0

嗨蘭迪,謝謝你的信息。我更新了原始問題,以幫助更好地反映我的最終目標。如果我讀了這個權利,我試圖做相反的事情,並迫使XStream使用getters/setters(例如通過JavaBeanConverter)。所有這些都有意義嗎? (我不是很擅長解釋) – 2010-03-16 18:24:30

+0

我認爲以上就是這樣做的。如果你改變你的代碼,我建議你會看到你的getter被調用。問題是第一個XStream嘗試編組TestObject,它決定使用JavaBeanConverter類來完成它,然後它調用getter並獲取一個字符串(「bar」),現在還必須編組該字符串。由於String有一個默認的公共構造函數,XStream認爲它可以再次使用JavaBeanConverter,但它不應該這樣做。相反,它應該使用SingleValueConverterWrapper來編組字符串。附加XStream源並逐步查看。 – 2010-03-16 18:47:12

+0

是的,你的權利。這是完美的。此外,它也適用於解組(例如,來自帶有setter的XML)。 – 2010-03-16 19:00:22

2

如果您註釋掉線

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

它工作得很好:)我認爲你正在做的兩個註釋處理和註冊轉換器時,只是其中的一個就足夠了

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

+0

嗨,我更新了原始問題以更好地解釋我正在嘗試實現的內容。對不起,我沒有事先解釋我的最終目標。 – 2010-03-16 18:21:34