我还有另一个棘手的问题:
E.g. Person Class has: --String firstName --String lastName --Map stringMap
Person person = new Person ();
person.setFirstName("FirstName");
person.setLastName("LastName");
Map<String,String> stringMap = new HashMap<String,String>();
stringMap.put("IwantThisKeyInXml","IwantThisValueInXml");
stringMap.put("IDONTwantThisKeyInXml","IDONTwantThisValueInXml");
InputStream iStream1 = classLoader.getResourceAsStream("person-binding.xml");
List<Object> fileList = new ArrayList<Object>();
fileList.add(iStream1);
Map<String, Object> properties = new HashMap<String,Object>();
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, fileList);
JAXBContext ctx = JAXBContext.newInstance(new Class[] { GaDictionary.class, Person.class }, properties);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Writer output = new StringWriter();
marshaller.marshal(person, output);
System.out.println(output);
person-binding.xml在
之下 <?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="my.test.model" xml-mapping-metadata-complete="true">
<xml-schema
element-form-default="QUALIFIED"/>
<java-types>
<java-type name="Person" xml-accessor-type="NONE">
<xml-root-element/>
<xml-type prop-order="firstName lastName"/>
<java-attributes>
<xml-element java-attribute="firstName" name="first-name"/>
<xml-element java-attribute="lastName" name="last-name"/>
<xml-element java-attribute="stringMap" name="string-map"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
因此,结果的定义是:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<first-name>FirstName</first-name>
<last-name>LastName</last-name>
<string-map>
<entry>
<key>IwantThisKeyInXml</key>
<value>IwantThisKeyInXml</value>
</entry>
<entry>
<key>IDONTwantThisKeyInXml</key>
<value>IDONTwantThisKeyInXml</value>
</entry>
</string-map>
</person>
如何在stringMap上排除该条目?我试过虚拟访问方法,但也许我无法正确配置它?!编组后我应该删除该值吗?这可能是一种聪明且可维护的方式吗?
最后一个问题是我是否拥有属性的空值。如何配置person-binding-xml文件(oxm.file)以使相对xml标记为空?
我可以更改模型类,但我更喜欢在可能的情况下不添加任何代码行。 (这就是我填充xml文件的原因)
所以我想获得的结果是:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<first-name>FirstName</first-name>
<last-name>LastName</last-name>
<string-map>
<entry>
<key>IwantThisKeyInXml</key>
<value>IwantThisKeyInXml</value>
</entry>
</string-map>
</person>
关于第二个相关问题: 我试过nillable =“true”但它不起作用! 所以对于istance如果我对stringMap或firstName或其他东西有空值我会分别得到 并用任何身体标记。
或者我想获得的另一种方式是:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<first-name>FirstName</first-name>
<last-name>LastName</last-name>
<string-map>
<entry>
<key>IwantThisKeyInXml</key>
<value>IwantThisKeyInXml</value>
</entry>
<entry><!-- I have the entry but I have an empty value-->
<key>KEY</key>
<value></value>
</entry>
</string-map>
</person>
感谢所有
答案 0 :(得分:4)
在您的解决方案中,null-policy是正确的想法,但它需要在StringEntryType的value属性上,而不是在整个地图上。所以你的绑定文件应该包含这样的内容:
<java-type name="StringEntryType">
<java-attributes>
<xml-element java-attribute="value" name="value">
<xml-null-policy null-representation-for-xml="EMPTY_NODE"/>
</xml-element>
</java-attributes>
</java-type>
你的解决方案看起来不错,但我想我也会发布一个替代解决方案,它使用你可能更喜欢的MOXy的只读和只写属性。在此示例中,变量myMap将在unmarshal期间设置,但在编组期间,将调用从getModifiedMap方法返回的Map。在getModifiedMap中,我们还使用空字符串替换空值,以便对空标记进行编组。
public class Root {
public Map<String, String> myMap = new HashMap<String, String>();
public Map<String, String> getModifiedMap(){
Map modifiedMap = new HashMap<String, String>();
Set<Entry<String, String>> entries = myMap.entrySet();
Iterator<Entry<String, String>> iter = entries.iterator();
while(iter.hasNext()){
Entry<String, String> nextEntry = iter.next();
String nextKey = nextEntry.getKey();
if(!nextKey.equals("omitthiskey")){
String nextValue = nextEntry.getValue();
if(nextValue == null){
nextValue ="";
}
modifiedMap.put(nextKey, nextValue);
}
}
return modifiedMap;
}
public void setModifiedMap(Map<String, String> newMap){
//this method shouldn't get hit but needs to be present
}
}
并且相应的绑定文件将包含以下内容:
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="test2" >
<xml-schema element-form-default="QUALIFIED"/>
<java-types>
<java-type name="Root" xml-accessor-type="NONE">
<xml-root-element/>
<java-attributes>
<xml-element java-attribute="myMap" name="myMap" read-only="true" />
<xml-element java-attribute="modifiedMap" name="myMap" write-only="true"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
答案 1 :(得分:1)
如果您想阻止某些Map条目被编组为XML,您可以提供一个XmlAdapter,它将在编组时删除任何不需要的条目:
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public final class MyAdapter extends XmlAdapter<Map<String, String>, Map<String, String>> {
private final String OMIT = "IDONTwantThisKeyInXml";
@Override
public Map<String, String> unmarshal(Map<String, String> arg0) throws Exception {
return arg0;
}
@Override
public Map<String, String> marshal(Map<String, String> arg0) throws Exception {
if (arg0 != null) {
arg0.remove(OMIT);
}
return arg0;
}
}
我不确定我理解你的第二个问题,你能解释一下你想看到的行为吗?
希望这有帮助,
瑞克
答案 2 :(得分:0)
我找到了正确的解决方案:
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public final class StringMapAdapter extends XmlAdapter<StringAdapterMap, Map<String, String>> {
private final String OMIT = "birthPlaceString";
@Override
public Map<String, String> unmarshal(StringAdapterMap v) throws Exception {
HashMap<String, String> hashMap = new HashMap<String, String>();
System.out.println("unmarshal");
for(StringEntryType myEntryType : v.entry) {
hashMap.put(myEntryType.key, myEntryType.value);
}
return hashMap;
}
@Override
public StringAdapterMap marshal(Map<String, String> v) throws Exception {
StringAdapterMap myMapType = new StringAdapterMap();
for(Entry<String, String> entry : v.entrySet()) {
StringEntryType EntryType = new StringEntryType();
EntryType.key= entry.getKey();
EntryType.value = entry.getValue();
if (!OMIT.equals(EntryType.key))
myMapType.entry.add(EntryType);
}
return myMapType;
}
StringAdapterMap类:
import java.util.ArrayList;
import java.util.List;
public class StringAdapterMap {
public List<StringEntryType> entry = new ArrayList<StringEntryType>();
}
StringEntryType类:
public class StringEntryType {
public String key;
public String value;
}
在oxm.file中记得配置适配器
<xml-element java-attribute="stringMap" name="string-map" >
<xml-java-type-adapter value="it.cineca.jaxb.adapter.StringMapAdapter" />
</xml-element>