Kotlin委托对象映射

时间:2019-01-20 13:36:44

标签: 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
    }
  }
}

有解决这个问题的好方法吗?

1 个答案:

答案 0 :(得分:2)

以下内容未经测试(因为您没有提供示例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
    }
  }
}