Kotlin Gson反序列化

我正在接收具有地图包装器的JSON数据模型。 我试图使用generics来传递超越包装的types,但它不能很好地在运行时翻译。 这里是我的JSON文件的一个例子:

{ "Table": [ { "paymentmethod_id": 1, "paymentmethod_description": "Cash", "paymentmethod_code": "Cash", "paymentmethod_is_ach_onfile": false, "paymentmethod_is_element": false, "paymentmethod_is_reward": false, "paymentmethod_is_openedgeswipe": false, "paymentmethod_update_user_id": 1, "paymentmethod_insert_user_id": 1, "paymentmethod_insertdate": "2014-10-07 14:53:16", "paymentmethod_deleted": false, "paymentmethod_is_mobile_visible": true } ] } 

我使用的包装类叫做Table。

 data class Table( @SerializedName("Table") val models : Array ) 

实际的模型类是PaymentMethod。

 data class PaymentMethod( @SerializedName("paymentmethod_id") val idNumber : Int = -1 ) 

我创建了一个通用数据管理器类,它带有types。 我想使用数据管理器的子类来本地化输入和结果(例如声明模型类PaymentMethod

 open class NXDataManager(manager: NXNetworkManager? = null, rpc : String?, parameters: List<Pair>? = null, method : String = "get") { ... open fun sendRequest(completionHandler: (models:Array) -> Unit, errorHandler: (error:FuelError) -> Unit) { val request = NXNetworkRequest(rpc, parameters, method) request.send(manager, completionHandler = { s: String -> val table: Table = Gson().fromJson(s) completionHandler(table.models) }, errorHandler = errorHandler) } inline fun  Gson.fromJson(json: String) = this.fromJson(json, object: TypeToken() {}.type) } 

我的子类数据管理器指定要解析的模型。

 final public class PaymentMethodsDataManager : NXDataManager { constructor () : super("genGetPaymentMethods") } 

当我运行代码为:

 val table: Table = Gson().fromJson(s) 

我得到一个错误消息java.lang.ClassCastException:java.lang.Object []不能转换为Networking.PaymentMethod [] 。 但是,当我传入一个显式types时,它按预期工作 – 将数组解析为PaymentMethod模型:

 val table: Table = Gson().fromJson(s) 

任何想法,我仍然可以使用genericstypesT?

数据类别:

 data class Table( @SerializedName("Table") val models : Array ) 

到JSON:

 val gson = Gson() val json = gson.toJson(table) 

来自JSON:

 val json = getJson() val table = gson.fromJson(json, Table::class.java) 

fromJson方法是通用的,所以当你调用Tablevariables时,它会创建Array为最合适的。 您需要注意的是, PaymentMethod类扩展了Tgenerics,但我不知道它甚至是可能的。 如果你发现如何做到这一点,请使用如下所示的内容:

 val table: Table = Gson().fromJson>(s) 

在你的情况,我使用gson适配器。 以下函数使用指定的type参数创建对象:

 fun getObjectFromString(type: Type, string: String) = Gson().getAdapter(TypeToken.get(type)).fromJson(string) 

要使用它写下面的东西:

 val table: Table = getObjectFromString(Table::class.java, s) as Table 

更新

为了避免空闲类的强制转换,可以使用泛化函数:

 inline fun  getObjectFromString(string: String): T = getGsonConverter().getAdapter(TypeToken.get(T::class.java)).fromJson(string)!! 

在这种情况下使用会更容易:

 val table: Table = getObjectFromString>(s) 

在我不知道对象是什么types的情况下,我使用了第一种解决方案 – 我只有Typevariables与关于该对象的信息。

java.lang.ClassCastException:java.lang.Object []不能转换为Networking.PaymentMethod []

你的JSON是

 { "Table": [ { "paymentmethod_id": 1, "paymentmethod_description": "Cash", "paymentmethod_code": "Cash", "paymentmethod_is_ach_onfile": false, "paymentmethod_is_element": false, "paymentmethod_is_reward": false, "paymentmethod_is_openedgeswipe": false, "paymentmethod_update_user_id": 1, "paymentmethod_insert_user_id": 1, "paymentmethod_insertdate": "2014-10-07 14:53:16", "paymentmethod_deleted": false, "paymentmethod_is_mobile_visible": true } ] } 

创建一个data class PaymentMethod

我们经常创建主要目的是保存数据的类。 在这样的类中,一些标准的function和实用function通常是从数据中机械地导出的。

 data class PaymentMethod(@SerializedName("Table") val table:ArrayList ) data class PaymentData ( @SerializedName("paymentmethod_id") val paymentmethod_id: Int, @SerializedName("paymentmethod_description") val paymentmethod_description: String, @SerializedName("paymentmethod_code") val paymentmethod_code:String, @SerializedName("paymentmethod_is_ach_onfile") val paidStatus:Boolean, @SerializedName("paymentmethod_is_element") val paymentmethod_is_element:Boolean, @SerializedName("paymentmethod_is_reward") val paymentmethod_is_reward:Boolean, @SerializedName("paymentmethod_is_openedgeswipe") val paymentmethod_is_openedgeswipe:Boolean, @SerializedName("paymentmethod_update_user_id") val paymentmethod_update_user_id:Int, @SerializedName("paymentmethod_insert_user_id") val paymentmethod_insert_user_id:Int, @SerializedName("paymentmethod_insertdate") val paymentmethod_insertdate:String, @SerializedName("paymentmethod_deleted") val paymentmethod_deleted:Boolean), @SerializedName("paymentmethod_is_mobile_visible") val paymentmethod_is_mobile_visible:Boolean ) 

你可以这样调用

  val paymentDATA = Gson().fromJson("JSON_RESPONSE", PaymentMethod::class.java) val _adapterPaymentHistory = paymentDATA.table