I am having trouble trying to deserialize a java object because the field ("info") inside the object can be one of two possible types: either ArrayList or just a String.Here is what I did so far:
First, create class Base:
public class Base {
}
Next create subclasses:
public class GoodInfo extends Base {
public ArrayList<MyCustomObject> info;
}
public class BadInfo extends Base {
public String info;
}
So now I would like to parse my JSON which is an ArrayList of Base objects (i.e. an ArrayList of objects where each object is either an ArrayList or a String):
Type listOfBase = new TypeToken<ArrayList<Base>>(){}.getType();
ArrayList<Base> resp=gson.fromJson(jsonText, listOfBase);
I know that for this to work, I must write a custom deserializer. The deserializer looks like this:
private class MyCustomDeserializer implements JsonDeserializer<DateTime> {
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
// WHAT DO I DO HERE?
}
}
As you can see, I don't know what to do to try to deserialize each of these subtypes and return the type that works. Anyone know how to do this?
I'm thinking it would look something like this:
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");
}
}
}
I cannot use context.deserialize on json passed in, according to GSON: Invokes default deserialization on the specified object. It should never be invoked on the element received as a parameter of the JsonDeserializer.deserialize(JsonElement, Type, JsonDeserializationContext) method. Doing so will result in an infinite loop since Gson will in-turn call the custom deserializer again.
So how do I do this?
No the documentation reads (emphasis mine):
...you should never invoke it on the same type passing
json
since that will cause an infinite loop...
It's perfectly fine to invoke context.deserialize(...)
as long as the type is different.
Rather than catching exceptions in your deserializer, you can use json
to inspect the info
field and take the appropriate action based on the element type, for example:
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);
}
Alternatively you can bypass a custom JsonDeserializer
altogether by modifying the superclass. Pulling-up the info
field as an Object
, e.g.:
public class Base {
public Object info;
}
Will allow Gson to deserialize the value appropriately.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With