4

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()、目的をより適切に説明しました。

ゲッター/セッターを使用して、内部オブジェクトのデータの「サニテーション」を行おうとしています。具体的には、Serializable の readResolve() メソッドを実装する必要がないようにしながら、デシリアライズされた着信データをクリーンアップしようとしています。

readResolve のメソッドを実装した場合、setter メソッド (別の場所にあるデシリアライズされていない着信データ セット) と readResolve (デシリアライズした XML データ) の両方でクリーンアップを行う必要があります。

これが、私が XStream の通常のフィールド ベースのプラクティスの代わりに JavaBeanConverter を使用している理由です... getter/setter を介してデータを強制します。

うまくいけば、これでもう少しうまく説明できます。

ありがとう。

4

2 に答える 2

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 がデフォルトの public コンストラクタ (String が持つ) を持つすべてのオブジェクトに使用されるためです。

この問題を解決する 1 つの方法は、JavaBeanConverter の優先度を下げることです。

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

次に、JavaBeanConverter が Bean に使用され、SingleValueConverterWrapper が String 値に使用されます。

于 2010-03-16T17:59:13.973 に答える
2

行をコメントアウトすると

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

それは正常に動作します:)注釈処理とコンバーターの登録の両方を行っていると思いますが、そのうちの1つだけで十分です

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

于 2010-03-16T17:53:08.103 に答える