【发布时间】:2026-01-12 17:15:02
【问题描述】:
我正在使用 Kotlin 解析 JSON。例如,我有一个国家/地区的代表:{"code":"US", "name":"United States of America"}。要从这样的JSONObject 生成Country 对象,我有这个功能:
val produceCountry = fun (js: JSONObject) =
Country(js.getString("code"), js.getString("name"))
我可以使用这个函数轻松解析Country 的数组。但是,除了Country 的数组之外,我还有Cat、Car、Cart、CordlessPhone 等的数组。每个都有自己的produce* 函数将JSONObject 转换为Kotlin 对象那种。为了概括数组解析,我有这个函数:
fun <T> produceSetOf(array: JSONArray, element: (JSONObject) -> T): Set<T> {
val set = mutableSetOf<T>()
for (i in 0 until array.length())
set.add(element(array.getJSONObject(i)))
return set
}
所以我可以在遇到元素类型为Country 的数组时调用produceSetOf(jsonArray, produceCountry)。这也适用于Cat、Car、Cart、CordlessPhone 的数组。
当我看到一个字符串数组时,问题就出现了。而不是array.getJSONObject(i),我必须使用array.getString(i)。实际上,我正在考虑向上面的函数引入另一种参数化类型,并让它以不同的方式进行调用:
fun <S,T> produceSetOf(array: JSONArray, element: (S) -> T): Set<T> {
val set = mutableSetOf<T>()
for (i in 0 until array.length()) {
when (S) {
is String ->
set.add(element(array.getString(i)))
is JSONObject ->
set.add(element(array.getJSONObject(i)))
}
}
return set
}
当然,Kotlin 不允许我这样做。有什么建议我可以在保持produceSetOf() 的通用性的同时不引入另一层抽象(例如元素迭代器,或将索引转换为字符串/JSONObject 的函数)吗?
谢谢。
【问题讨论】:
-
您可以为此使用 reifeid 类型参数。见kotlinlang.org/docs/reference/…。在您的情况下,我将添加
inline和reified关键字,然后在您的 when 中检查S::class。 -
可能还值得一提*.com/a/45952201/5335131
-
@AndreasVolkmann,谢谢。
inline和reified完成这项工作,除非它现在抱怨(is String)关于Incompatible types: String and KClass<S>。如果我将S::class.java放入when,则投诉将转向Incompatible types: String and Class<S>。在这两种情况下,is JSONObject行都不会提出投诉。任何线索为什么会这样?再次感谢。 -
使用
when (S::class)String::class而不是is String
标签: arrays json kotlin higher-order-functions