Reputation: 3914
I am deserializing json that contains instances of many different classes, using gson. The following works as long as I know all the classes up front:
String receivedPayloadStr = receivedMessage.get("payload");
Type payloadType = getType(receivedMessage.get("type").toString());
Object typedPayload = gson.fromJson(payloadJson, payloadType);
System.out.println(typedPayload);
My getType function is as follows:
static Type getType(String typeName){
switch (typeName){
case "mypackage1.MyThing1":
return new TypeToken<MyThing1>() {}.getType();
case "mypackage2.MyThing1":
return new TypeToken<MyThing2>() {}.getType();
default:
throw new RuntimeException("Unsupported type: " + typeName);
}
}
Which works, short term, but is ugly and fragile. Clearly we want a more maintainable approach. Is there a way to implement getType in a general way, so that is supports all known classes?
Edit: we are not limited to gson. If another library makes the task easier, we can switch to it.
Upvotes: 2
Views: 7839
Reputation: 3993
Gson's TokenType has static factory method, and you can use it like this:
public Type getType(String name) {
try {
Class<?> clazz = Class.forName(typeName);
TypeToken<?> typeToken = TypeToken.get(clazz);
return typeToken.getType();
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Unsupported type: " + typeName, ce);
}
}
This should get you through majority of cases that do not involve generics or wildcards (or where wildcards are bounded, in which case you should get parametrized type that's right on the boundary).
Disclaimer: I have not tested this.
Also, you may want to check out Guava's version of a TypeToken.
Upvotes: 6