我从一个返回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模块。
使用谷歌的Gson 2.7(可能是更早的版本,但我测试了当前的2.7版本),它很简单:
Gson gson = new Gson();
Map map = gson.fromJson(jsonString, Map.class);
它返回一个类型为com.google.gson. inner . linkedtreemap的Map,并对嵌套对象、数组等进行递归工作。
我像这样运行OP示例(简单地将双引号替换为单引号并删除空格):
String jsonString = "{'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'}";
Map map = gson.fromJson(jsonString, Map.class);
System.out.println(map.getClass().toString());
System.out.println(map);
并得到如下输出:
class com.google.gson.internal.LinkedTreeMap
{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}
我已经克服了一个自定义JsonDeSerializer类似的问题。我试着让它有点通用,但还是不够。这是一个满足我需求的解决方案。
首先,需要为Map对象实现一个新的JsonDeserializer。
public class MapDeserializer<T, U> implements JsonDeserializer<Map<T, U>>
反序列化方法看起来像这样:
public Map<T, U> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (!json.isJsonObject()) {
return null;
}
JsonObject jsonObject = json.getAsJsonObject();
Set<Entry<String, JsonElement>> jsonEntrySet = jsonObject.entrySet();
Map<T, U> deserializedMap = new HashMap<T, U>();
for (Entry<java.lang.String, JsonElement> entry : jsonEntrySet) {
try {
U value = context.deserialize(entry.getValue(), getMyType());
deserializedMap.put((T) entry.getKey(), value);
} catch (Exception ex) {
logger.info("Could not deserialize map.", ex);
}
}
return deserializedMap;
}
这个解决方案的缺点是,我的地图的键总是类型“字符串”。然而,通过改变某些东西,人们可以使它变得通用。此外,我需要说,值的类应该在构造函数中传递。因此,代码中的getMyType()方法返回Map值的类型,该类型被传递到构造函数中。
你可以参考这篇文章我如何为Gson编写一个自定义JSON反序列化?以了解有关自定义反序列化器的更多信息。
从gson 2.8.0开始支持以下内容
public static Type getMapType(Class keyType, Class valueType){
return TypeToken.getParameterized(HashMap.class, keyType, valueType).getType();
}
public static <K,V> HashMap<K,V> fromMap(String json, Class<K> keyType, Class<V> valueType){
return gson.fromJson(json, getMapType(keyType,valueType));
}