首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Gson和Abstract类

使用Gson和Abstract类
EN

Stack Overflow用户
提问于 2013-04-14 22:30:54
回答 3查看 14.5K关注 0票数 10

我正在尝试使用GSON在客户端和服务器之间交换消息。

问题如下:

我有这样的结构:

代码语言:javascript
复制
public class Message 
{
    private TypeOfContent type; //  It's a enum 
    private Content       content;
    ....
}

那么对象内容可以是各种类的集合。

我找到了两个教程herehere,但是他们都没有解决这个问题。

Edit1:

类消息是这样的:

代码语言:javascript
复制
public class Mensagem
{
    private TipoMensagem    type;

    private Conteudo        conteudo;

    private Cliente         autor;
    private Cliente         destino;    // null -> to all(broadcast)
}

内容是这样的:

代码语言:javascript
复制
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;
    }    
} 

来自conteudo的扩展类的示例如下所示:

代码语言:javascript
复制
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;
    }
}

最后,我所做的类似于:"String strObject = new Gson().toJson(mensage);“这个方法可以工作,但在反序列化时就不行了,因为它总是假定它来自Content类

EN

回答 3

Stack Overflow用户

发布于 2013-04-15 23:11:12

我终于解决了!

代码语言:javascript
复制
    // 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);

注意:"registerTypeAdapter(AbstractClass.class,InterfaceAdapter());“

我说的AbstractClass.class是指你在我的例子中实现的类,它可以是ConteudoTweet或ConteudoUserSystem等等。

InterfaceAdapter的实现是:

代码语言:javascript
复制
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;
    }

}

而且这个InterfaceAdapter是通用的,所以它应该在一般情况下工作...

就这样!

票数 10
EN

Stack Overflow用户

发布于 2014-02-28 15:53:19

你应该看看我在这里回答的一个类似的问题:https://stackoverflow.com/a/22081826/3315914

您需要使用Gson's RuntimeTypeAdapterFactory

并注册基类和所有子类以使其工作。

票数 1
EN

Stack Overflow用户

发布于 2020-07-04 14:17:41

这是我对Sub类型序列化的看法。(github repo here)

代码语言:javascript
复制
// GsonSerializer.java
package com.rathnas.main;

import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
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;
import com.rathnas.vo.Thing;
import com.rathnas.vo.sub.Animal;
import com.rathnas.vo.sub.Bird;
import com.rathnas.vo.sub.nested.Barking;
import com.rathnas.vo.sub.nested.Chirping;
import com.rathnas.vo.sub.nested.NoiseType;

public class GsonSerializer {
    public static void main(String[] args) {
        GsonBuilder builder = new GsonBuilder().registerTypeAdapter(Thing.class, new ThingSerializer<Thing>()).registerTypeAdapter(NoiseType.class, new ThingSerializer<NoiseType>());
        builder.setPrettyPrinting();
        Gson gson = builder.create();
        Animal thing = God.createDog();
        String tmp = gson.toJson(thing, Thing.class); // Note: StackoverflowError, if you do gson.toJson(thing)
        System.out.println("Ser Dog: " + tmp);
        System.out.println("Des Dog: " + gson.fromJson(tmp, Thing.class));
        Bird thing2 = God.createBird();
        tmp = gson.toJson(thing2, Thing.class);
        System.out.println("\n\n\nSer Bird: " + tmp);
        System.out.println("Des Bird: " + gson.fromJson(tmp, Thing.class));
    }
}

class ThingSerializer<T> implements JsonSerializer<T>, JsonDeserializer<T> {
    private static final String TYPE = "type";

    public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObj = json.getAsJsonObject();
        String className = jsonObj.get(TYPE).getAsString();
        try {
            return context.deserialize(json, Class.forName(className));
        } catch (ClassNotFoundException e) {
            throw new JsonParseException(e);
        }
    }
    public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
        JsonElement jsonEle = context.serialize(src, src.getClass());
        jsonEle.getAsJsonObject().addProperty(TYPE, src.getClass().getCanonicalName());
        return jsonEle;
    }
}

class God {
    public static Animal createDog() {
        Animal thing = new Animal();
        thing.setName("Dog");
        thing.setLegs(4);
        thing.setWings(0);
        thing.setNoise(new Barking());
        return thing;
    }
    public static Bird createBird() {
        Bird thing = new Bird();
        thing.setName("Bird");
        thing.setLegs(1);
        thing.setWings(2);
        thing.setNoise(new Chirping());
        return thing;
    }
}
// Thing.java
public abstract class Thing {
    private String name;
    private NoiseType noise;
    ..
}

// Animal.java
public class Animal extends Thing implements iThing {
    private Integer legs;
    private Integer wings;
    ..
}
// Bird.java
public class Bird extends Thing implements iThing {
    private Integer legs;
    private Integer wings;
    ..
}
// NoiseType.java
public abstract class NoiseType {..}
// Chirping.java
public class Chirping extends NoiseType {..}
// Barking.java
public class Barking extends NoiseType {..}

输出

代码语言:javascript
复制
Ser Dog: {
  "legs": 4,
  "wings": 0,
  "name": "Dog",
  "noise": {
    "noise": "barking",
    "type": "com.rathnas.vo.sub.nested.Barking"
  },
  "type": "com.rathnas.vo.sub.Animal"
}
Des Dog: Animal [legs=4, wings=0, noise=NestedAbstractClass [noise=barking]]

Ser Bird: {
  "legs": 1,
  "wings": 2,
  "name": "Bird",
  "noise": {
    "noise": "chirping",
    "type": "com.rathnas.vo.sub.nested.Chirping"
  },
  "type": "com.rathnas.vo.sub.Bird"
}
Des Bird: Bird [legs=1, wings=2, noise=NestedAbstractClass [noise=chirping]]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16000163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档