java jaxb marshalling moxy xmladapter

java - JAXB @XmlAdapter: Mapa-> ¿Adaptador de lista?(Marshall solo)



marshalling moxy (1)

En lugar de adaptar el Map a una List , debe adaptarlo a un objeto que tenga una propiedad de List .

XmlAdapter (MapPropertiesAdapter)

import java.util.*; import java.util.Map.Entry; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlAdapter; public class MapPropertiesAdapter extends XmlAdapter<MapPropertiesAdapter.AdaptedProperties, Map<String, String>>{ public static class AdaptedProperties { public List<Property> property = new ArrayList<Property>(); } public static class Property { @XmlAttribute public String name; @XmlValue public String value; } @Override public Map<String, String> unmarshal(AdaptedProperties adaptedProperties) throws Exception { if(null == adaptedProperties) { return null; } Map<String, String> map = new HashMap<String, String>(adaptedProperties.property.size()); for(Property property : adaptedProperties.property) { map.put(property.name, property.value); } return map; } @Override public AdaptedProperties marshal(Map<String, String> map) throws Exception { if(null == map) { return null; } AdaptedProperties adaptedProperties = new AdaptedProperties(); for(Entry<String,String> entry : map.entrySet()) { Property property = new Property(); property.name = entry.getKey(); property.value = entry.getValue(); adaptedProperties.property.add(property); } return adaptedProperties; } }

Modelo de dominio (raíz)

A continuación se muestra un objeto modelo con una propiedad de Map . La anotación @XmlJavaTypeAdapter se usa para especificar el XmlAdapter .

import java.util.Map; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlJavaTypeAdapter(MapPropertiesAdapter.class) private Map<String, String> properties; }

Manifestación

import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum17024050/input.xml"); Root root = (Root) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } }

input.xml / Salida

<?xml version="1.0" encoding="UTF-8"?> <root> <properties> <property name="A">a</property> <property name="B">b</property> </properties> </root>

Tengo un Map<String, String> .
La primera idea que todos tienen es convertirla en una List<Pair<String,String>> ( Pair es una clase personalizada).

He probado un @XmlAdapter como este:

public class MapPropertiesAdapter extends XmlAdapter<List<Property>, Map<String,String>> { ... }

Pero Eclipse MOXy, la aplicación JAXB que uso, terminó con ClassCastException : "no se puede convertir HashMap en Collection".

¿Esta conversión es compatible con JAXB? ¿O pasé por alto parte de la documentación que explica por qué no lo es?

PD: quería obtener XML así:

<properties> <property name="protocol"/> <property name="marshaller"/> <property name="unmarshaller"/> <property name="timeout"/> ... </properties>

Lo tengo, solo tuve que usar una clase intermedia. También se describe en Handle NPE en XMLCompositeObjectMappingNodeValue.marshalSingleValue (XMLCompositeObjectMappingNodeValue.java:161)