Android, Kotlin: создание GenericTypeIndicator из отражения

Итак, я написал класс, который десериализует снимок Firebase в класс. Причина, по которой я это сделал, заключается в том, что я получаю объект String из Firebase, для которого я действительно хочу создать экземпляр другого класса. Это не поддерживается getValue, поэтому мне нужно найти обходной путь.

Теперь все работает, кроме части карты. DataSnapshot действительно хочет, чтобы в качестве аргумента был GenericTypeIndicator, но поскольку все будет выполняться динамически, я не знаю, как это сделать с помощью отражения.

Вот мой текущий код:

fun <T> deserialize(dataSnapshot: DataSnapshot, clazz: Class<T>): T {
    val obj = clazz.newInstance()

    dataSnapshot.children.forEach {
        val field = try {
            clazz.getDeclaredField(it.key)
        } catch(e: NoSuchFieldException) { return@forEach }

        field.isAccessible = true

        when(field.type){
            Translation::class.java ->
                field.set(obj, Translation(it.getValue(String::class.java)!!))
            Map::class.java -> { /* Here we need to do crazy Map GenericTypeIndicator stuff */ }
            else -> field.set(obj, it.getValue(field.type))
        }
    }

    return obj
}


Ошибка, которую я получаю при удалении корпуса карты:

Class java.util.Map has generic type parameters, please use GenericTypeIndicator instead


Если я действительно использую GenericTypeIndicator с HashMap, он выдаст мне следующую ошибку:

com.google.firebase.database.DatabaseException: Not a direct subclass of GenericTypeIndicator: class java.lang.Object

Не то чтобы я хотел сделать это таким образом, потому что в конечном итоге это должно происходить динамически.

Теперь я в растерянности, поэтому любая помощь будет принята с благодарностью, в основном потому, что карта отличается для каждого объекта, поэтому я не могу просто иметь предопределенный общий.

0
0
351
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я обнаружил, что переменная Map работает, выполнив isAssignableFrom и создав объект для GenericTypeIndicator.

Итак, единственное, что нужно было изменить, это часть when в коде на это:

when {
    field.type == Translation::class.java ->
        field.set(obj, Translation(it.getValue(String::class.java)!!))
    Map::class.java.isAssignableFrom(field.type) ->
        field.set(obj, it.getValue(object: GenericTypeIndicator<HashMap<String, Any>>(){}))
    else -> field.set(obj, it.getValue(field.type))
}

Firebase принимает только String в качестве ключей, поэтому мы можем просто сделать это фиксированным, хотя он не любит использовать нотацию * для значения, но мы можем просто сделать его Any, и, похоже, он работает нормально.

Надеюсь, это поможет другим людям, которые могут когда-либо столкнуться с этой проблемой x)

Другие вопросы по теме