Gson序列化/反序列化Map为/从键值对列表。

11

在服务器端,我得到了这个API(例如)(我无法修改它。

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

服务器会发送这个JSON:

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

而在客户端,我必须创建这些类以进行正确的反序列化:

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

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

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

我该如何配置GSON简单地使用以下内容:(进行序列化和反序列化)

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

即使是像复杂的关键对象这样的情况,它变得更加有趣:

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

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

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

8
创建一个自定义的JsonDeserializer用于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;
    }
}

并将其注册:

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

1
我该如何使它通用化,以便我不必为每个Map<K,V>创建一个? - Gergely Fehérvári
@GergelyFehérvári 我又编辑了一次我的答案。我刚测试了这个方法,它对泛型也适用。 - Egor Neliuba

2

一种替代方案,Jackson JSON处理器

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接