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

在Kotlin中使用Moshi解析Map<String, Double>报错:意外原始类型double

解决Moshi解析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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:45:49