我有一个看起来像这样的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来实现这一目标?
您至少有两个选择:命令式和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,该伪造的DTO将成为GsonTypeToken
的特殊标记,以便更精确地绑定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
值或的自定义反序列化器null
。一旦绑定了类型及其反序列化器,Gson
就可以使用该实例了,并且可以像解析一个整数到整数列表一样对给定的JSON进行解析。完全相同的输出如下:
{1 = [1、2、3、4],2 = [5、6],3 = [3、4]}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句