gson:用复合键反序列化json

时间:2012-07-13 19:51:12

标签: java json serialization map gson

我想用json:

来使用这种对象
class Message{
    int code;
    String user;
    Map<List<String>, List<String>> profile;
}

似乎json无法将Object键作为数组处理,所以我需要像这样传输它们:

{
"code": 1,
"user": "John",
"profile": {
    "type,1": ["tester"],
    "lang,2": ["fr", "it", "en", "sp"],
    "rate,4": ["10", "1000"],
    "date,5": ["134118329", "1341973211"]

    }
}

{
"code": 1,
"user": "John",
"profile": {
    "type": [1,"tester"],
    "lang": [2,"fr", "it", "en", "sp"],
    "rate": [4,"10", "1000"],
    "date": [5,"134118329", "1341973211"]

    }
}

第一个json可能更简单,即使它依赖于硬字符串分隔符,

所以第一个似乎我必须编写这个巨大的适配器:

private static class MyAdapter implements JsonSerializer<Map<List<String>, List<String>>>,
        JsonDeserializer<Map<List<String>, List<String>>> {

    @Override   
    public JsonElement serialize(Map<List<String>, List<String>> m,
            Type type, JsonSerializationContext context) {

        JsonObject j = new JsonObject();
        for (Entry<List<String>, List<String>> e : m.entrySet() ){
            JsonArray jj=new JsonArray();
            for (String s : e.getValue()){
                jj.add(new JsonPrimitive(s));
            }
            j.add(e.getKey().get(0)+","+e.getKey().get(1), jj);
        }
        return j;
    }

    @Override
    public Map<List<String>, List<String>> deserialize(JsonElement json, Type type,
            JsonDeserializationContext arg2) throws JsonParseException {

        Map<List<String>, List<String>> m = new HashMap<List<String>, List<String>>();

        JsonObject jObject = json.getAsJsonObject();
        for (Entry<String, JsonElement> e : jObject.entrySet() ){
            List<String> key = new ArrayList<String>();
            List<String> value = new ArrayList<String>();
            for (String s : e.getKey().split(",") ){
                key.add(s);
            }
            for (JsonElement jj : e.getValue().getAsJsonArray() ){
                value.add(jj.getAsString());
            }
            m.put(key, value);
        }
        return m;
    }
}

...

GsonBuilder g = new GsonBuilder();
    g.registerTypeAdapter(Map.class, new MyAdapter());
    Gson gson = g.create();

有更快的方法吗?我想是的,这个想法只是将密钥拆分为Map复合密钥,因为密钥的每个部分都有重要意义

thx,sry for the edit

2 个答案:

答案 0 :(得分:1)

这不起作用。

根据specification的对象声明语法:

  

对象是一组无序的名称/值对。一个对象开始   用{(左括号)和以}结尾(右括号)。每个名字都是   后跟:(冒号)和名称/值对分开,   (逗号)。

此:

{
    ["type", 1]: "tester",
    ["lang", 2]: ["fr", "it", "en", "sp"],
    ["rate", 4]: ["10", "1000"],
    ["date", 5]: ["134118329", "1341973211"]

}

无效,因此您无法使用Gson读取导致以下异常:com.google.gson.JsonSyntaxException:java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING

json前面的名字:aRequest =也是无效的。

答案 1 :(得分:1)

  

对于个人资料值,我不知道是否有优于对象

List<String>String[]看起来很自然,对单一值条目的处理不是列表格式。

不幸的是,反序列化JSON结构的问题(有时候是一个列表,有时候是一个对象)在SO上反复出现。幸运的是,solutions也是如此。