使用 Gson 和抽象类 [英] Using Gson and Abstract Classes
问题描述
我正在尝试使用 GSON 在客户端和服务器之间交换消息.
问题如下:
我有这个结构:
公共类消息{私有 TypeOfContent 类型;//这是一个枚举私人内容内容;....}
那么对象内容可以是各种类的集合.
编辑 1:
类消息是这样的:
公共类 Mensagem{私人 TipoMensagem 类型;私人 Conteudo conteudo;私人委托人;私人客户目的地;//空 ->对所有人(广播)}
内容是这样的:
公共类 Conteudo{受保护的 TipoConteudo 类型 Conteudo;受保护的字符串文本;受保护的 Posicao posicao;public Conteudo(TipoConteudo typeConteudo, String texto, Posicao posicao){this.texto = texto;this.posicao = posicao;this.typeConteudo = typeConteudo;}}
来自 conteudo 的扩展类的一个例子是这个:
公共类 ConteudoTweet 扩展 Conteudo{受保护的字符串路径图像;public ConteudoTweet(TipoConteudo typeConteudo, String tweet, Posicao location, String picturePath){超级(类型Conteudo,推文,位置);this.pathImagem = 图片路径;}}
最后我要做的是:String strObject = new Gson().toJson(mensage);"它有效,但在反序列化时无效,因为它始终假定它来自 Content 类
我终于解决了!
//GSONGsonBuilder gsonBilder = new GsonBuilder();gsonBilder.registerTypeAdapter(Conteudo.class, new InterfaceAdapter());gsonBilder.setPrettyPrinting();gson gson =gsonBilder.create();String str2send = gson.toJson(message);Mensagem msg_recv = gson.fromJson(str2send,Mensagem.class);
注意:registerTypeAdapter(AbstractClass.class, new InterfaceAdapter());"
通过 AbstractClass.class 我的意思是你在我的例子中实现的类是 Conteúdo,可能是 ConteudoTweet 或 ConteudoUserSystem 等等......
InterfaceAdapter 的实现是:
import java.lang.reflect.Type;导入 com.google.gson.JsonDeserializationContext;导入 com.google.gson.JsonDeserializer;导入 com.google.gson.JsonElement;导入 com.google.gson.JsonObject;导入 com.google.gson.JsonParseException;导入 com.google.gson.JsonSerializationContext;导入 com.google.gson.JsonSerializer;公共类 InterfaceAdapter实现 JsonSerializer、JsonDeserializer;{@覆盖public final JsonElement serialize(final T object, final Type interfaceType, final JsonSerializationContext context){最终的 JsonObject 成员 = new JsonObject();member.addProperty("type", object.getClass().getName());member.add("data", context.serialize(object));回归会员;}@覆盖public final T deserialize(final JsonElement elem, final Type interfaceType, final JsonDeserializationContext context)抛出 JsonParseException{最终的 JsonObject 成员 = (JsonObject) elem;final JsonElement typeString = get(member, "type");final JsonElement data = get(member, "data");final Type actualType = typeForName(typeString);返回 context.deserialize(data, actualType);}私有类型 typeForName(final JsonElement typeElem){尝试{返回 Class.forName(typeElem.getAsString());}捕获(ClassNotFoundException e){抛出新的 JsonParseException(e);}}private JsonElement get(final JsonObject wrapper, final String memberName){final JsonElement elem = wrapper.get(memberName);如果(元素 == 空){抛出新的 JsonParseException("没有 '" + memberName + "' 在 json 文件中找到的成员.");}返回元素;}}
这个 InterfaceAdapter 是通用的,所以它应该可以正常工作......
就是这样!
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
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!
这篇关于使用 Gson 和抽象类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!