你至少有兩個選擇:命令式和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]}