2017-02-16 5 views
0

を使用してリストのリストを解析する方法:私はこのようになりますJSONを持ってGson

{ 
    "1": [{"id": 1}, {"id": 2},{"id": 3}, {"id": 4}], 
    "2": [{"id": 5}, {"id": 6}], 
    "3": [{"id": 3}, {"id": 4}] 
} 

は、私はそれが

List<List<Integer>> list 

または

Map<Integer, List<Integer>> map 

どのように解析されたいですこれを達成するためにGsonを使用すべきですか?

答えて

0

少なくとも2つのオプションがあります。命令型とGson型です。

不可欠オプションでは、あなたは、単にステップでGson施設のステップを使用して、指定されたJSONのための全体JSONツリー解析することができます:

final Gson gson = new GsonBuilder() 
     // any custom Gson configuration here 
     .create(); 
final Map<Integer, List<Integer>> map = new LinkedHashMap<>(); 
for (final Entry<String, JsonElement> e : gson.fromJson(JSON, JsonElement.class).getAsJsonObject().entrySet()) { 
    // parseInt() ignores additional type adapters in Gson 
    final Integer key = gson.fromJson(e.getKey(), Integer.class); 
    final List<Integer> list = new ArrayList<>(); 
    @SuppressWarnings({ "unchecked", "rawtypes" }) 
    final Iterable<JsonObject> asJsonArray = (Iterable) e.getValue().getAsJsonArray(); 
    for (final JsonObject el : asJsonArray) { 
     final Integer integer = gson.fromJson(el.get("id"), Integer.class); 
     list.add(integer); 
    } 
    map.put(key, list); 
} 
out.println(map); 

少し汚れが、そうではありません?。出力:

{1 = [1、2、3、4] 2 = [5、6]、3 = [3,4]}

代替カスタムを作っていますJSONのデシリアライズをより正確にバインドするために、Gson TypeTokenの特別なマーカーになる擬似DTO。例:

abstract class FakeInt { 

    private FakeInt() { 
     throw new AssertionError("Not meant to be instantiated"); 
    } 

} 

これは、プライベートコンストラクタがエラーをスローする抽象クラスであるため、外部でインスタンス化することはできません。そしてそれは決してあってはならない、ただのマーカだ。

final class FakeIntDeserializer 
     implements JsonDeserializer<Integer> { 

    private static final JsonDeserializer<Integer> fakeIntDeserializer = new FakeIntDeserializer(); 

    private FakeIntDeserializer() { 
    } 

    static JsonDeserializer<Integer> getFakeIntDeserializer() { 
     return fakeIntDeserializer; 
    } 

    @Override 
    public Integer deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context) { 
     final JsonElement idElement = json.getAsJsonObject().get("id"); 
     return context.deserialize(idElement, Integer.class); 
    } 

} 

このデシリアライザはid特性を有するJSON配列要素を認識している:それは親オブジェクトから取得だ後、idElementInteger値を抽出するために下流パーサに委任されています。 idElement.getAsInt()を使用することは可能ですが、Gson構成全体を尊重するためにidElementが委任されています(Integerクラスの特別なルールがあります)。そして、どのように偽のDTOクラスとそのJSONデシリアライザの仕事を一緒:

final Type integerToFakeIntListType = new TypeToken<Map<Integer, List<FakeInt>>>() { 
}.getType(); 
final Gson gson = new GsonBuilder() 
     .registerTypeAdapter(FakeInt.class, getFakeIntDeserializer()) 
     .create(); 
final Map<Integer, List<Integer>> map = gson.fromJson(JSON, integerToFakeIntListType); 
out.println(map); 

Gsonインスタンスがハックやチートの一種で構築されていること:FakeIntクラスができる唯一のリターンカスタムデシリアライザにバインドされていますInteger値またはnullです。型とそのデシリアライザがバインドされると、Gsonインスタンスが使用可能になり、指定されたJSONは、整数のリストのマップであるかのように、のように解析できます。次のように正確に同じ出力である:

{1 = [1、2、3、4] 2 = [5、6]、3 = [3,4]}

関連する問題