2017-12-22 104 views
5

Tôi nhận được một mô hình dữ liệu JSON có trình bao bọc bản đồ Bảng. Tôi đang cố gắng sử dụng generics để vượt qua trong các loại đó là vượt quá wrapper nhưng nó không dịch tốt tại thời gian chạy. Dưới đây là ví dụ về tệp JSON của tôi:Kotlin Gson Deserializing

{ 
"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 
    } 
    ] 
} 

Lớp trình bao bọc mà tôi đang sử dụng được gọi là Bảng.

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

Lớp mô hình thực tế là PaymentMethod.

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

Tôi đã tạo lớp quản lý dữ liệu chung có loại < T>. Tôi nghĩ rằng lớp con sử dụng của người quản lý dữ liệu để bản địa hoá đầu vào và kết quả (như tuyên bố model class PAYMENTMETHOD.

open class NXDataManager<T>(manager: NXNetworkManager? = null, rpc : String?, parameters: List<Pair<String, String>>? = null, method : String = "get") 
{ 
    ... 


open fun sendRequest(completionHandler: (models:Array<T>) -> Unit, errorHandler: (error:FuelError) -> Unit) { 

    val request = NXNetworkRequest(rpc, parameters, method) 

    request.send(manager, completionHandler = { s: String -> 

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

     completionHandler(table.models) 

    }, errorHandler = errorHandler) 
} 

inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type) 

} 

quản lý dữ liệu subclassed tôi xác định mô hình để phân tích thành.

final public class PaymentMethodsDataManager : NXDataManager<PaymentMethod> 
{ 
    constructor() : super("genGetPaymentMethods") 

} 

Khi tôi chạy mã dưới dạng:

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

Tôi nhận được thông báo lỗi java.lang.ClassCastExceptio n: java.lang.Object [] không thể truyền sang Networking.PaymentMethod []. Tuy nhiên, khi tôi chuyển một loại rõ ràng, nó hoạt động như mong đợi - phân tích mảng thành các mô hình PaymentMethod:

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

Bất kỳ ý tưởng nào về cách tôi vẫn có thể sử dụng loại T chung?

Trả lời

4

liệu Class:

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

để JSON:

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

từ JSON:

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

tôi đã không thể sử dụng Bảng :: class.java, vì bảng cần phải xác định nó generic loại Bảng :: class.java. Nhưng điều đó ném một lỗi bởi vì tôi đoán trình biên dịch không thể nói những gì T là lúc biên dịch thời gian (không phải là loại điểm của generics ở nơi đầu tiên?). –

3

Phương pháp fromJson là chung chung, vì vậy khi bạn gọi nó cho Table<T> biến nó tạo ra Array<Any> phù hợp nhất. Bạn cần lưu ý rằng lớp học PaymentMethod mở rộng T chung chung, nhưng tôi không biết là nó thậm chí có thể. Nếu bạn tìm hiểu cách thực hiện, hãy sử dụng một cái gì đó như sau:

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

Trong trường hợp của bạn, tôi đang sử dụng bộ điều hợp gson.chức năng sau đây tạo ra đối tượng với quy định type tham số:

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

Để sử dụng nó viết cái gì đó như sau:

val table: Table<T> = getObjectFromString(Table<PaymentMethod>::class.java, s) as Table<PaymentMethod> 

Cập nhật

Để tránh tùng lớp diễn viên bạn có thể sử dụng reified hàm tổng quát:

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

Trong trường hợp đó sử dụng sẽ dễ dàng hơn:

val table: Table<T> = getObjectFromString<Table<PaymentMethod>>(s) 

tôi đã sử dụng giải pháp đầu tiên trong trường hợp tôi không biết những gì loại đối tượng sẽ là - Tôi đã có chỉ Type biến với thông tin về đối tượng đó.

2

java.lang.ClassCastException: java.lang.Object [] không thể được đúc để Networking.PaymentMethod []

JSON của bạn là

{ 
"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 
    } 
    ] 
} 

Tạo một data class, PaymentMethod.

Chúng tôi thường xuyên tạo các lớp có mục đích chính là giữ dữ liệu. Trong một lớp như vậy, một số chức năng tiêu chuẩn và chức năng tiện ích là thường có thể lấy được dữ liệu từ dữ liệu.

data class PaymentMethod(@SerializedName("Table") val table:ArrayList<PaymentData>) 
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 
         ) 

Bạn có thể gọi theo cách này

val paymentDATA = Gson().fromJson<PaymentMethod>("JSON_RESPONSE", PaymentMethod::class.java) 
    val _adapterPaymentHistory = paymentDATA.table 
Các vấn đề liên quan