在Kotlin中使用Moshi解析Map<String, Double>报错:意外原始类型double
Map<String, Double>时的IllegalArgumentException问题 首先直接给结论:是的,Moshi确实不支持直接用原始类型(比如double/float)作为泛型参数来构造适配器,这正是你遇到报错的核心原因。
问题根源
你用Double::class.java传入Types.newParameterizedType时,这个Class对象对应的是Java的原始类型double,而非装箱类型Double。虽然Kotlin里我们写Double时默认是装箱类型,但::class.java在Kotlin中对于基本数据类型会返回原始类型的Class(比如Double::class.java → double.class,Double::class.javaObjectType才是真正的Double.class)。
Moshi的设计比Gson更严格,它严格遵循Java/Kotlin泛型的规则——泛型参数不能是原始类型,所以会抛出这个IllegalArgumentException提示你使用装箱类型。而Gson内部做了隐式的兼容转换,所以之前用Gson时没遇到这个问题。
两种解决方案
方案一:手动指定装箱类型的Class
把Double::class.java替换为Double::class.javaObjectType,明确告诉Moshi使用装箱类型:
val moshi = Moshi.Builder().build() val type = Types.newParameterizedType(Map::class.java, String::class.java, Double::class.javaObjectType) val adapter = moshi.adapter<Map<String, Double>>(type) val result = adapter.fromJson(InitData.json)
同理,如果是Float类型,就用Float::class.javaObjectType。
方案二:利用Kotlin的reified类型参数(更推荐)
因为你已经引入了moshi-kotlin依赖,它提供了inline扩展函数moshi.adapter<T>(),可以自动处理正确的类型推导,不需要手动构造ParameterizedType:
val moshi = Moshi.Builder().build() val adapter = moshi.adapter<Map<String, Double>>() val result = adapter.fromJson(InitData.json)
这种方式不仅代码更简洁,还能避免手动构造类型时容易犯的原始类型/装箱类型混淆的错误,是Kotlin环境下使用Moshi的最佳实践。
版本说明
你当前使用的1.8.0版本的这个行为是符合Moshi设计原则的,后续版本也保持了这个严格性,所以不管升级到哪个Moshi版本,都需要遵循这个规则。
内容的提问来源于stack exchange,提问作者Flo We

