The best, easiest way to do this is to wrap the JSON itself in a container that contains the type.
For example:
{
"foo":"bar"
}
Becomes
{
"type":"FooContainer"
"value": {
"foo":"bar"
}
}
However, you said you can't do that, so I won't go into details about how to actually do the deserialization. If you can do this limited change, you can write a TypeAdapterFactory
and let Gson do all the rest of the work, by using the passed Gson
object in the create()
method and calling gson.fromJson()
in the read method, which will be a lot less code than the method below.
Think about what really needs to happen here. Somehow, you need to detect what data is in the Websphere MQ objects and use that to figure it out. Detecting it in this way is going to take code, to analyze what data you've received, and spit out the correct object.
The first problem you're going to face is that you don't want to do this:
Object myObj = gson.fromJson(jsonString, Object.class);
This means that you are overriding the default, base deserializer, which can have all sort of nasty side effects. It's better to wrap the behavior in the TypeAdapter
for some sort of custom object:
public class Wrapper {
public Object data; // Encapsulate this if you want, this is just for brevity
}
I'll leave the casting / generics to you. There are lots of ways to do it but I recommend the Visitor Pattern as a good choice, or perhaps creating an enum type object. It would be best if you can have all the received object types implement some sort of interface to make this easier, but, again, that's not your main problem.
Your main problem is actually detecting these classes in code. Now that we have a wrapper class, we can use this:
Wrapper myWrapper = gson.fromJson(jsonString, Wrapper.class);
Now, every class that's generated is the same class, so Gson is happy. But where do we put the rules? They go in your custom TypeAdapter
:
public class WrapperTypeAdapter extends TypeAdapter<Wrapper> {
@Override
public final void write(JsonWriter out, Wrapper value) throws IOException {
if(value == null) {
out.nullValue();
return;
}
// Don't worry about Write for now, obviously
}
@Override
public final Wrapper read(JsonReader in) throws IOException {
if(in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
Wrapper wrapper = new Wrapper();
// HERE IS WHERE YOU GET TO WRITE CODE
return wrapper;
}
}
In the read method, as you stream tokens, you can use rules based on what you expect the JSON tokens themselves to be to decide what class it's going to be, then construct the new object. I recommend breaking this down into many methods like MyFoo readMyFoo(JsonReader)
, MyBar readMyBar(JsonReader)
, etc. It's difficult for me to go into much more detail without knowing more about the JSON itself, but this should be enough to start you off.