我从一个返回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模块。


当前回答

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());
}

其他回答

给你:

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);

我也有同样的问题,结果来了这里。我有一个不同的方法,看起来简单得多(也许是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

您可以在导航jsonObject时使用instanceof动态检查。类似的

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");
} ...

它对我有效,所以它一定对你有效;-)

我已经克服了一个自定义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 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());

试试这个,它会起作用的。我在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替换为键类。