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

密封类自定义JsonSerializer失效:序列化方法未被调用

问题解决:Gson序列化密封类列表时自定义Serializer未被调用

问题原因

序列化List<Parent>时,列表内元素的实际类型是Child1、Child2这类Parent的子类。Gson的registerTypeAdapter(Parent::class.java, ...)仅会严格匹配Parent类型的对象,对子类实例不会触发该自定义序列化器,而是使用Gson默认的子类序列化逻辑,导致serialize方法未被调用。而反序列化时,由于明确指定了List<Parent>类型,Gson会匹配注册的Parent反序列化器,所以deserialize方法能正常执行。

解决方案

使用registerTypeHierarchyAdapter替代registerTypeAdapter,该方法会对指定类及其所有子类统一应用序列化/反序列化器。

修改后的测试代码

@Test
fun check() {
    val list = listOf(Parent.Child1("first"), Parent.Child2("second"))
    
    val gson = GsonBuilder()
        .registerTypeHierarchyAdapter(Parent::class.java, ParentSerializer())
        .create()

    val jsonString = gson.toJson(list)
    println(jsonString) // 此时serialize方法会被正常调用

    val type = object : TypeToken<List<Parent>>() {}.type
    val deserializedList = gson.fromJson<List<Parent>>(jsonString, type)
    assertThat(deserializedList).isEqualTo(list) 
}

修复序列化方法的递归问题

原序列化代码中context.serialize(src)会再次触发当前序列化器,导致无限递归,需指定父类类型避免递归:

override fun serialize(src: Parent, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
    val jsonObject = JsonObject()
    jsonObject.addProperty(CLASSNAME, src.javaClass.name)
    // 指定序列化类型为Parent::class.java,避免递归调用当前序列化器
    jsonObject.add(DATA, context.serialize(src, Parent::class.java))
    return jsonObject
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:57:17