2017-12-22 119 views
5

मुझे एक JSON डेटा मॉडल प्राप्त हो रहा है जिसमें नक्शा रैपर तालिका है। मैं जेनरिक्स का उपयोग उस प्रकार से गुजरने के लिए कर रहा हूं जो रैपर से बाहर है लेकिन यह रनटाइम पर अच्छी तरह से अनुवाद नहीं कर रहा है। यहाँ मेरी JSON फ़ाइल का एक उदाहरण है:कोटलिन जीसन 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 
    } 
    ] 
} 

आवरण वर्ग मैं उपयोग कर रहा हूँ तालिका कहा जाता है।

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

वास्तविक मॉडल वर्ग PaymentMethod है।

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

मैंने एक जेनेरिक डेटा मैनेजर क्लास बनाया है जो < टी> प्रकार लेता है। मैं डेटा प्रबंधक के उपयोग उपवर्गों इनपुट और इस तरह के मॉडल वर्ग 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) 

} 

मेरे subclassed डेटा प्रबंधक मॉडल में पार्स करने के लिए निर्दिष्ट करता है।

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

} 

जब मैं के रूप में कोड चलाएँ:

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

मैंने एक त्रुटि संदेश java.lang.ClassCastExceptio मिल n: java.lang.Object [] को नेटवर्किंग में नहीं डाला जा सकता है। भुगतान विधि []। हालांकि, जब मैं एक स्पष्ट प्रकार में पारित यह उम्मीद के रूप में काम करता है - PAYMENTMETHOD मॉडल में सरणी को पार्स:

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

कैसे मैं अभी भी सामान्य प्रकार टी का उपयोग कर सकते की कोई भी विचार?

उत्तर

4

डाटा कक्षा:

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

JSON करने के लिए:

val gson = Gson() 
val json = gson.toJson(table) 
JSON से

:

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

मैं टेबल :: class.java उपयोग करने के लिए सक्षम नहीं था कह सकते हैं। लेकिन यह एक त्रुटि फेंकता है क्योंकि मैं अनुमान लगा रहा हूं कि कंपाइलर यह नहीं बता सकता कि टी संकलन समय पर क्या है (जेनरिक्स के उस बिंदु की पहली जगह नहीं है?)। –

3

विधि fromJson सामान्य है, इसलिए जब आप Table<T> चर के लिए इसे कहते यह Array<Any> बनाता है सबसे उपयुक्त के रूप में। आपको नोटिस करना होगा कि PaymentMethod कक्षा T सामान्य है, लेकिन मुझे नहीं पता कि यह भी संभव है। यदि आपको पता चलता है कि इसे कैसे बनाया जाए, तो निम्न का उपयोग करें:

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

आपके मामले में मैं जीसन एडाप्टर का उपयोग कर रहा हूं।समारोह के बाद निर्दिष्ट type पैरामीटर के साथ ऑब्जेक्ट बनाएगी:

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

यह कुछ निम्नलिखित लिखने का उपयोग करें:

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

अद्यतन

अतिरिक्त वर्ग डाली से बचने के लिए आप reified सामान्य समारोह का उपयोग कर सकते हैं:

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

उस मामले में का उपयोग कर आसान होगा:

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

मैं ऐसे मामलों में जहां मैं क्या टाइप वस्तु होगा पता नहीं है में पहली समाधान इस्तेमाल किया - मुझे लगता है कि वस्तु के बारे में जानकारी के साथ ही Type चर मिल गया है।

2

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

हम अक्सर कक्षाएं बनाते हैं जिनके मुख्य उद्देश्य डेटा धारण करना है। में ऐसी कक्षा कुछ मानक कार्यक्षमता और उपयोगिता फ़ंक्शन अक्सर यांत्रिक रूप से डेटा से व्युत्पन्न होते हैं।

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 
         ) 

आप क्योंकि तालिका इसके जेनेरिक प्रकार टेबल :: class.java निर्दिष्ट करने के लिए की जरूरत है, इस तरह से

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