How can I convert JSON to a HashMap using Gson?
我正在从服务器请求数据,该服务器以JSON格式返回数据。 在发出请求时将HashMap转换为JSON并不难,但另一方面似乎有点棘手。 JSON响应如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | { "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 2 3 4 5 |
此代码有效:
1 2 3 4 |
我知道这是一个相当古老的问题,但我正在寻找一种解决方案,通常将嵌套的JSON反序列化为
我的yaml反序列化器的工作方式,当你没有指定类型时,它默认JSON对象为
我使用下面的反序列化器来自然地反序列化任何东西,将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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; } } |
您可以注册此适配器,如:
1 2 3 | GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer()); Gson gson = gsonBuilder.create(); |
然后把它称为:
我不确定为什么这不是gson中的默认行为,因为它在大多数其他半结构化序列化库中...
使用谷歌的Gson 2.7(可能是早期版本,但我使用当前版本2.7进行测试),它很简单:
返回类型
我像这样运行OP示例(简单地用单引号替换double并删除空格):
1 2 3 4 | 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); |
得到以下输出:
1 2 | 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} |
更新新的Gson lib:
您现在可以直接将嵌套的Json解析为Map,但是您应该知道如果您尝试将Json解析为
1 2 3 | String nestedJSON ="{"id":"1","message":"web_didload","content":{"success":1}}; Gson gson = new Gson(); LinkedTreeMap result = gson.fromJson(nestedJSON , LinkedTreeMap.class); |
我有完全相同的问题,最后来到这里。我有一个看起来更简单的不同方法(也许是更新版本的gson?)。
以下是json
1 2 3 4 5 6 7 8 9 | { "map-00": { "array-00": [ "entry-00", "entry-01" ], "value":"entry-02" } } |
下列
1 2 3 4 5 6 7 |
输出
1 2 3 | map-00.array-00[0]= entry-00 map-00.array-00[1]= entry-01 map-00.value = entry-02 |
您可以在导航jsonObject时使用instanceof动态检查。就像是
1 2 3 4 5 6 |
它对我有用,所以它必须适合你;-)
从gson 2.8.0开始支持以下版本
1 2 3 4 5 6 7 |
试试这个,它会奏效。我把它用于Hashtable。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public static Hashtable<Integer, KioskStatusResource> parseModifued(String json) { JsonObject object = (JsonObject) new com.google.gson.JsonParser().parse(json); Set<Map.Entry<String, JsonElement>> set = object.entrySet(); Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator(); Hashtable<Integer, KioskStatusResource> map = new Hashtable<Integer, KioskStatusResource>(); while (iterator.hasNext()) { Map.Entry<String, JsonElement> entry = iterator.next(); Integer key = Integer.parseInt(entry.getKey()); KioskStatusResource value = new Gson().fromJson(entry.getValue(), KioskStatusResource.class); if (value != null) { map.put(key, value); } } return map; } |
将KioskStatusResource替换为您的类,将Integer替换为您的密钥类。
这是我一直在使用的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public static HashMap<String, Object> parse(String json) { JsonObject object = (JsonObject) parser.parse(json); Set<Map.Entry<String, JsonElement>> set = object.entrySet(); Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator(); HashMap<String, Object> map = new HashMap<String, Object>(); while (iterator.hasNext()) { Map.Entry<String, JsonElement> entry = iterator.next(); String key = entry.getKey(); JsonElement value = entry.getValue(); if (!value.isJsonPrimitive()) { map.put(key, parse(value.toString())); } else { map.put(key, value.getAsString()); } } return map; } |
我已经克服了自定义JsonDeSerializer的类似问题。我试图让它有点通用但仍然不够。这是一个满足我需求的解决方案。
首先,您需要为Map对象实现一个新的JsonDeserializer。
1 | public class MapDeserializer<T, U> implements JsonDeserializer<Map<T, U>> |
并且反序列化方法看起来类似于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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; } |
与此解决方案一致的是,我的Map的键始终是Type"String"。然而,通过chaning某些东西,有人可以使它成为通用的。另外,我需要说,值的类应该在构造函数中传递。所以我的代码中的方法
您可以参考这篇文章如何为Gson编写自定义JSON反序列化器?以了解有关自定义反序列化器的更多信息。
这是一个可以做到这一点的单线程:
1 2 |
你可以使用这个类:)(处理偶数列表,嵌套列表和json)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | public class Utility { public static Map<String, Object> jsonToMap(Object json) throws JSONException { if(json instanceof JSONObject) return _jsonToMap_((JSONObject)json) ; else if (json instanceof String) { JSONObject jsonObject = new JSONObject((String)json) ; return _jsonToMap_(jsonObject) ; } return null ; } private static Map<String, Object> _jsonToMap_(JSONObject json) throws JSONException { Map<String, Object> retMap = new HashMap<String, Object>(); if(json != JSONObject.NULL) { retMap = toMap(json); } return retMap; } private static Map<String, Object> toMap(JSONObject object) throws JSONException { Map<String, Object> map = new HashMap<String, Object>(); Iterator<String> keysItr = object.keys(); while(keysItr.hasNext()) { String key = keysItr.next(); Object value = object.get(key); if(value instanceof JSONArray) { value = toList((JSONArray) value); } else if(value instanceof JSONObject) { value = toMap((JSONObject) value); } map.put(key, value); } return map; } public static List<Object> toList(JSONArray array) throws JSONException { List<Object> list = new ArrayList<Object>(); for(int i = 0; i < array.length(); i++) { Object value = array.get(i); if(value instanceof JSONArray) { value = toList((JSONArray) value); } else if(value instanceof JSONObject) { value = toMap((JSONObject) value); } list.add(value); } return list; } } |
要将JSON字符串转换为hashmap,请使用以下命令:
1 |
这是对Kevin Dolan的答案的补充,而不是一个完整的答案,但我无法从Number中提取类型。这是我的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private Object handlePrimitive(JsonPrimitive json) { if(json.isBoolean()) { return json.getAsBoolean(); } else if(json.isString()) return json.getAsString(); } Number num = element.getAsNumber(); if(num instanceof Integer){ map.put(fieldName, num.intValue()); } else if(num instanceof Long){ map.put(fieldName, num.longValue()); } else if(num instanceof Float){ map.put(fieldName, num.floatValue()); } else { // Double map.put(fieldName, num.doubleValue()); } } |
1 2 3 4 5 6 7 8 9 10 |
我用过这段代码:
JSONObject通常在内部使用
例,
1 2 3 4 5 6 7 |