You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用kotlin-reflect读取JSON生成匿名对象的动态属性如何实现?

问题分析与解决方案

现有代码的核心问题

  • 变量引用错误:let 块的参数默认名为 it,你代码中直接使用未定义的 res 变量引用反序列化得到的对象,运行时会直接报错。
  • 反序列化类型选择错误:调用 asObject(Any::class.java) 时,绝大多数JSON解析库会将JSON对象反序列化为Map类型(而非自定义类实例),Map本身的Kotlin成员属性不包含JSON的键名,通过反射查找成员属性自然找不到对应结果。
  • 反射调用参数错误:KProperty的getter.call仅需要传入实例对象本身作为唯一参数,你额外传入了属性名参数,会触发参数数量不匹配的反射调用异常。
  • 不必要的类型校验:你只过滤KMutableProperty<*>类型的属性,不可变属性会被直接排除,哪怕属性存在也会被过滤掉。

正确实现方案

方案1:优先转Map读取(无需反射,性能更高)

绝大多数场景下反序列化为Any的JSON对象本质是Map,直接强转后读取对应键即可:

val decodedToken = JWT(jwtString)
decodedToken.getClaim("useful_claim").asObject(Any::class.java)?.let { claimObj ->
    // 直接转Map读取,无需反射
    (claimObj as? Map<*, *>)?.get(BuildConfig.VARIABLE_NAME)?.let { value ->
        (value as? List<*>)?.filterIsInstance<MyClass>()?.let {
            return it
        }
    }
}

方案2:反射读取(仅适用于反序列化结果为自定义类实例的场景)

如果确认反序列化得到的是带成员属性的Kotlin类实例,正确的反射写法如下:

val decodedToken = JWT(jwtString)
decodedToken.getClaim("useful_claim").asObject(Any::class.java)?.let { instance ->
    // 查找对应名称的属性
    val reflectProp = instance::class.memberProperties.find { it.name == BuildConfig.VARIABLE_NAME }
    reflectProp?.let { prop ->
        // 调用getter仅传入实例本身即可
        (prop.getter.call(instance) as? List<*>)?.filterIsInstance<MyClass>()?.let {
            return it
        }
    }
}

内容的提问来源于stack exchange,提问作者Cédric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 13:27:05