2013-10-22 30 views
3

我有一個帶有「id」sring字段和一個java.util.Properties字段及其getter和setter的Java類。我將如何使用JAXB將此類的實例轉換爲XML?如何在Java類具有java.util.Properties時進行JAXB轉換?

非常感謝!

+0

您是否需要遵循特定的XML方案,或者*任何方案是否可接受?由於['Properties'](http://docs.oracle.com/javase/7/docs/api/java/util/Properties。html)實現了'Map',JAXB知道如何序列化地圖,一個簡單的getter將'Properties'對象作爲'Map'實例返回就足夠了。無論是getter還是默認構造函數都將負責創建一個空的'Properties'對象。 – MvG

+0

感謝您的回覆!但是,如果我嘗試將屬性映射到Map,它似乎不會編譯。 – user1982497

回答

0

JAXB可以處理collections,但map本身不是一個集合。並且entry set將作爲集合的最合理的地圖表示,存在兩個問題:其元素類型是接口Map.Entry,並且它不支持通過add方法進行修改。前一個問題可以通過適配器來避開,但後者依靠JAXB處理集合是相當有問題的。可以是done using a custom collection class。如果您不想編寫自己的收藏集,那麼我建議您使用XmlAdapter來創建整個Properties對象的替代表示形式。如果你願意,你可以這樣設計它,以便模擬Properties.storeToXMLProperties.loadFromXML使用的XML方案。事情是這樣的:

@XmlType(name="property") class XmlProperty { 
    @XmlAttribute public String key; 
    @XmlValue public String value; 
} 

@XmlType(name="properties") class XmlProperties { 
    @XmlElement(name="entry") public Collection<XmlProperty> entries 
     = new ArrayList<XmlProperty>(); 
} 

// for use with a @XmlJavaTypeAdapter(PropertiesAdapter.class) annotation 
class PropertiesAdapter extends XmlAdapter<XmlProperties, Properties> { 
    public XmlProperties marshal(Properties props) { 
     XmlProperties xml = new XmlProperties(); 
     for (Map.Entry<Object, Object> entry: props.entrySet()) { 
      XmlProperty xmlEntry = new XmlProperty(); 
      xmlEntry.key = entry.getKey().toString(); 
      xmlEntry.value = entry.getValue().toString(); 
      xml.entries.add(xmlEntry); 
     } 
     return xml; 
    } 
    public Properties unmarshal(XmlProperties xml) { 
     Properties props = new Properties(); 
     for (XmlProperty entry: xml.entries) 
      props.setProperty(entry.key, entry.value); 
     return props; 
    } 
} 

我也寫a small executable demo snippet使用這個序列化像你描述的一個一類,與除了屬性成員的ID。訪問器被寫成這樣:

@XmlElement 
@XmlJavaTypeAdapter(PropertiesAdapter.class) 
public Properties getProperties() { return props; } 
public void setProperties(Properties props) { this.props.putAll(props); } 

注意,整個Properties字段被序列化爲單個<properties>元件,它依次包含<entry>元素的任意數量。如果您希望將條目作爲類元素的直接子元素,那麼您將不得不依賴於序列化,並實現自己的集合來封裝屬性。

0

由於JAXB顯然可以處理collections,但不是maps,您可以提供properties場的自己的集合視圖,基於AbstractCollection

@XmlType(name="property") class XmlProperty { 
    @XmlAttribute public String key; 
    @XmlValue public String value; 
} 

class XmlProperties extends AbstractCollection<XmlProperty> { 
    private final Properties props; 
    public XmlProperties(Properties props) { this.props = props; } 
    public int size() { return props.size(); } 
    public Iterator<XmlProperty> iterator() { 
     return new XmlPropertyIterator(props.entrySet().iterator()); 
    } 
    public boolean add(XmlProperty xml) { 
     return !xml.value.equals(props.setProperty(xml.key, xml.value)); 
    } 
} 

class XmlPropertyIterator implements Iterator<XmlProperty> { 
    private final Iterator<Map.Entry<Object, Object>> base; 
    public XmlPropertyIterator(Iterator<Map.Entry<Object, Object>> base) { 
     this.base = base; 
    } 
    public boolean hasNext() { return base.hasNext(); } 
    public void remove() { base.remove(); } 
    public XmlProperty next() { 
     Map.Entry<?, ?> entry = base.next(); 
     XmlProperty xml = new XmlProperty(); 
     xml.key = entry.getKey().toString(); 
     xml.value = entry.getValue().toString(); 
     return xml; 
    } 
} 

你可以有型的一個getter Collection<XmlProperty>返回XmlProperties對象,它封裝您Properties場。我已經再次提供an executable demo of this code。它有一個像你所描述的類,有一個標識符和一個屬性字段。屬性字段是使用

@XmlElement(name="property") 
public Collection<XmlProperty> getProperties() { 
    return new XmlProperties(props); 
} 

注意,Properties收集的各個條目將代表您的包含類元素的直接子建模。如果這不應該,你可以使用一個註釋來爲它們提供一個包裝元素。

比較這個答案到my first,它看起來更有效率,因爲它只能一次轉換一個映射條目,而且它對於是否需要包含整個XML元素也更靈活一組屬性。