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

Gson无法反序列化自身生成的JSON字符串?Kotlin数据类HashMap问题

问题原因

Gson 默认处理 Map 的自定义类型 Key 时,不会把 Key 对象序列化为 JSON 对象,而是直接调用对象的 toString() 方法生成字符串作为 JSON 的 Key。你生成的 JSON 里,Key 是 Picture 实例的字符串表示(比如 Picture(image_url=...)),反序列化时 Gson 尝试把这个字符串解析成 Picture 对象,自然会抛出 Expected BEGIN_OBJECT but was STRING 异常——因为它期待的是 {...} 格式的 JSON 对象,结果拿到的是普通字符串。

解决方案

方案1:自定义 TypeAdapter + 开启复杂 Map Key 序列化

给 Picture 类写一个自定义的 TypeAdapter,让 Gson 把 Key 序列化为结构化的 JSON 字符串,反序列化时再把这个字符串转回 Picture 对象,同时要开启 Gson 的复杂 Map Key 序列化支持:

首先定义你的 Picture 数据类(示例):

data class Picture(
    val image_url: String,
    val creator_name: String,
    val creator_address: String,
    val image_name: String,
    val additional_url: String
)

然后编写 TypeAdapter:

class PictureKeyTypeAdapter : TypeAdapter<Picture>() {
    private val internalGson = Gson()

    override fun write(writer: JsonWriter, picture: Picture) {
        // 将Picture转为JSON字符串作为Key,Gson会自动处理转义
        val pictureJson = internalGson.toJson(picture)
        writer.value(pictureJson)
    }

    override fun read(reader: JsonReader): Picture {
        // 读取Key对应的JSON字符串,再转回Picture对象
        val pictureJson = reader.nextString()
        return internalGson.fromJson(pictureJson, Picture::class.java)
    }
}

创建 Gson 实例时注册适配器并开启复杂 Key 序列化:

val gson = GsonBuilder()
    .registerTypeAdapter(Picture::class.java, PictureKeyTypeAdapter())
    .enableComplexMapKeySerialization()
    .create()

用这个 Gson 实例序列化/反序列化你的 HashMap<Picture, String>,就能正常工作了。

方案2:将 Map 转为 List 处理

如果不想写自定义适配器,可以把 HashMap 转成 List<Pair<Picture, String>>,Gson 对这种结构的序列化和反序列化支持更友好:

// 序列化
val map = HashMap<Picture, String>()
// ... 填充map数据
val list = map.toList()
val json = gson.toJson(list)

// 反序列化
val type = object : TypeToken<List<Pair<Picture, String>>>() {}.type
val list = gson.fromJson<List<Pair<Picture, String>>>(json, type)
val restoredMap = list.toMap()

方案3:改用唯一字符串作为 Map Key

如果 Picture 里有唯一标识字段(比如 image_url),可以直接用这个字符串作为 Map 的 Key,完全避开自定义对象作为 Key 的问题:

val map = HashMap<String, String>()
map[picture.image_url] = yourBase64String
// 序列化和反序列化都能正常工作,无需额外配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 18:05:38