[英]How to write GSON custom deserializer for embedded object with two possible types
我在嘗試反序列化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會再次調用自定義反序列化器。
那我該怎么做?
沒有文檔讀取 (強調我的):
...你永遠不應該在傳遞
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適當地反序列化該值。
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
的類型與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;
}
}
測試:
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.