[英]jersey (+ jackson) map field serialization
我有一個簡單的jersey網絡服務,我想消費/產生包含地圖字段的對象,例如
@XmlElement
private Map<String,String> properties;
如果此字符串進入Web服務,
{ properties: { key1: val1, key2: val2 )}
屬性字段反序列化為null,沒有錯誤。 相同的JSON進出GSON沒問題,在短期內,我通過讓jersey使用產生字符串並使用GSON序列化/反序列化JSON解決了這一問題。
有任何想法嗎? 謝謝。
一種選擇是使用帶注釋的類。 因此,例如,一個用戶可能由以下數據表示。
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "user")
public class User {
private int uid;
public int user_id;
public String user_name;
public String email;
public URI image_url;
public List<User> friends;
public boolean admin;
public User() {
...
}
public User(final int userid) {
// Find user by id
}
}
如果按照以下代碼返回User對象,那么jaxb會自動將List序列化為JSON列表等。
@GET
@Path("/{userid}")
@Produces("application/json", "application/xml")
public User showUser(@PathParam("userid") final int userid) {
return new User(userid);
}
Jersey使用JAXB進行序列化。 JAXB無法序列化Map,因為Java類型Map沒有XML類型。 而且,Map是一個接口,而JAXB不喜歡接口。 如果您正在使用JAXBJackson橋進行封送,則會遇到問題。
您將需要創建如下所示的適配器,並使用注釋您的Map屬性
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String,String> properties;
@XmlSeeAlso({ Adapter.class, MapElement.class })
public class MapAdapter<K,V> extends XmlAdapter<Adapter<K,V>, Map<K,V>>{
@Override
public Adapter<K,V> marshal(Map<K,V> map) throws Exception {
if ( map == null )
return null;
return new Adapter<K,V>(map);
}
@Override
public Map<K,V> unmarshal(Adapter<K,V> adapter) throws Exception {
throw new UnsupportedOperationException("Unmarshalling a list into a map is not supported");
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="Adapter", namespace="MapAdapter")
public static final class Adapter<K,V>{
List<MapElement<K,V>> item;
public Adapter(){}
public Adapter(Map<K,V> map){
item = new ArrayList<MapElement<K,V>>(map.size());
for (Map.Entry<K, V> entry : map.entrySet()) {
item.add(new MapElement<K,V>(entry));
}
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="MapElement", namespace="MapAdapter")
public static final class MapElement<K,V>{
@XmlAnyElement
private K key;
@XmlAnyElement
private V value;
public MapElement(){};
public MapElement(K key, V value){
this.key = key;
this.value = value;
}
public MapElement(Map.Entry<K, V> entry){
key = entry.getKey();
value = entry.getValue();
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.