首页 > 解决方案 > Kotlin 委托对象映射

问题描述

我正在尝试将地图创建到这样的 kotlin 类中:

class RegisterThingPostBody(inputBody: Map<String, Any>) {
  val device: Device by inputBody
  val thing: Thing by inputBody

  class Device(inputBody: Map<String, Any>) {
    val serialnumber: String by inputBody
    val securityCode : String by inputBody
  }

  class Thing(inputBody: Map<String, Any>) {
    val name: String by inputBody
    val location: Location by inputBody

    class Location(inputBody: Map<String, Any>) {
        val street: String by inputBody
        val city: String by inputBody
        val state: String by inputBody
        val lat: Double by inputBody
        val lon: Double by inputBody
    }
  }
}

但我确实得到了ClassCastException对象(事物、设备位置)的信息,这是可以理解的。我可以按照下面的方法解决它,但它不如上面的那么整洁。而且我必须重复两次变量名。

class RegisterThingPostBody(inputBody: Map<String, Any>) {
  val device = Device(inputBody["device"] as Map<String, Any>)
  val thing = Thing(inputBody["thing"] as Map<String, Any>)

  class Device(inputBody: Map<String, Any>) {
    val serialnumber: String by inputBody
    val securityCode : String by inputBody
  }

  class Thing(inputBody: Map<String, Any>) {
    val name: String by inputBody
    val location = Location(inputBody["location"] as Map<String, Any>)

    class Location(inputBody: Map<String, Any>) {
        val street: String by inputBody
        val city: String by inputBody
        val state: String by inputBody
        val lat: Double by inputBody
        val lon: Double by inputBody
    }
  }
}

有没有很好的方法来解决这个问题?

标签: kotlin

解决方案


以下内容未经测试(因为您没有提供带有 sample 的完整示例inputBody)并对构造函数做出一些假设:

import kotlin.reflect.*
import kotlin.reflect.jvm.*

class CreatorMapWrap<T: Any>(val map: Map<String, Any>) {
    operator fun getValue(thisRef: Any?, property: KProperty<*>) = property.returnType.jvmErasure.constructors.first().call(map[property.name] as Map<String, Any>) as T
}


class RegisterThingPostBody(inputBody: Map<String, Any>) {
  val device: Device by CreatorMapWrap(inputBody)
  val thing: Thing by CreatorMapWrap(inputBody)

  class Device(inputBody: Map<String, Any>) {
    val serialnumber: String by inputBody
    val securityCode : String by inputBody
  }

  class Thing(inputBody: Map<String, Any>) {
    val name: String by inputBody
    val location: Location by CreatorMapWrap(inputBody)

    class Location(inputBody: Map<String, Any>) {
        val street: String by inputBody
        val city: String by inputBody
        val state: String by inputBody
        val lat: Double by inputBody
        val lon: Double by inputBody
    }
  }
}

推荐阅读