簡體   English   中英

如何將json解組到java.util.Map <String, Object> 與MOXy?

[英]How to unmarshal json to java.util.Map<String, Object> with MOXy?

我知道周圍也有類似的問題,例如如何將Map <Integer,List <Integer >>編組/解組? JAXB java.util.Map綁定 另外,我也經常閱讀Blaise Doughan的博客,尤其是這篇文章: http ://blog.bdoughan.com/2013/03/jaxb-and-javautilmap.html,並盡我所能遵循他的建議,但是我仍然不能成功解組json負載,並非常感謝您的幫助。

要解組的JSON有效負載如下所示:

{
    "uri":"\\foo\\dosomthing",
    "action":"POST",
    "queryParameters":[
        "$filter=aaa",
        "$orderby=bbb"
    ],
    "requestData":{
        "data1":{
            "key1":"value1",
            "key2":"value2"
        },
        "ids":[
            "1234",
            "0294"
        ]
    }
}

我在將“數據”編組到java.util.Map中時遇到問題。 “數據”字段沒有特定的架構,因此它可以包含數組,鍵值對或任何其他有效的json數據。 我決定使用地圖進行包裝。 根據我的研究,我認為我需要XmlAdapter才能正確轉換數據。

這是我的代碼:

Java模式類

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class CustomerRequest
{
    public CustomerRequest() {}

    public CustomerRequest(String uri, String action, List<String>
 queryParameters, Map<String, Object> reqeustData)
    {
        this.uri = uri;
        this.action = action;
        this.queryParameters = queryParameters;
        this.requestData = reqeustData;
    }

    public String getUri()
    {
        return uri;
    }

    public String getAction()
    {
        return action;
    }

    public List<String> getQueryParameters()
    {
        return Collections.unmodifiableList(queryParameters);
    }

    public Map<String, Object> getRequestData()
    {
        return Collections.unmodifiableMap(requestData);
    }

    @XmlElement
    private String uri;

    @XmlElement
    private String action;

    @XmlElementWrapper
    private List<String> queryParameters = new ArrayList<String>();

    @XmlPath(".")
    @XmlJavaTypeAdapter(StringObjectMapAdapter.class)
    private Map<String, Object> requestData = new HashMap<String, Object>();

}

XmlAdpater:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlAdapter;

import org.eclipse.persistence.oxm.annotations.XmlVariableNode;

public class StringObjectMapAdapter extends 
XmlAdapter<StringObjectMapAdapter.AdaptedMap, Map<String, Object>> 
{

public static class AdaptedEntry
{
    @XmlTransient
    public String key;

    @XmlValue
    public Object value = new Object();
}
public static class AdaptedMap
{
    @XmlVariableNode("key")
    List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}

@Override
public AdaptedMap marshal(Map<String, Object> map) throws Exception 
{
    AdaptedMap adaptedMap = new AdaptedMap();

    for (Entry<String, Object> entry : map.entrySet())
    {
        AdaptedEntry adaptedEntry = new AdaptedEntry();
        adaptedEntry.key = entry.getKey();
        adaptedEntry.value = entry.getValue();
        adaptedMap.entries.add(adaptedEntry);
    }
    return adaptedMap;
}

@Override
public Map<String, Object> unmarshal(AdaptedMap adaptedMap) throws Exception 
{
    List<AdaptedEntry> adapatedEntries = adaptedMap.entries;
    Map<String, Object> map = new HashMap<String, Object>(adapatedEntries.size());

    for (AdaptedEntry adaptedEntry : adapatedEntries )
    {
        map.put(adaptedEntry.key, adaptedEntry.value);
    }

    return map;
}

}

最后是我的測試應用程序:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.testng.annotations.Test;

public class TestStringObjectMapAdapter {

    @Test
    public void testUnmarshalFromJson() throws Exception 
    {
        JAXBContext jc = JAXBContext.newInstance(CustomerRequest.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
        unmarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        StreamSource json = new StreamSource("test-data.json");
        CustomerRequest request= unmarshaller.unmarshal(json,   
            CustomerRequest.class).getValue();

        assert(request.getUri().equals("\\foo\\dosomthing"));
        assert(request.getAction().equals("POST"));
    }
}

然后,當測試應用程序運行時,將生成一個java.lang.ClassCastException異常:

FAILED: testUnmarshalFromJson
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DocumentImpl cannot be cast to org.w3c.dom.Element
    at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.endSelfNodeValue(XMLCompositeObjectMappingNodeValue.java:468)
    at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.endDocument(UnmarshalRecordImpl.java:606)
    at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.endElement(UnmarshalRecordImpl.java:1084)
    at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:304)
    at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parseRoot(JSONReader.java:179)
    at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:125)
    at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:140)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:857)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:707)
    at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:655)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:301)
    at com.absolute.asb.urp.services.domain.TestStringObjectMapAdapter.testUnmarshalFromJson(TestStringObjectMapAdapter.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)

也許您應該嘗試創建正確的MoXY JAXBContext,例如:

    private static synchronized JAXBContext createJAXBContext() throws JAXBException {
        if(jc == null){
            jc = org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(new Class[] {CustomerReqeust.class}, null);
        }
        return jc;
    }

或使用類似http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html中提到的方法

順便說一句“ CustomerReqeust”拼寫有點錯誤:-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM