将字符串匹配到对象属性

时间:2018-11-26 11:11:00

标签: kotlin

我有一组要匹配请求的策略。如果该策略存在,我想匹配请求并查看值是否匹配。

策略为List<Policies> -> (key: String, value: String),请求中可以包含不同的密钥。

示例:

策略是请求应匹配的一组规则。

class Policy {
    val key: String,
    val value: String
}

请求是一个数据类,其中包含不同的值(所有可选值),例如姓,名,地址,++++

data class Request (
  id: Long =  12,
  firstName: String = "test",
  surname: String = "test",
  address: String = "somewhere"
  ...// more fields
)

策略列表如下所示(列表):

List<Policy> => [
    {
       key: "surname",
       value: "test"
    },
        {
       key: "firstName",
       value: "test"
    }
]

我不知道如何将策略与请求匹配。 Policy.key是字符串,并且Request可以包含属性的所有不同变体。

如何将策略列表与我的数据类Request相匹配?

1 个答案:

答案 0 :(得分:1)

出于您的目的,您需要使用反射(您想按名称查找字段并获取值),或更改模型中的某些内容。

反射解决方案如下:

data class Policy(
    val key: String,
    val value: String?
)

data class Request(
        val id: Int,
        val firstName: String? = null,
        val surname: String? = null,
        val address: String? = null
)

class PolicyException : Exception()

fun checkPolicies(request: Request, policies: List<Policy>) {
    policies.forEach { policy ->
        val member = request::class.members.find { member -> member.name == policy.key }
        val requestMemberValue = member?.call(request)

        if (requestMemberValue != policy.value) throw PolicyException()
    }
}

fun main(args: Array<String>) {
    println("Hello, reflection!")
    checkPolicies(Request(id = 0, firstName = "Johnn"), listOf(Policy("firstName", "John")))
}

此外,我更改了策略模型以处理可为空的值(并且仍然正确地将“ null”作为字符串处理)。

但是,使用此解决方案时,更改模型名称必须非常小心。并且要注意不要混淆您的模型。

另外,更好的解决方案是添加Annotation(注释),该策略将策略名称保留为注释属性(然后,在应用程序中更改字段名称的问题将消失)。