2017-02-16 62 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

你至少有兩個選擇:命令式和Gson方式。

在必要的選項,你可以簡單地分析整個JSON樹使用GSON設施步步給出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]}

一個替代方案是一種製造自定義假的DTO,它將成爲Gson TypeToken的特殊標記,以便更精確地綁定JSON反序列化。例如:

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數組元素:一旦它從父對象獲得的idElement委託給下游解析器提取Integer值。儘管可以使用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]}