сериализация поля карты джерси (+ джексон) - PullRequest
2 голосов
/ 05 апреля 2011

У меня есть простой веб-сервис Джерси, и я хотел бы использовать / создавать объекты, содержащие поля карты, например

@XmlElement
private Map<String,String> properties;

, если эта строка входит в веб-сервис,

{ properties: { key1: val1, key2: val2 )}

поле свойств десериализовано как ноль без ошибок.тот же самый JSON входит и выходит из GSON без проблем, и в краткосрочной перспективе я решил эту проблему с помощью использования строк с производством джерси и использования GSON для сериализации / десериализации JSON.

есть идеи?спасибо.

Ответы [ 2 ]

1 голос
/ 07 апреля 2011

Один из вариантов - использовать аннотированные классы. Так, например, пользователь может быть представлен следующими данными.

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 автоматически сериализует список в виде списка JSON и т. Д. И т. Д. *

@GET
@Path("/{userid}")
@Produces("application/json", "application/xml")
    public User showUser(@PathParam("userid") final int userid) {
        return new User(userid);
}
0 голосов
/ 21 июля 2011

Джерси использует JAXB для сериализации. JAXB не может сериализовать карту, так как не существует типа XML для карты типа Java. Кроме того, 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;
    }


  }

}
...