2014-11-21 74 views
0

我有一个需要mashalling/unmashalling的逻辑。我正在使用jaxws的metro实现。 我使用了Blaise here的建议,它适用于我的对象数据是字符串的场景。对于具有列表作为我注意到数据,在客户端(在网络上)的那些,JAXB产生它自己的自定义ArrayList类即延长定制AbstractList中,如下所示:JAXB地图错误

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "arrayList") 
@XmlSeeAlso({ 
    CustomFieldMap.class 
}) 
public class ArrayList 
    extends AbstractList 
{ 


} 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "abstractList") 
@XmlSeeAlso({ 
    ArrayList.class 
}) 
public abstract class AbstractList 
    extends AbstractCollection 
{ 


} 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "abstractCollection") 
@XmlSeeAlso({ 
    AbstractList.class 
}) 
public abstract class AbstractCollection { 


} 

我认为上面是有点怪因为,当客户需要消耗ArrayList的数据,没有价值的呈现,因为它使用的是自定义的ArrayList代替java.util.ArrayList中

我的模型看起来像这样:

@XmlSeeAlso({ CFMap.class, CField.class, ArrayList.class }) 
public final class MAdapt 
     extends 
     XmlAdapter< CFMap, Map< String, Object >> 
{ 
    @Override 
    public CFMap marshal(Map< String, Object > pCField) 
     throws Exception 
    { 
     CFMap vCFMap = new CFMap(); 

     // ignore custom fields having null values 
     if(pCField == null) 
     { 
     return vCFMap; 
     } 

     for(Entry< String, Object > vEntry : pCField.entrySet()) 
     { 
     CField vCField = new CField(); 
     vCField.key = vEntry.getKey(); 
     vCField.value = vEntry.getValue(); 
     vCFMap.add(vCField); 
     } 

     return vCFMap; 
    } 

    @Override 
    public Map< String, Object > unmarshal(CFMap pCFMap) 
     throws Exception 
    { 
     HashMap< String, Object > vHashMap = new HashMap< String, Object >(); 

     if(pCFMap == null) 
     { 
     return vHashMap; 
     } 

     pCFMap.forEach(p -> vHashMap.put(p.key, p.value)); 

     return vHashMap; 
    } 
} 



@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlSeeAlso({CField.class, ArrayList.class}) 
public class CFMap extends ArrayList<CField> 
{ 
    private static final long serialVersionUID = 1L; 

    @XmlElement (name = "cField") 
    public List<CField> getCFields() 
    { 
     return this; 
    } 
} 

@XmlRootElement 
@XmlSeeAlso({ MAdapt.class, CFMap.class, ArrayList.class }) 
public class CField 
{ 
    @XmlElement(nillable = true) 
    public String key; 

    @XmlElement(nillable = true) 
    public Object value; 
} 

的用法是:

@XmlRootElement 
public class TestC 
{ 
    .... 
    protected Map< String, Object > csFields; 

    @XmlElement(name = "cfields") 
    @XmlJavaTypeAdapter(MAdapt.class) 
    public Map< String, Object > getCsFields() 
    { 
     return customFields; 
    } 
} 

回答

0

我终于能够解开这个谜团。

我通过创建一个子类来处理收集类型像这样修改的适配器:

@XmlType (name = "itemList") 
public static class CType 
{ 
    @XmlElement (name = "item") 
    private Collection<?> items; 
} 

然后数据编排期间执行必要的健全性检查:

@Override 
public CFMap marshal(Map< String, Object > pCField) 
    throws Exception 
{ 
    ..... 

    for(Entry< String, Object > vEntry : pCField.entrySet()) 
    { 
    ... 
    Object vTempV = vEntry.getValue(); 
    if (vTempV instanceof Collection<?>) 
    { 
     CType wrapper = new CType(); 
     wrapper.collection = (Collection<?>) vTempV; 
     vCustomField.value = wrapper; 
    } 
    else 
    { 
     vCustomField.value = vTempV; 
    } 

    vCFMap.add(vCField); 
    } 

    return vCFMap; 
}