Mar*_*arc 5 java serialization json gson
我在尝试反序列化java对象时遇到问题,因为对象内的字段("info")可能是两种可能的类型之一:ArrayList或者只是String.Here是我到目前为止所做的:
首先,创建类Base:
public class Base {
}
Run Code Online (Sandbox Code Playgroud)
接下来创建子类:
public class GoodInfo extends Base {
public ArrayList<MyCustomObject> info;
}
public class BadInfo extends Base {
public String info;
}
Run Code Online (Sandbox Code Playgroud)
所以现在我想解析我的JSON,它是Base对象的ArrayList(即每个对象是ArrayList或String的对象的ArrayList):
Type listOfBase = new TypeToken<ArrayList<Base>>(){}.getType();
ArrayList<Base> resp=gson.fromJson(jsonText, listOfBase);
Run Code Online (Sandbox Code Playgroud)
我知道为了这个工作,我必须写一个自定义的反序列化器.解串器看起来像这样:
private class MyCustomDeserializer implements JsonDeserializer<DateTime> {
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
// WHAT DO I DO HERE?
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我不知道如何尝试反序列化每个子类型并返回有效的类型.有人知道怎么做吗?
我认为它看起来像这样:
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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据GSON,我不能在传入的json上使用context.deserialize:在指定对象上调用默认的反序列化.永远不应该在作为JsonDeserializer.deserialize(JsonElement,Type,JsonDeserializationContext)方法的参数接收的元素上调用它.这样做会导致无限循环,因为Gson会再次调用自定义反序列化器.
那我该怎么做?
没有文档读取(强调我的):
...你永远不应该在相同的类型
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);
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以JsonDeserializer通过修改超类来完全绕过自定义.拉起info场Object,例如:
public class Base {
public Object info;
}
Run Code Online (Sandbox Code Playgroud)
将允许Gson适当地反序列化该值.
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
该解决方案是工作正常为GoodInfo和BadInfo是相同类型的不Base因为在视对象点GSON偏离航线,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;
}
}
Run Code Online (Sandbox Code Playgroud)
测试:
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);
Run Code Online (Sandbox Code Playgroud)
它打印:
2
test
[test, test, test]
| 归档时间: |
|
| 查看次数: |
3152 次 |
| 最近记录: |