Gson和序列化具有继承性的对象的ArrayList

我对Gson和Json很新。 我有简单的事件,我想在Gson的帮助下通过Json序列化。

注意:代码在Kotlin。

public abstract class Event() { } public class Move : Event() { var from: Point? = null var to: Point? = null } public class Fire : Event() { var damage: Int = 0 var area: ArrayList<Point> = ArrayList(0) } public class Build : Event() { var to: Point? = null var type: String = "" var owner: String = "" } 

我坚持通过这种方式一堆:

 val list: ArrayList<Event>() = ArrayList() list.add(move) list.add(fire) val str = gson.toJson(events) 

而不是:

 val type = object : TypeToken<ArrayList<Event>>(){}.getType() val eventStr = obj.getString("events") val events: ArrayList<Event> = gson.fromJson(eventStr, type) 

我已经尝试创建一个事件类的序列化器和反序列化器,并通过registerTypeAdapter注册,并且我也尝试了RuntimeTypeAdapterFactory,但是都不会持久化所需的信息来执行正确的类型。

例如,RuntimeTypeAdapterFactory说:“不能反序列化事件,因为它没有定义一个名为类型的字段”

编辑 :这是“适配器”,这是..以及从另一个StackOverflow帖子改编的代码:

 public class Adapter : JsonSerializer<Event>, JsonDeserializer<Event> { final val CLASSNAME = "CLASSNAME" final val INSTANCE = "INSTANCE" override fun serialize(src: Event?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement? { val obj = JsonObject() val className = (src as Event).javaClass.getCanonicalName() obj.addProperty(CLASSNAME, className) val elem = context!!.serialize(src) obj.add(INSTANCE, elem) return obj } override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Event? { val jsonObject = json!!.getAsJsonObject() val prim = jsonObject.get(CLASSNAME) val className = prim.getAsString() val klass = Class.forName(className) return context!!.deserialize(jsonObject.get(INSTANCE), klass) } } 

此代码失败,并在线上发生NullPointerException:

 val className = prim.getAsString() 

你不能这样做。

你所指的例子并不针对你的情况。 它只在一种情况下工作:如果你注册基类型(不是类型层次结构)并使用gson.toJson(obj, javaClass<Event>())序列化。 它不会为数组工作,除非您为您的事件容器对象编写自定义序列化程序

通常,您需要另一种方法:使用TypeAdapterFactory和委托适配器: GSON:使用ReflectiveTypeAdapterFactory.Adapter和https://code.google.com/p/google-gson/issues 对具有注册类型层次结构适配器的类的对象进行序列化/反序列化 /细节?ID = 43个#C15

我相信这种方法是过于复杂,所以如果你有几个类型,最简单的解决方案是两个手动序列化这些类型,通过自定义序列化器逐字段和忘记尝试委派给默认