我有一個帶有「id」sring字段和一個java.util.Properties字段及其getter和setter的Java類。我將如何使用JAXB將此類的實例轉換爲XML?如何在Java類具有java.util.Properties時進行JAXB轉換?
非常感謝!
我有一個帶有「id」sring字段和一個java.util.Properties字段及其getter和setter的Java類。我將如何使用JAXB將此類的實例轉換爲XML?如何在Java類具有java.util.Properties時進行JAXB轉換?
非常感謝!
JAXB可以處理collections,但map本身不是一個集合。並且entry set將作爲集合的最合理的地圖表示,存在兩個問題:其元素類型是接口Map.Entry
,並且它不支持通過add
方法進行修改。前一個問題可以通過適配器來避開,但後者依靠JAXB處理集合是相當有問題的。可以是done using a custom collection class。如果您不想編寫自己的收藏集,那麼我建議您使用XmlAdapter
來創建整個Properties
對象的替代表示形式。如果你願意,你可以這樣設計它,以便模擬Properties.storeToXML
和Properties.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>
元素的任意數量。如果您希望將條目作爲類元素的直接子元素,那麼您將不得不依賴於序列化,並實現自己的集合來封裝屬性。
由於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元素也更靈活一組屬性。
您是否需要遵循特定的XML方案,或者*任何方案是否可接受?由於['Properties'](http://docs.oracle.com/javase/7/docs/api/java/util/Properties。html)實現了'Map',JAXB知道如何序列化地圖,一個簡單的getter將'Properties'對象作爲'Map'實例返回就足夠了。無論是getter還是默認構造函數都將負責創建一個空的'Properties'對象。 – MvG
感謝您的回覆!但是,如果我嘗試將屬性映射到Map,它似乎不會編譯。 – user1982497