Reputation: 33056
I am currently working on a thin-client application, where the communication happens through JSON-serialized message objects. Server serializes the message, sends it through a socket, client receives and deserializes. Answers happen in the same way.
First, let's assume the message class are defined both on server and client.
Problem is that Gson::fromJson
function needs a .class/type object for deserializing via introspection (understandably), but in my application, multiple type of objects can be received without knowing the .class in advance.
My idea was to create a message wrapper like this:
class MessageWrapper {
public class MessageWrapper(Object message, MessageType type) {
this.message = message;
this.type = type;
}
// getters...
public enum MesssageType {
PLACEMENT,
UPDATE,
// ...
}
private final Object message;
private final MessageType type;
}
Or even go further by determining type
param with introspection. This solution is great for serializing (I repeat, that is not a problem), but while deserializing I would get the message type and loose the message itself, at least if I don't parse it twice. Specializing MessageWrapper through Java "templating" mechanism brings us back to the original problem (I would have multiple classes to choose from).
Another idea, was to send a token to identify the message, before the JSON string, like:
Placement={"foo": 2, "bar": "baz"}
Then read the token to determine the .class type. This could work, but there is still a problem: how would I return the value from my receive
function? Of course I could do:
public Object receive(Reader stream) {}
And force the user to do a downcast, but I'd rather avoid it.
EDIT: this is because the client has a reactor-like structure: it runs in a loop and dispatches messages to appropriate handlers.
Upvotes: 2
Views: 1351
Reputation: 18751
Using Gson, if you have a reasonable number of possible messages, you could create a class containing all of them (something similar to which @Enrichman wrote, but you don't need to check for nulls...). For example if you have the class
public class Response {
private Placement placement;
private Update update;
//more message types
//getters & setters
}
Then you can deserialize your response with:
Gson gson = new Gson();
Response response = gson.fromJson(jsonString, Response.class);
And it would deserialize this JSON:
{"placement": {...} }
and this:
{"update": {...} }
and this:
{"placement": {...}, "update": {...} }
Gson will ignore all the fields in the JSON response that don't correspond to any attribute in your class, so you can use a single class to deserialize multiple responses...
Upvotes: 3
Reputation: 11337
EDIT:
Ok, now it's clearer.
What about having a Wrapper with a series of defined Objects? How many handlers do you have?
I mean something like:
class HandlerWrapper {
private final Placement placement;
private final Update update;
}
then the client will deserialize this and check for the not-null property:
{"placement":{"foo": 2, "bar": "baz"}, "update":null, ...}
I knwo it's not very nice but I cannot think about something else.. : /
OLD
I don't think this is actually a problem, because you can say in your specification what kind of object you have to expect from that specific case.
For example, if you're calling an API to get a User, you will expect a User.class in the Object. The same for an API to get a Book (or whatelse).
(I hope I understood the question)
Upvotes: 3