gpt4 book ai didi

java - gson 的多态性

转载 作者:IT老高 更新时间:2023-10-28 11:32:31 31 4
gpt4 key购买 nike

我在使用 Gson 反序列化 json 字符串时遇到问题。我收到一系列命令。该命令可以是 start、stop 或其他类型的命令。自然我有多态性,启动/停止命令继承自命令。

如何使用 gson 将其序列化回正确的命令对象?

似乎我只得到基本类型,即声明的类型,而不是运行时类型。

最佳答案

这有点晚了,但我今天必须做同样的事情。所以,根据我的研究,在使用 gson-2.0 时,你真的不想使用 registerTypeHierarchyAdapter 方法,而是更普通的 registerTypeAdapter。而且您当然不需要为派生类做 instanceofs 或编写适配器:基类或接口(interface)只需一个适配器,当然前提是您对派生类的默认序列化感到满意.无论如何,这是代码(已删除包和导入)(也可在 github 中找到):

基类(在我的例子中是接口(interface)):

public interface IAnimal { public String sound(); }

两个派生类,Cat:

public class Cat implements IAnimal {

public String name;

public Cat(String name) {
super();
this.name = name;
}

@Override
public String sound() {
return name + " : \"meaow\"";
};
}

还有狗:

public class Dog implements IAnimal {

public String name;
public int ferocity;

public Dog(String name, int ferocity) {
super();
this.name = name;
this.ferocity = ferocity;
}

@Override
public String sound() {
return name + " : \"bark\" (ferocity level:" + ferocity + ")";
}
}

IAnimalAdapter:

public class IAnimalAdapter implements JsonSerializer<IAnimal>, JsonDeserializer<IAnimal>{

private static final String CLASSNAME = "CLASSNAME";
private static final String INSTANCE = "INSTANCE";

@Override
public JsonElement serialize(IAnimal src, Type typeOfSrc,
JsonSerializationContext context) {

JsonObject retValue = new JsonObject();
String className = src.getClass().getName();
retValue.addProperty(CLASSNAME, className);
JsonElement elem = context.serialize(src);
retValue.add(INSTANCE, elem);
return retValue;
}

@Override
public IAnimal deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME);
String className = prim.getAsString();

Class<?> klass = null;
try {
klass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new JsonParseException(e.getMessage());
}
return context.deserialize(jsonObject.get(INSTANCE), klass);
}
}

还有测试类:

public class Test {

public static void main(String[] args) {
IAnimal animals[] = new IAnimal[]{new Cat("Kitty"), new Dog("Brutus", 5)};
Gson gsonExt = null;
{
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(IAnimal.class, new IAnimalAdapter());
gsonExt = builder.create();
}
for (IAnimal animal : animals) {
String animalJson = gsonExt.toJson(animal, IAnimal.class);
System.out.println("serialized with the custom serializer:" + animalJson);
IAnimal animal2 = gsonExt.fromJson(animalJson, IAnimal.class);
System.out.println(animal2.sound());
}
}
}

当您运行 Test::main 时,您会得到以下输出:

serialized with the custom serializer:
{"CLASSNAME":"com.synelixis.caches.viz.json.playground.plainAdapter.Cat","INSTANCE":{"name":"Kitty"}}
Kitty : "meaow"
serialized with the custom serializer:
{"CLASSNAME":"com.synelixis.caches.viz.json.playground.plainAdapter.Dog","INSTANCE":{"name":"Brutus","ferocity":5}}
Brutus : "bark" (ferocity level:5)

我实际上也使用 registerTypeHierarchyAdapter 方法完成了上述操作,但这似乎需要实现自定义 DogAdapter 和 CatAdapter 序列化器/反序列化器类,这在您想要添加另一个时很难维护字段为 Dog 或 Cat。

关于java - gson 的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5800433/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com