java 使用 Gson 和抽象类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16000163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Gson and Abstract Classes
提问by André Carvalho
I'm trying to exchange messages between a client and a server using GSON.
我正在尝试使用 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 hereand here, but none of them solves the problem.
Edit1:
编辑1:
The class Message is this one:
Message 类是这样的:
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 contedo is this one:
来自 contedo 的扩展类的一个例子是这个:
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;
}
}
Finaly what i do is like : "String strObject = new Gson().toJson(mensage);" which works but on deserialization it doesnt because it assumes always that it is from Content class
最后我所做的是:“String strObject = new Gson().toJson(mensage);” 它有效,但在反序列化时它不起作用,因为它始终假定它来自 Content 类
回答by André Carvalho
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());"
注意:“registerTypeAdapter( AbstractClass.class, new InterfaceAdapter());”
by AbstractClass.classi mean the class that you are implementing in my case it was Conteúdo that could be ConteudoTweet or ConteudoUserSystem and so on...
通过AbstractClass.class我的意思是你在我的例子中实现的类是 Conteúdo,可能是 ConteudoTweet 或 ConteudoUserSystem 等等......
The implementation of InterfaceAdapteris :
InterfaceAdapter的实现是:
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...
这个 InterfaceAdapter 是通用的,所以它应该可以正常工作......
That's it!
而已!
回答by rpax
You should take a look on a similar question I've answered here : https://stackoverflow.com/a/22081826/3315914
你应该看看我在这里回答的类似问题:https: //stackoverflow.com/a/22081826/3315914
You need to use Gson's RuntimeTypeAdapterFactory
你需要使用Gson 的 RuntimeTypeAdapterFactory
And register the base class and all child classes to make it work.
并注册基类和所有子类以使其工作。