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

使用Gson转换HashMap<LocalDate,Int>与JSON:反向转换失败原因

问题原因解析

你遇到的问题核心在于JSON对象的键只能是字符串,而Gson默认没有内置逻辑,能把JSON里的日期字符串键自动转换成LocalDate类型。

当序列化Map<LocalDate, Int>时,Gson会自动把LocalDate转为字符串形式(比如"2024-01-01")作为JSON对象的键;但反序列化时,Gson会尝试直接把这个字符串键当成LocalDate实例解析——而LocalDate并非字符串类型,Gson默认的反序列化器不知道如何将字符串转换为LocalDate作为Map的键,因此抛出Expected BEGIN_OBJECT but was STRING异常(它原本期望解析一个LocalDate的JSON对象,结果拿到的是字符串)。

解决方法

方法1:注册Java 8日期适配器(推荐)

如果项目使用Java 8+日期API,Gson提供了专门的扩展库处理这类类型:

  1. 引入Gradle依赖:
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.google.code.gson:gson-javatype-adapters:2.10.1'
  1. 创建带适配器的Gson实例:
val gson = GsonBuilder()
    .registerTypeAdapter(LocalDate::class.java, LocalDateTypeAdapter())
    .create()

用这个gson实例即可完成Map<LocalDate, Int>的双向序列化/反序列化。

方法2:自定义TypeAdapter处理Map键转换

若不想引入额外依赖,可自行编写适配器处理LocalDate键的解析:

class LocalDateMapKeyAdapter : TypeAdapter<LocalDate>() {
    override fun write(out: JsonWriter, value: LocalDate?) {
        value?.let { out.value(it.toString()) }
    }

    override fun read(`in`: JsonReader): LocalDate {
        return LocalDate.parse(`in`.nextString())
    }
}

注册到GsonBuilder:

val gson = GsonBuilder()
    .registerTypeAdapter(LocalDate::class.java, LocalDateMapKeyAdapter())
    .create()

这样Gson反序列化Map键时,会通过适配器将字符串转为LocalDate。

关于你的替代方案

你手动遍历JSON对象的键,自行调用LocalDate.parse(key)完成字符串到LocalDate的转换,本质上是替Gson完成了它默认未实现的键类型转换工作,因此可以正常运行。

内容的提问来源于stack exchange,提问作者android developer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:57:34