2013-06-10 29 views
7

Map<String, String> var.
Herkesin sahip olduğu ilk fikir, onu List<Pair<String,String>> (özel bir sınıf olmak üzere Pair) haline getirmektir.JAXB @XmlAdapter: Harita -> Adaptör listesi? (yalnızca marshall)

Böyle bir @XmlAdapter denedim:

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

Ama Eclipse Moxy, kullandığım JAXB impl, bir ClassCastException ile sona erdi - "Koleksiyonuna HashMap dönüştürmek olamaz".

Bu dönüştürmeyi JAXB tarafından desteklenen midir? Ya da neden olmadığını açıklayan bazı dokümantasyon bölümlerini gözden kaçırdım mı?

Not: Böyle XML almak istedim:

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

Anladım, sadece bir ara sınıf kullanmak zorunda kaldı. Ayrıca yerine List için Map uyarlamak Handle NPE in XMLCompositeObjectMappingNodeValue.marshalSingleValue(XMLCompositeObjectMappingNodeValue.java:161)

cevap

8

açıklandığı, bir List özelliği olan bir nesneye adapte edilmelidir.

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; 
    } 

} 

etki alanı modeli (Kök) Aşağıda

bir Map özelliği ile örnek bir amacıdır. @XmlJavaTypeAdapter ek açıklaması, XmlAdapter belirtmek için kullanılır.

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; 

} 

Demo

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/Çıktı

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

Hiç kullanışlı adaptörleri bir sürü bir java kütüphanesi oluşturmak için düşündünüz mü? –

+0

Harita yerine, > var mı ??? – Anand