I have read a lot of answers in these forums, as well as other blog posts, but I can\'t quite seem to connect the pieces together.
So, we start with a basic POJO con
Depends on the solution listed above, I've came into this MapAdapter that addresses both marshaling and unmarshalling process.
@XmlType
public class MapWrapper{
private List> properties = new ArrayList<>();
public MapWrapper(){
}
@XmlAnyElement
public List> getProperties() {
return properties;
}
public void setProperties(List> properties) {
this.properties = properties;
}
@Override
public String toString() {
return "MapWrapper [properties=" + toMap() + "]";
}
public Map toMap(){
//Note: Due to type erasure, you cannot use properties.stream() directly when unmashalling is used.
List> props = properties;
return props.stream().collect(Collectors.toMap(MapWrapper::extractLocalName, MapWrapper::extractTextContent));
}
@SuppressWarnings("unchecked")
private static String extractLocalName(Object obj){
Map, Function super Object, String>> strFuncs = new HashMap<>();
strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement)jaxb).getName().getLocalPart());
strFuncs.put(Element.class, ele -> ((Element) ele).getLocalName());
return extractPart(obj, strFuncs).orElse("");
}
@SuppressWarnings("unchecked")
private static String extractTextContent(Object obj){
Map, Function super Object, String>> strFuncs = new HashMap<>();
strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement)jaxb).getValue());
strFuncs.put(Element.class, ele -> ((Element) ele).getTextContent());
return extractPart(obj, strFuncs).orElse("");
}
private static Optional extractPart(ObjType obj, Map, Function super ObjType, T>> strFuncs){
for(Class> clazz : strFuncs.keySet()){
if(clazz.isInstance(obj)){
return Optional.of(strFuncs.get(clazz).apply(obj));
}
}
return Optional.empty();
}
}
public class MapAdapter extends XmlAdapter>{
@Override
public Map unmarshal(MapWrapper v) throws Exception {
return v.toMap();
}
@Override
public MapWrapper marshal(Map m) throws Exception {
MapWrapper wrapper = new MapWrapper();
for(Map.Entry entry : m.entrySet()){
wrapper.addEntry(new JAXBElement(new QName(entry.getKey()), String.class, entry.getValue()));
}
return wrapper;
}
}
I've post the full the full post here (in another post), where comments as well as examples are also provided..