Kristian
Kristian

Reputation: 1388

Pass DataType of the Class

I have the following data class, which stores two values, JSON and dataType:

data class DataTypeItem(
    var json     : String = "",
    var dataType : Class<*> ?= null
)

I have the list defined in the following way:

val dataTypeList = mutableMapOf<String, DataTypeItem>()

dataTypeList.put( "item_1", DataTypeItem( json1, MyDataType::class.java ) )
dataTypeList.put( "item_2", DataTypeItem( json1, List<MyDataType>::class.java ) )

Please note that in one case I'm using the MyDataType as the DataType and in the other List < MyDataType >.

Now I would like to loop through each of the dataTypeList items and parse JSON for the given data type into it's model:

fun init()
{
    dataTypeList.forEach {
        dataTypeItem ->
            val model = Gson().fromJson( dataTypeItem.value.json, dataTypeItem.value.dataType::class.java )
    }
}

I'm using the following model:

data class dataTypeItem(
    @SerializedName("sqlId")
    val sqlId: String,
    @SerializedName("name")
    val name: String
)

But I keep getting an Runtime exception:

Attempted to deserialize a java.lang.Class. Forgot to register a type adapter?

In addition, in case it's a list, I need to call toList() on Gson().fromJSON(..):

fun init()
{
    dataTypeList.forEach {
        dataTypeItem ->
            val model;

            if( dataTypeItem.value.dataType::class.java is Array )
                model = Gson().fromJson( dataTypeItem.value.json, dataTypeItem.value.dataType::class.java ).toList()
            else
                model = Gson().fromJson( dataTypeItem.value.json, dataTypeItem.value.dataType::class.java )
    }
}

How can I pass the dataType dynamically and distinguish if it's a List/Array or straight up class? In addition, whenever I try to call toList(), I get an error that it's undefined.

If I specify the class directly, then it's working fine

 var model = Gson().fromJson( json, DataTypeItem::class.java )

or

 var model = Gson().fromJson( json, Array<DataTypeItem>::class.java )

but I need to be able to specify it dynamically as an argument

Upvotes: 1

Views: 122

Answers (1)

goedi
goedi

Reputation: 2123

This code works fine:

val dataTypeMap = mapOf(                                                                                                                              
    "item_1" to MyDataTypeItem("""{"sqlId" : "1",  "name" : "a"}""", MyDataType::class.java),                                                           
    "item_2" to MyDataTypeItem("""[{"sqlId" : "1",  "name" : "a"}, {"sqlId" : "2",  "name" : "b"}]""", Array<MyDataType>::class.java)                  
)                                                                                                                                                     

val result = dataTypeMap.map{ Gson().fromJson(it.value.json, it.value.dataType) }                                                                                       

I renamed DataTypeItem to MyDataTypeItem and dataTypeItem to MyDataType.

Why you need to call toList()? If it is really necessary you can do the following instead:

val result = dataTypeMap.map {                                                                                           
    if (it.value.dataType?.isArray == true) Gson().fromJson<Array<*>>(it.value.json, it.value.dataType).toList()        
    else Gson().fromJson(it.value.json, it.value.dataType)                                                              
}  

Upvotes: 1

Related Questions