I'm trying to write a custom JsonSerializer for a sealed class but the serialize method is not being called. For simplicity, I created a sample sealed class
sealed class Parent {
data class Child1(val name: String): Parent()
data class Child2(val name: String): Parent()
}
and then created a JsonSerializer for this like this:
class ParentSerializer : JsonSerializer<Parent>, JsonDeserializer<Parent> {
companion object {
const val CLASSNAME = "CLASSNAME"
const val DATA = "DATA"
}
override fun serialize(src: Parent, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
val jsonObject = JsonObject()
jsonObject.addProperty(CLASSNAME, src.javaClass.name)
jsonObject.add(DATA, context.serialize(src))
return jsonObject
}
override fun deserialize(jsonElement: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Parent {
val jsonObject = jsonElement.asJsonObject
val className = jsonObject.get(CLASSNAME) as JsonPrimitive
val objectClass = Class.forName(className.asString)
return context.deserialize(jsonObject.get(DATA), objectClass)
}
}
and I tried serializing a list using this, but the serialize method is not called, but interestingly enough deserialize method is getting called(though it's currently erroring out that it's not able to find CLASSNAME, since serialize wasn't called first).
I created a test for this
@Test
fun check() {
val list = listOf(Parent.Child1("first"), Parent.Child2("second"))
val gson = GsonBuilder()
.registerTypeAdapter(Parent::class.java, ParentSerializer())
.create()
val jsonString = gson.toJson(list)
println(jsonString) // here serialize isn't called
val type = object : TypeToken<List<Parent>>() {}.type
val deserializedList = gson.fromJson<List<Parent>>(jsonString, type) // here deserialize is called correctly
assertThat(deserializedList).isEqualTo(list)
}