我有一个看起来像这样的JSON:
{
"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 :(得分:0)
你至少有两种选择:命令式和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]}
另一种方法是制作一个自定义假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()
,但委派idElement
是为了尊重整个Gson
配置(您可以对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
值的自定义反序列化程序或{{ 1}}。一旦绑定了类型及其反序列化器,就可以使用null
实例,并且可以解析给定的JSON ,就像它是整数列表的整数映射一样。完全相同的输出如下:
{1 = [1,2,3,4],2 = [5,6],3 = [3,4]}