如何使用Gson将JSON转换为HashMap?

问题

我正在从服务器请求数据,该服务器以JSON格式返回数据。在发出请求时将HashMap转换为JSON并不难,但另一方面似乎有点棘手。 JSON响应如下所示:

{ 
    "header" : { 
        "alerts" : [ 
            {
                "AlertID" : "2",
                "TSExpires" : null,
                "Target" : "1",
                "Text" : "woot",
                "Type" : "1"
            },
            { 
                "AlertID" : "3",
                "TSExpires" : null,
                "Target" : "1",
                "Text" : "woot",
                "Type" : "1"
            }
        ],
        "session" : "0bc8d0835f93ac3ebbf11560b2c5be9a"
    },
    "result" : "4be26bc400d3c"
}

最简单的方法是访问这些数据?我正在使用GSON模块。


#1 热门回答(358 赞)

干得好

Type type = new TypeToken<Map<String, String>>(){}.getType();
Map<String, String> myMap = gson.fromJson("{'k1':'apple','k2':'orange'}", type);

#2 热门回答(93 赞)

此代码有效:

Gson gson = new Gson(); 
String json = "{\"k1\":\"v1\",\"k2\":\"v2\"}";
Map<String,Object> map = new HashMap<String,Object>();
map = (Map<String,Object>) gson.fromJson(json, map.getClass());

#3 热门回答(73 赞)

我知道这是一个相当古老的问题,但我正在寻找一种解决方案,通常将嵌套的JSON反序列化为aMap<String, Object>,但一无所获。

我的yaml反序列化器的工作方式,当你没有指定类型时,它默认JSON对象为Map<String, Object>,但是gson似乎没有这样做。幸运的是,你可以使用自定义反序列化器来完成它。

我使用以下反序列化器自然地反序列化任何东西,默认JsonObjects到Map<String, Object>JsonArrays到Object[]s,其中所有的孩子都被类似地反序列化。

private static class NaturalDeserializer implements JsonDeserializer<Object> {
  public Object deserialize(JsonElement json, Type typeOfT, 
      JsonDeserializationContext context) {
    if(json.isJsonNull()) return null;
    else if(json.isJsonPrimitive()) return handlePrimitive(json.getAsJsonPrimitive());
    else if(json.isJsonArray()) return handleArray(json.getAsJsonArray(), context);
    else return handleObject(json.getAsJsonObject(), context);
  }
  private Object handlePrimitive(JsonPrimitive json) {
    if(json.isBoolean())
      return json.getAsBoolean();
    else if(json.isString())
      return json.getAsString();
    else {
      BigDecimal bigDec = json.getAsBigDecimal();
      // Find out if it is an int type
      try {
        bigDec.toBigIntegerExact();
        try { return bigDec.intValueExact(); }
        catch(ArithmeticException e) {}
        return bigDec.longValue();
      } catch(ArithmeticException e) {}
      // Just return it as a double
      return bigDec.doubleValue();
    }
  }
  private Object handleArray(JsonArray json, JsonDeserializationContext context) {
    Object[] array = new Object[json.size()];
    for(int i = 0; i < array.length; i++)
      array[i] = context.deserialize(json.get(i), Object.class);
    return array;
  }
  private Object handleObject(JsonObject json, JsonDeserializationContext context) {
    Map<String, Object> map = new HashMap<String, Object>();
    for(Map.Entry<String, JsonElement> entry : json.entrySet())
      map.put(entry.getKey(), context.deserialize(entry.getValue(), Object.class));
    return map;
  }
}

handlePrimitive方法内部的混乱是为了确保你只获得一个Double或整数或一个Long,并且可能更好,或者至少简化如果你可以获得BigDecimals,我相信这是默认的。

你可以注册此适配器,如:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer());
Gson gson = gsonBuilder.create();

然后称之为:

Object natural = gson.fromJson(source, Object.class);

我不确定为什么这不是gson中的默认行为,因为它在大多数其他半结构化序列化库中...