1

JAXB を使用して XML でクラスをシリアライズしようとしています。

@XmlRootElement
class Foo
{
   Hashtable<String, Hashtable<String, Integer>> table = new Hashtable<>();

   public Hashtable<String, Hashtable<String, Integer>> getTable() {
     return table;
   }

   public void setTable(Hashtable<String, Hashtable<String, Integer>> t) {
     table = t;
  }
}

ただし、これは空の値を持つ XML を生成します (値が実際に存在することを保証します!)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Foo>
    <table>
        <entry>
            <key>Test key</key>
            <value/>
        </entry>
    </table>
</Foo>

これを修正する簡単な方法はありますか?@XmlJavaTypeAdapters本当に必要でない限り、私は本当に使用する必要はありません。

通常のハッシュテーブルを使用すると問題なく動作します。Hashtable<String, Integer>> table = new Hashtable<>();

4

1 に答える 1

1

がっかりさせて申し訳ありませんが、現在のところ、簡単に修正する方法はありません。外側と内側のハッシュテーブルには大きな違いがあります。外側の 1 つはプロパティであり、com.sun.xml.bind.v2.runtime.property.SingleMapNodeProperty<BeanT, ValueT>クラスによって内部的に処理されます。このクラスは、マップをキー/値エントリとして表現する魔法を行います。

ただし、内部の Hashtable の場合は「静的」プロパティではなく、動的なものです。そのため、ジェネリックで処理されcom.sun.xml.bind.v2.model.impl.RuntimeClassInfoImplます。このクラスは、Hashtable で JAXB プロパティを検出しません (つまり、getter と setter の両方を持つ Java Bean プロパティ)。その結果、空のvalue要素が得られます。

同じ理由で、次の動的 Hashtable プロパティも機能しません。

@XmlRootElement
@XmlSeeAlso(Hashtable.class)
public static class TypeWithHashtableAsObject {
    private Object property;

    public Object getProperty() {
        return property;
    }

    public void setProperty(Object property) {
        this.property = property;
    }

}

...
TypeWithHashtableAsObject foo = new TypeWithHashtableAsObject();
Hashtable<String, Integer> property = new Hashtable<>();
property.put("innerKey", 12);
foo.setProperty(property);
StringWriter writer = new StringWriter();
marshaller.marshal(foo, writer);
System.out.println(writer.toString());

結果:

<typeWithHashtableAsObject>
    <property xsi:type="hashtable" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</typeWithHashtableAsObject>

それは空の要素です。

別の回答では、ネストされたコレクションをマーシャリングする方法の例をさらに見つけることができます。別の解決策は、Hashtable を別の型でラップすることです。表のように:

public class Table {
    private Hashtable<String, Integer> table = new Hashtable<>();

    public Table(Hashtable<String, Integer> table) {
        this.table = table;
    }

    public Table() {

    }

    public Hashtable<String, Integer> getTable() {
        return table;
    }

    public void setTable(Hashtable<String, Integer> table) {
        this.table = table;
    }

}

Foo.tableタイプを に変更しHashtable<String, Table>ます。

結果は元のものよりも冗長ですが、IMHO は非常に一貫しています。

<foo>
   <table>
      <entry>
         <key>key1</key>
         <value>
            <table>
               <entry>
                  <key>innerKey</key>
                  <value>12</value>
               </entry>
            </table>
         </value>
      </entry>
   </table>
</foo>
于 2013-10-18T19:26:43.880 に答える