[英]How to serialize a java.util.Map[String, Object] to JSON in Scala using Play 2.3.9?
[英]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.