[英]Kotlin reflection
With Retrofit
, I am fetching data and getting JSONObject
with the structure like this for example:使用Retrofit
,我正在获取数据并获取具有如下结构的JSONObject
,例如:
{
"token": "some-token",
"tiles": [
{
"id": "id-1",
"type": "RedTile",
"title": "This red title",
"stuff": "hello world"
},
{
"id": "id-2",
"type": "BlueTile",
"title": "This blue title",
"value": 200
}
]
}
Now, when I get this response, I need to make a parser that will actually take the type from every tile and match it with the class that already exists inside application.现在,当我收到此响应时,我需要创建一个解析器,它实际上会从每个图块中获取类型,并将其与应用程序中已经存在的类匹配。 I need to basically from this response to create new one with token and tiles list but in this case tiles will reflect to actual class in app.我基本上需要从这个响应中创建一个带有令牌和图块列表的新响应,但在这种情况下,图块将反映到应用程序中的实际类。
Any idea what is proper way to do it?!知道什么是正确的方法吗?
I don't know what your classes look like, but suppose it's this for example:我不知道您的课程是什么样的,但假设是这样的:
sealed interface Tile
data class RedTile(val title: String, val stuff: String) : Tile
data class BlueTile(val title: String, val value: Int) : Tile
Then you could make this as response object然后你可以把它作为响应对象
data class Response (
val token: String,
val tiles: List<TileResponse>
) {
fun getTilesObjects() = tiles.mapNotNull { it.toTile() }
}
data class TileResponse (
val id: String,
val type: String,
val title: String,
val stuff: String? = null,
val value: Int? = null
){
fun toTile() : Tile? {
if (type == "RedTile" && stuff != null) return RedTile(title, stuff)
if (type == "BlueTile" && value != null) return BlueTile(title, value)
return null
}
}
And then you can call toTile()
on the individual TileResponse
objects or get the full list by doing getTilesObjects()
on the response object然后您可以在各个TileResponse
对象上调用toTile()
或通过对响应对象执行getTilesObjects()
来获取完整列表
Because you mention Reflection in your question's title:因为您在问题的标题中提到了反射:
import kotlin.reflect.full.declaredMemberProperties
data class TileResponse(val id: String, val type: String, val title: String, val stuff: String? = null, val value: Int? = null)
data class Response(val token: String, val tiles: List<Tile>)
sealed interface Tile
data class RedTile(val title: String, val stuff: String) : Tile
data class BlueTile(val title: String, val value: Int) : Tile
fun getTiles(): List<Tile> {
return tileResponses
.filter { tileResponse -> mapTypeToClass.containsKey(tileResponse.type) }
.map { tileResponse ->
val clazz = mapTypeToClass[tileResponse.type]!!
val constructor = clazz.constructors.first()
val declaredMemberProperties = tileResponse::class.declaredMemberProperties
val fields = constructor.parameters.map { parameter ->
parameter to declaredMemberProperties.first { it.name == parameter.name }
}
val arguments = fields.associate { (parameter, property) ->
parameter to property.call(tileResponse)
}
constructor.callBy(arguments)
}
}
val tileResponses = listOf(
TileResponse("id-1", "RedTile", "This red title", "hello world", null),
TileResponse("id-2", "BlueTile", "This blue title", "null", 200)
)
val mapTypeToClass = mapOf(
"RedTile" to RedTile::class,
"BlueTile" to BlueTile::class,
)
val response = Response("some-token", getTiles())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.