我在尝试反序列化java对象时遇到问题,因为对象内的字段(" info")可能是两种可能的类型之一:ArrayList或者只是一个String.Here就是我这样做的远:
首先,创建类Base:
public class Base {
}
接下来创建子类:
public class GoodInfo extends Base {
public ArrayList<MyCustomObject> info;
}
public class BadInfo extends Base {
public String info;
}
所以现在我想解析我的JSON,这是一个Base对象的ArrayList(即每个对象是ArrayList或String的对象的ArrayList):
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会再次调用自定义反序列化器。
那我该怎么做?
答案 0 :(得分:7)
没有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适当地反序列化该值。
答案 1 :(得分:4)
class MyCustomDeserializer implements JsonDeserializer<Base>
{
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{
try
{
return context.deserialize(json, GoodInfo.class);
}
catch (JsonParseException e)
{
return context.deserialize(json, BadInfo.class);
}
}
}
此解决方案工作正常,因为GoodInfo
和BadInfo
与GSON的Base
类型不同,因为从对象的角度来看,GoodInfo
和BadInfo
个实例是 Base
个实例。
考虑到这两个类已实现toString()
:
class GoodInfo extends Base
{
public ArrayList<String> info;
public String toString()
{
return info.toString();
}
}
class BadInfo extends Base
{
public String info;
public String toString()
{
return info;
}
}
测试:
Type listOfBase = new TypeToken<ArrayList<Base>>(){}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Base.class, new MyCustomDeserializer());
Gson gson = gsonBuilder.create();
ArrayList<Base> resp = gson.fromJson("[{\"info\": \"test\"}, {\"info\": [\"test\", \"test\", \"test\"]}]", listOfBase);
System.out.println(resp.size());
for (Object o : resp) System.out.println(o);
打印:
2
test
[test, test, test]