2015-04-17 9 views
9

sul lato server ho avuto questa API (ad esempio)GSON serializzare/deserializzare Mappa per/dalla lista dei KeyValuePairs

namespace MyNameSpace 
{ 
    [Serializable][DataContract] 
    public class GetMyObject 
    { 
     [DataMember] 
     public Dictionary<int, int> MyDictionary { get; set; } 
    } 
} 

E il server invia questo JSON (non riesco a modificare questo.):

{ 
    "MyDictionary" : 
     [{ 
      "Key" : 1, 
      "Value" : 1 
     }, 
     { 
      "Key" : 2, 
      "Value" : 2 
     }, 
     { 
      "Key" : 3, 
      "Value" : 3 
     }, 
     { 
      "Key" : 4, 
      "Value" : 4 
     }] 
} 

E sul lato client, devo creare queste classi per una corretta deserializzazione:

class GetMyObject { 
    @SerializedName("MyDictionary") 
    private List<MyDictionaryItem> myDictionary; 
} 

class MyDictionaryItem { 
    @SerializedName("Key") 
    private int key; 

    @SerializedName("Value") 
    private int value; 
} 

Come posso configurare GSON di utilizzare semplicemente questo: (per serializzare e deserializzare)

class GetMyObject { 
    @SerializedName("MyDictionary") 
    private Map<Integer, Integer> myDictionary; 
} 

E 'ancora più intresting con complessi oggetto chiave come:

class ComplexKey { 
    @SerializedName("Key1") 
    private int key1; 

    @SerializedName("Key2") 
    private String key2; 
} 

class GetMyObject { 
    @SerializedName("MyDictionary") 
    private Map<ComplexKey, Integer> myDictionary; 
} 

risposta

8

Creare un costume JsonDeserializer per Map<?, ?>:

public class MyDictionaryConverter implements JsonDeserializer<Map<?, ?>> { 
    public Map<Object, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) { 
     Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(typeOfT, $Gson$Types.getRawType(typeOfT)); 

     Map<Object, Object> vals = new HashMap<Object, Object>(); 
     for (JsonElement item : json.getAsJsonArray()) { 
      Object key = ctx.deserialize(item.getAsJsonObject().get("Key"), keyAndValueTypes[0]); 
      Object value = ctx.deserialize(item.getAsJsonObject().get("Value"), keyAndValueTypes[1]); 
      vals.put(key, value); 
     } 
     return vals; 
    } 
} 

e registrarlo:

gsonBuilder.registerTypeAdapter(new TypeToken<Map>(){}.getType(), 
     new MyDictionaryConverter()); 
+1

Come posso farlo generica, quindi non devo creare per ogni mappa ? –

+0

@ GergelyFehérvári Ho modificato la mia risposta ancora una volta. Ho appena approcciato questo approccio e funziona solo con i generici. –

1

alternativa, Jackson JSON processore

@JsonDeserialize(contentAs=Integer.class) 
private Map<ComplexKey, Integer> myDictionary;