{
"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 楼
您可以在这里:import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
Type type = new TypeToken<Map<String, String>>(){}.getType();
Map<String, String> myMap = gson.fromJson("{'k1':'apple','k2':'orange'}", type);
评论
不错,但是我不喜欢使用TypeToken-它确实在内部隐式转换。
– AlikElzin-kilaka
2014年5月26日15:57
投放到Map <>,您结束了我的无聊时光!
–糊精
17年1月21日在18:48
示例中的那个有效json吗?
–埃文·凯鲁兹(Evan Kairuz)
19年2月15日在20:46
@EvanKairuz不,不是。应该是{“ k1”:“ apple”,“ k2”:“ orange”}
–Vadim Kotov
19-09-27在11:41
如果我需要转换实际上是数组的字符串怎么办
–拉维·亚达夫(Ravi Yadav)
19年11月15日13:50
#2 楼
此代码适用于: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());
评论
这会将int转换为float,然后再将其转换为字符串,但可以将JSON转换为map以进行比较。
–louielouie
2012年10月19日在21:49
对我来说效果很好,但是我将地图更改为Map
– Moshe Shaham
13年7月13日在13:52
这给人留下了错误的印象。参数化类型的正确解决方案是TypeToken。
– Sotirios Delimanolis
16年7月26日在14:29
这将是所有类型的通用解决方案,但有点少见。
–里昂
18年8月21日在11:12
#3 楼
我知道这是一个相当老的问题,但是我正在寻找一种将嵌套JSON反序列化为Map<String, Object>
的解决方案,却一无所获。我的yaml反序列化器的工作方式是,它将JSON对象默认为
Map<String, Object>
当您没有指定类型,但gson似乎没有这样做时。幸运的是,您可以使用自定义反序列化器完成此操作。我使用以下反序列化器对任何内容进行自然反序列化,将
JsonObject
s分别设置为Map<String, Object>
和JsonArray
s分别设置为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或Integer或Long,并且可能会更好,或者至少可以简化。可以使用BigDecimals,我相信这是默认设置。您可以像下面这样注册该适配器:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer());
Gson gson = gsonBuilder.create();
然后调用它像这样:
Object natural = gson.fromJson(source, Object.class);
我不确定为什么这不是gson中的默认行为,因为它在大多数其他半结构化序列化库中也是如此...
评论
...尽管我不太确定现在该如何处理返回的对象。即使我知道它们是字符串,似乎也无法将它们转换为String
–马特·祖科夫斯基
2011年5月20日,1:17
啊哈!诀窍是递归调用解串器,而不是context.deserialize()调用。
–马特·祖科夫斯基
2011年5月20日在1:34
你有代码马特吗?我正在尝试在反序列化器上进行更改,但我真的看不到你的意思
–罗曼·皮尔(Romain Piel)
2011年7月18日在16:30
现在默认情况下,Gson在他的代码片段中似乎具有Kevin Dolan想要的行为。
–eleotlecram
2013年1月25日15:13
@SomeoneSomewhere在此处查看已接受的答案stackoverflow.com/questions/14944419/gson-to-hashmap
– M.Y.
2014年7月9日在9:36
#4 楼
使用Google的Gson 2.7(可能也是更早的版本,但我使用当前版本2.7进行了测试),操作非常简单:Map map = gson.fromJson(jsonString, Map.class);
返回
Map
类型的com.google.gson.internal.LinkedTreeMap
并可以正常工作我递归地运行OP示例(用单引号简单地将double-替换并除去空白):
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}
#5 楼
更新了新的Gson库:您现在可以将嵌套的Json直接解析为Map,但是如果您尝试将Json解析为
Map<String, Object>
类型,则应注意:它将引发异常。要解决此问题,只需将结果声明为LinkedTreeMap
类型。以下示例:String nestedJSON = "{"id":"1","message":"web_didload","content":{"success":1}};
Gson gson = new Gson();
LinkedTreeMap result = gson.fromJson(nestedJSON , LinkedTreeMap.class);
评论
我从哪里导入LinkedTreeMap?我在Gson代码中找不到它。
– HelpMeStackOverflowMyOnlyHope
2014年8月10日15:33
我记得,LinkedTreeMap是在新的Gson lib中定义的。您可以在此处查看:code.google.com/p/google-gson/source/browse/trunk/gson/src/main/…
– Hoang Nguyen Huu
15年6月18日在9:28
对我来说,它也可以与Map
– Ferran Maylinch
16-3-26在23:36
#6 楼
我有完全相同的问题,并在这里结束。我采用了一种似乎更简单的方法(也许是gson的较新版本?)。 Gson gson = new Gson();
Map jsonObject = (Map) gson.fromJson(data, Object.class);
并带有以下json
{
"map-00": {
"array-00": [
"entry-00",
"entry-01"
],
"value": "entry-02"
}
}
以下
Map map00 = (Map) jsonObject.get("map-00");
List array00 = (List) map00.get("array-00");
String value = (String) map00.get("value");
for (int i = 0; i < array00.size(); i++) {
System.out.println("map-00.array-00[" + i + "]= " + array00.get(i));
}
System.out.println("map-00.value = " + value);
输出
map-00.array-00[0]= entry-00
map-00.array-00[1]= entry-01
map-00.value = entry-02
您可以在何时使用instanceof动态检查浏览您的jsonObject。
Map json = gson.fromJson(data, Object.class);
if(json.get("field") instanceof Map) {
Map field = (Map)json.get("field");
} else if (json.get("field") instanceof List) {
List field = (List)json.get("field");
} ...
对我有用,所以它必须对你有用;-)
#7 楼
自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));
}
#8 楼
试试这个,它将起作用。我将其用于Hashtable。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替换为您的键类。
评论
在HashMap抛出LinkedTreeMap异常之后,这对我有用。
– newfivefour
2014年3月19日3:00,
#9 楼
这是我一直在使用的: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;
}
#10 楼
这是一个可以做到的事情:HashMap<String, Object> myMap =
gson.fromJson(yourJson, new TypeToken<HashMap<String, Object>>(){}.getType());
评论
是的,它只是一行,但是请记住,新的TypeToken
–马丁·迈瑟(Martin Meeser)
5月12日14:07
#11 楼
我已经使用Custom 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;
}
此解决方案的缺点在于,我的Map的密钥始终为“字符串”类型。但是,通过更改某些内容,可以使某些人通用。另外,我需要说的是,该值的类应在构造函数中传递。因此,我代码中的方法
getMyType()
返回在构造函数中传递的Map值的类型。您可以参考这篇文章如何为Gson写一个自定义JSON反序列化器?为了进一步了解自定义解串器。
#12 楼
您可以改用此类:)(处理列表,嵌套列表和json)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,请使用以下命令: br />
HashMap<String, Object> hashMap = new HashMap<>(Utility.jsonToMap(response)) ;
#13 楼
这不是凯文·多兰(Kevin Dolan)答案的补充,而不是完整的答案,但是我在从数字中提取类型时遇到了麻烦。这是我的解决方案: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());
}
}
#14 楼
HashMap<String, String> jsonToMap(String JsonDetectionString) throws JSONException {
HashMap<String, String> map = new HashMap<String, String>();
Gson gson = new Gson();
map = (HashMap<String, String>) gson.fromJson(JsonDetectionString, map.getClass());
return map;
}
#15 楼
JSONObject通常在内部使用HashMap
来存储数据。因此,您可以在代码中将其用作Map。 示例,
JSONObject obj = JSONObject.fromObject(strRepresentation);
Iterator i = obj.entrySet().iterator();
while (i.hasNext()) {
Map.Entry e = (Map.Entry)i.next();
System.out.println("Key: " + e.getKey());
System.out.println("Value: " + e.getValue());
}
评论
这是来自json-lib,而不是gson!
– Ammar
2011-12-14 14:43
#16 楼
我使用了以下代码:Gson gson = new Gson();
HashMap<String, Object> fields = gson.fromJson(json, HashMap.class);
评论
这给了我未经检查的转换警告。
– Line
17年6月2日在15:12
评论
Map如何转换回来?我的意思是从Map到Json Array。