密封类自定义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
相关产品推荐
相关产品推荐

