Using Gson and Abstract Classes
abstract-class, gson, java, object
Solution
I finally solved it!
// GSON
GsonBuilder gsonBilder = new GsonBuilder();
gsonBilder.registerTypeAdapter(Conteudo.class, new InterfaceAdapter<Conteudo>());
gsonBilder.setPrettyPrinting();
Gson gson =gsonBilder.create();
String str2send = gson.toJson(message);
Mensagem msg_recv = gson.fromJson(str2send,Mensagem.class);
Note that: "registerTypeAdapter(AbstractClass.class, new InterfaceAdapter());"
by AbstractClass.class i mean the class that you are implementing in my case it was Conteúdo that could be ConteudoTweet or ConteudoUserSystem and so on...
The implementation of InterfaceAdapter is :
import java.lang.reflect.Type;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public class InterfaceAdapter<T>
implements JsonSerializer<T>, JsonDeserializer<T> {
@Override
public final JsonElement serialize(final T object, final Type interfaceType, final JsonSerializationContext context)
{
final JsonObject member = new JsonObject();
member.addProperty("type", object.getClass().getName());
member.add("data", context.serialize(object));
return member;
}
@Override
public final T deserialize(final JsonElement elem, final Type interfaceType, final JsonDeserializationContext context)
throws JsonParseException
{
final JsonObject member = (JsonObject) elem;
final JsonElement typeString = get(member, "type");
final JsonElement data = get(member, "data");
final Type actualType = typeForName(typeString);
return context.deserialize(data, actualType);
}
private Type typeForName(final JsonElement typeElem)
{
try
{
return Class.forName(typeElem.getAsString());
}
catch (ClassNotFoundException e)
{
throw new JsonParseException(e);
}
}
private JsonElement get(final JsonObject wrapper, final String memberName)
{
final JsonElement elem = wrapper.get(memberName);
if (elem == null)
{
throw new JsonParseException(
"no '" + memberName + "' member found in json file.");
}
return elem;
}
}
And this InterfaceAdapter is generic so it should work in general...
That's it!
Problem
I'm trying to exchange messages between a client and a server using GSON. The problem is the following: I have this structure: ``` public class Message { private TypeOfContent type; // It's a enum private Content content; .... } ``` Then the object content can be a various set of Classes. I found 2 tutorials here and here, but none of them solves the problem. Edit1: The class Message is this one: ``` public class Mensagem { private TipoMensagem type; private Conteudo conteudo; private Cliente autor; private Cliente destino; // null -> to all(broadcast) } ``` And Content is this one: ``` public class Conteudo { protected TipoConteudo typeConteudo; protected String texto; protected Posicao posicao; public Conteudo(TipoConteudo typeConteudo, String texto, Posicao posicao) { this.texto = texto; this.posicao = posicao; this.typeConteudo = typeConteudo; } } ``` And an example of a extend class from conteudo is this one: ``` public class ConteudoTweet extends Conteudo { protected String pathImagem; public ConteudoTweet(TipoConteudo typeConteudo, String tweet, Posicao location, String picturePath) { super(typeConteudo,tweet, location); this.pathImagem = picturePath; } } ``` Finally what I do is like : "String strObject = new Gson().toJson(mensage);" which works but on deserialization it doesn't because it assumes always that it is from Content class