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

时间:2015-07-02 13:17:56

标签: java json gson kotlin

我对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)

我已经尝试过创建一个序列化器&amp;用于Event-class的反序列化器,并通过registerTypeAdapter注册它,我也尝试过RuntimeTypeAdapterFactory,但是它们都不会保留解析正确类型所需的信息。

例如,RuntimeTypeAdapterFactory说: “无法反序列化Event,因为它没有定义名为type

的字段

编辑:这是“适配器”的代码,它很好地改编自另一个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()

1 个答案:

答案 0 :(得分:1)

你不能这样做。

您所指的示例并不针对您的案例。它只适用于一种情况:如果注册基类型(不是类型层次结构)并使用gson.toJson(obj, javaClass<Event>())序列化。除了为事件容器对象编写自定义序列化程序之外,它永远不会用于数组

通常你需要另一种方法:使用TypeAdapterFactory和委托适配器:GSON: serialize/deserialize object of class, that have registered type hierarchy adapter, using ReflectiveTypeAdapterFactory.Adapterhttps://code.google.com/p/google-gson/issues/detail?id=43#c15

我认为这种方法过于复杂,所以如果您的类型很少,最简单的解决方案是手动,通过自定义序列化器逐个字段序列化这些类型,并忘记尝试委托默认

相关问题