2015-07-02 55 views
0

我對Gson和Json很新。我有簡單的事件,我想在Gson的幫助下通過Json序列化。Gson和序列化繼承對象的ArrayList

注意:代碼在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) 

而且unpersisting:

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() 
+0

我想創建一個自定義的反序列化器是要走的路。你能發表你寫的代碼嗎? – rciovati

+0

@RiccardoCiovati嗨,我添加了一些代碼。在序列化事件中沒有任何問題..但是,正如我所說的,當我反序列化時,信息根本就不存在(我打印了一個反序列化的Move事件,並且它只有Point數據爲「from」和「to」)(我也有Point-class的自定義序列化程序) – fluxi

+0

傻了。我沒有註冊適用於子類的類型適配器,但只針對Event-class,這是問題所在。但是,現在我在線上有一個StackOverflowError:'val elem = context !!。serialize(src)'。任何想法可能會導致這種情況? – fluxi

回答

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

我認爲這種方法過於複雜,所以如果你有幾種類型最簡單的解決方案是兩個手動序列化這些類型,通過自定義序列化器逐個字段並忘記嘗試委派給默認值

+0

感謝您的回答。我通過手動序列化類型來解決它,併爲每個類型分別設置一個單獨的ArrayList。 – fluxi