klaxon icon indicating copy to clipboard operation
klaxon copied to clipboard

Polymorphic field serialization uses the converter based on the declared field type, not the type of the field value

Open Woodz opened this issue 3 years ago • 0 comments

abstract class Animal

class Dog : Animal(val favouritePark: String)

class Cat : Animal(val favouriteWindow: String)

data class PetStore(val cutestAnimal: Animal) 

class DogConverter: Converter {
    override fun canConvert(cls: Class<*>): Boolean = cls == Dog::class.java
    override fun fromJson(jv: JsonValue): Any? = TODO("Not yet implemented")
    override fun toJson(value: Any): String = "Dog!"
}

class CatConverter: Converter {
    override fun canConvert(cls: Class<*>): Boolean = cls == Cat::class.java
    override fun fromJson(jv: JsonValue): Any? = TODO("Not yet implemented")
    override fun toJson(value: Any): String = "Cat!"
}

val petStore = PetStore(Dog("Central"))
val klaxon = Klaxon().converter(DogConverter()).converter(CatConverter())
klaxon.toJsonString(petStore)

Expected: {"cutestAnimal": "Dog!"} Actual: {"cutestAnimal": {}}

From examine the code, it looks like the declare class type of the property takes precedence over the class of the actual value: https://github.com/cbeust/klaxon/blob/master/klaxon/src/main/kotlin/com/beust/klaxon/Klaxon.kt#L265

val toConvert = prop?.returnType?.javaType as? Class<*> ?: cls

I don't think this is the best approach as for polymorphic types, typically the specialized converter should be used

Woodz avatar Nov 11 '20 10:11 Woodz