使用 Gson 和抽象类 [英] Using Gson and Abstract Classes

查看:24
本文介绍了使用 Gson 和抽象类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆