2013-06-10 18 views
7

Tôi có một số Map<String, String>.
Ý tưởng đầu tiên mà mọi người có là chuyển đổi nó thành một số List<Pair<String,String>> (Pair làm lớp tùy chỉnh).JAXB @XmlAdapter: Bản đồ -> Bộ điều hợp danh sách? (marshall only)

Tôi đã thử một @XmlAdapter như thế này:

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

Nhưng Eclipse MOXY, các impl JAXB tôi sử dụng, đã kết thúc với một ClassCastException - "không thể chuyển đổi HashMap vào bộ sưu tập".

Chuyển đổi này có được JAXB hỗ trợ không? Hoặc tôi đã bỏ qua một số phần tài liệu giải thích tại sao nó không phải là?

PS: tôi muốn để có được XML như thế này:

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

tôi đã nhận nó, chỉ phải dùng một lớp trung gian. Cũng được mô tả tại Handle NPE in XMLCompositeObjectMappingNodeValue.marshalSingleValue(XMLCompositeObjectMappingNodeValue.java:161)

Trả lời

8

Thay vì thích ứng Map đến một List, bạn nên thích ứng với nó đến một đối tượng mà có một tài sản 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; 
    } 

} 

Domain Model (Root)

Dưới đây là một đối tượng mô hình với một tài sản Map. Chú thích @XmlJavaTypeAdapter được sử dụng để chỉ định 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; 

} 

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/Output

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

Bạn đã bao giờ xem xét để tạo ra một thư viện java với rất nhiều adapter hữu ích? –

+0

Những thay đổi sẽ được thực hiện nếu thay vì Map , chúng ta có Map > ??? – Anand

Các vấn đề liên quan