309

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モジュールを使用しています。

4

16 に答える 16

506

どうぞ:

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);
于 2013-04-11T07:39:28.693 に答える
120

このコードは機能します:

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());
于 2012-09-06T09:03:57.350 に答える
78

これはかなり古い質問であることは知っていますが、ネストされた JSON を に一般的に逆シリアル化するソリューションを探していましたがMap<String, Object>、何も見つかりませんでした。

私のyamlデシリアライザーの仕組みでMap<String, Object>は、タイプを指定しないとJSONオブジェクトがデフォルトになりますが、gsonはこれを行わないようです。幸いなことに、カスタム デシリアライザーを使用して実現できます。

次のデシリアライザーを使用して、すべての子が同様にデシリアライズされるデフォルトJsonObjectの sMap<String, Object>JsonArraysを自然にデシリアライズしました。Object[]

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 のデフォルトの動作ではない理由がわかりません...

于 2011-01-25T22:29:03.640 に答える
13

まったく同じ質問があり、ここにたどり着きました。私ははるかに単純に見える別のアプローチを持っていました(おそらく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");
} ...

それは私のために働くので、あなたのために働く必要があります;-)

于 2014-09-09T14:13:52.550 に答える
3

これを試してください、うまくいきます。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をキー クラスに置き換えます。

于 2012-09-14T10:50:05.127 に答える
2

これが私が使用しているものです:

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;
}
于 2011-11-10T14:42:39.677 に答える
1

カスタム 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 デシリアライザーを作成するにはどうすればよいですか? カスタムデシリアライザーについて詳しく知るために。

于 2013-03-01T12:47:40.943 に答える
-1
 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;

}
于 2017-09-21T19:38:49.743 に答える
-3

私はこのコードを使用しました:

Gson gson = new Gson();
HashMap<String, Object> fields = gson.fromJson(json, HashMap.class);
于 2015-04-21T15:06:36.260 に答える
-3

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());
}
于 2010-05-06T09:49:01.593 に答える