我试图使用GSON在客户端和服务器之间交换消息。
问题如下:
我有这样的结构:
public class Message
{
private TypeOfContent type; // It's a enum
private Content content;
....
}
然后,对象内容可以是一组不同的类。
我在这里和这里找到了两个教程,但没有一个能解决这个问题。
编辑1:
public class Mensagem
{
private TipoMensagem type;
private Conteudo conteudo;
private Cliente autor;
private Cliente destino; // null -> to all(broadcast)
}
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;
}
}
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);”它可以工作,但在反序列化上不行,因为它总是假定它来自内容类
这是我对子类型序列化的看法。(
// 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 {..}
输出
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]]
你应该看看我在这里回答的类似问题:https://stackoverflow.com/a/22081826/3315914
您需要使用Gson的RuntimeTypeAdapterFactory
并注册基类和所有子类以使其工作。
我终于解决了!
// 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,new InterfaceAdapter())
通过抽象课堂。我的意思是,在我的例子中,你正在实现的类可以是ConteudoTweet或ConteudoUserSystem等等。。。
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;
}
}
这个InterfaceAdapter是通用的,所以它应该在一般情况下工作。。。
就这样!
问题内容: 假设有一个 抽象 类say 和两个非抽象子类say 和。我想通过使用GSON库从json格式“反序列化”它们。 例如,我得到一个对象数组。 有人将其转换为JSON字符串,如下所示: 最后,如果我尝试如下反序列化 那么我就遇到了一个错误,因为GSON默认的反序列化器找到了一个抽象类(即),并且它无法猜测子类的类型。 我该如何解决? PS:我阅读了有关自定义反序列化器的信息,但在这种情况下
假设有一个抽象类,例如和两个非抽象子类,例如和。我想使用GSON库从json格式“反序列化”它们。 例如。我得到一个对象的数组。 有人将其转换为JSON字符串,如下所示: 最后,如果我尝试反序列化如下 然后我有一个错误,因为GSON默认反序列化器找到一个抽象类(即)并且它无法猜测子类类型。 我如何解决这个问题? PS:我读过关于自定义反序列化器的文章,但我不明白如何在这种情况下使用它们。
我有以下类层次结构 改装日志: 但是当我在请求参数中发布事件实例时,只有抽象类被序列化。 改型Java接口: 我还注意到,在第二种情况下,字段序列化名称是,但它应该是!这使我认为改型对使用的与对参数使用的不同... 分级依赖关系 REST客户端
我想读关于抽象的文章,但读到不同的文章,我感到很困惑。 下面是我无法理解的问题: 1)“抽象是通过使用抽象类和接口实现的吗?”我对此进行了搜索,得到了三种类型的答案: 与此处解释的不同。 它们是相同的,只是不同的观点,就像这里解释的。 最后一个是抽象类用来实现抽象。 哪一个是真的?请举一个简单的例子。 2)“抽象意味着隐藏不必要的细节。比如专注于一个对象做什么而不是它是如何完成的。” 这是正确的吗
问题内容: 我是一名 Java 开发人员,对Object Orientation概念有很好的了解( 或者也许我这样认为 )。现在我正在学习设计模式(从头开始设计模式)。我一直在阅读有关OOPS概念抽象的文章,以简要地理解它,而阅读更多有关它的内容,使我比以前更加困惑。 据我了解,抽象是指隐藏程序的内部细节,同时将接口暴露给其他程序员,而无需担心内部细节。但是我不明白 抽象类如何适应这种抽象概念,其
也许我跑错了方向,但我有一个元素列表,我想读。 我有一个抽象基类,让我们称之为: 现在我有两个可能的实现: