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

为何Gson的fromJson需用TypeToken?两种Kotlin实现可行性分析

DTO转领域层的Gson映射函数问题解答

两种Kotlin内联泛型扩展实现

实现一(使用TypeToken)

inline fun <reified DTO_TYPE, reified TYPE> DTO_TYPE.toDomainLayer(): TYPE {
    val gson = Gson()
    val strJson = gson.toJson(this)
    val type = object: TypeToken<TYPE>() {}.type
    return gson.fromJson(strJson, type)
}

实现二(直接用TYPE::class.java)

inline fun <reified DTO_TYPE, reified TYPE> DTO_TYPE.toDomainLayer(): TYPE {
    val gson = Gson()
    val strJson = gson.toJson(this)
    return gson.fromJson(strJson, TYPE::class.java)
}

实现二的可用范围

实现二在目标类型TYPE是无泛型参数的普通类时可以正常工作,比如将UserDTO映射到普通数据类User,此时TYPE::class.java能提供足够的类型信息让Gson完成解析。

实现二的失效场景

当TYPE包含泛型参数时,实现二会因为丢失泛型信息而解析失败,典型场景包括:

  • 泛型集合类:比如List<User>、Map<String, Order>。TYPE::class.java只能得到List.class或Map.class,无法获取泛型参数User、Order的类型,Gson会把集合元素解析成默认的LinkedTreeMap,后续类型转换时会抛出异常。
  • 自定义泛型类:比如ApiResult<Data>这类自定义泛型容器。ApiResult::class.java无法携带Data的类型信息,Gson无法正确解析泛型字段,导致目标对象的泛型属性类型错误。

为什么需要TypeToken?

Java和Kotlin都存在泛型类型擦除:编译时泛型信息会被抹除,运行时无法直接获取泛型参数的具体类型。而TypeToken通过创建匿名子类的方式,在编译阶段把完整的泛型类型(包括泛型参数)保留在子类的Class信息中,Gson通过反射读取这个Type对象,就能准确识别目标类型的泛型结构,从而正确解析JSON到带泛型的目标对象中。

内容的提问来源于stack exchange,提问作者Parth Malaviya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:28:24