So, I'm trying to set a property of a data class after compile time. I'm attempting to use bracket notation, but the IDE is barking at me with the following: No set method providing array access
.
I did a little research, and it looks like I need to use the Reflection api. Tried using memberProperties
, but after identifying the property there's no setter
method on it. So, I'm here hoping to find some guidance.
Here's a contrived example of what I'm trying to do:
data class EmailMessageStats(
var bounce: Int = 0,
var click: Int = 0,
var deferred: Int = 0,
var delivered: Int = 0,
var dropped: Int = 0,
var open: Int = 0,
var processed: Int = 0,
var spamreport: Int = 0
)
val sampleResponseFromDatabase = listOf(
mapOf("type" to "bounce", "value" to 148),
mapOf("type" to "click", "value" to 142),
mapOf("type" to "deferred", "value" to 286),
mapOf("type" to "delivered", "value" to 700),
mapOf("type" to "dropped", "value" to 152),
mapOf("type" to "open", "value" to 550),
mapOf("type" to "processed", "value" to 1000),
mapOf("type" to "spamreport", "value" to 140)
)
var summary = EmailMessageStats()
for (row in sampleResponseFromDatabase) {
val type = row["type"] // e.g. bounce
val value = row["value"] //e.g. 148
summary[type] = value
}
println(summary)
I made a Kotlin extension function just for that functionality:
fun Any.setPropertyValue(propName: String, value: Any) {
for (prop in this::class.declaredMemberProperties) {
if (prop.name == propName) {
(prop as? KMutableProperty<*>)?.setter?.call(this, value)
}
}
}
Similarly for getting the property value:
fun Any.getPropertyValue(propName: String): Any? {
for (prop in this::class.declaredMemberProperties) {
if (prop.name == propName) return prop.getter.call(this)
}
return null
}
Here, you can set the property as follows:
var summary = EmailMessageStats()
for (row in sampleResponseFromDatabase) {
val type = row["type"] // e.g. bounce
val value = row["value"] //e.g. 148
summary.setPropertyValue(type, value)
}
Keep in mind to use declaredMemberProperties
if you only want the fields related to EmailMessageStats
. Otherwise, if EmailMessageStats
were to extend from another object, it will iterate through that object's fields too.
I got it worked in following way:
data class Item(var name: String, var description: String?)
On runtime
val item = "Runtime item object"
val property = "name"
val value = "Updated value of name"
val jo = JsonParser().parse( Gson().toJson(item) ).asJsonObject
if(jo.has(property)) {
jo.remove(property)
jo.addProperty(property, value)
}
val item = Gson().fromJson(jo, Item::class.java)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.