所以我编写了一个将Firebase快照反序列化为类的类。我这样做的原因是因为我从Firebase获取了一个String对象,我实际上想要实例化一个不同的类。 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
}
我删除Map案例时遇到的错误是:
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)
我通过执行isAssignableFrom检测Map变量,并为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,它似乎工作正常。 / p>
我希望这可以帮助其他可能遇到过这个问题的人x)