我在尝试反序列化Java对象时遇到了麻烦,因为对象内部的字段(“info”)可以是两种可能的类型之一:ArrayList或只是String。这是我到目前为止所做的:
首先,创建类Base:
public class Base {
}
接下来创建子类:
public class GoodInfo extends Base {
public ArrayList<MyCustomObject> info;
}
public class BadInfo extends Base {
public String info;
}
因此,现在我想解析我的JSON,它是基础对象的ArrayList(即对象的ArrayList,其中每个对象是ArrayList或String):
Type listOfBase = new TypeToken<ArrayList<Base>>(){}.getType();
ArrayList<Base> resp=gson.fromJson(jsonText, listOfBase);
我知道要使其正常工作,我必须编写一个自定义反序列化器。解串器如下所示:
private class MyCustomDeserializer implements JsonDeserializer<DateTime> {
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
// WHAT DO I DO HERE?
}
}
如您所见,我不知道该如何尝试反序列化每个子类型并返回有效的类型。有人知道怎么做吗?
我在想它看起来像这样:
private class MyCustomDeserializer implements JsonDeserializer<DateTime> {
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
try {
GoodInfo goodInfo=SOMEHOW TRY TO DESERIALIZE json INTO A GoodInfo object
return goodInfo;
} catch {
//
}
try {
BadInfo badInfo=SOMEHOW TRY TO DESERIALIZE json INTO A BadInfo object
return badInfo;
} catch {
throw new JsonParseException("Could not deserialize");
}
}
}
根据GSON,我不能在传入的json上使用context.deserialize:
对指定对象调用默认反序列化。永远不要在作为JsonDeserializer.deserialize(JsonElement,Type,JsonDeserializationContext)方法的参数接收的元素上调用它。这样做将导致无限循环,因为Gson会依次再次调用自定义解串器。
那么我该怎么做呢?
最佳答案
否documentation reads(重点是我的):
...您永远不要在传递相同类型json
的上调用它,因为这将导致无限循环...
只要类型不同,最好调用context.deserialize(...)
。
您可以使用json
检查info
字段并根据元素类型采取适当的操作,而不是在反序列化器中捕获异常,例如:public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
final JsonElement elem = json.getAsJsonObject()
.get("info");
if (elem.isJsonArray()) {
return context.deserialize(json, GoodInfo.class);
}
return context.deserialize(json, BadInfo.class);
}
另外,您可以通过修改超类来完全绕过自定义的JsonDeserializer
。将info
字段上拉为Object
,例如:public class Base {
public Object info;
}
将允许Gson适当地反序列化该值。